diff options
229 files changed, 21299 insertions, 3108 deletions
@@ -9,7 +9,7 @@ PROG := abc MODULES := src/base/abc src/base/abci src/base/seq src/base/cmd src/base/io src/base/main \ src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/parse src/bdd/reo \ src/map/fpga src/map/pga src/map/mapper src/map/mio src/map/super \ - src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/vec \ + src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/espresso src/misc/vec \ src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr src/opt/sim \ src/sat/asat src/sat/csat src/sat/msat src/sat/fraig diff --git a/Makefile_calypto b/Makefile_calypto new file mode 100644 index 00000000..077d1926 --- /dev/null +++ b/Makefile_calypto @@ -0,0 +1,81 @@ + +CC := gcc +CXX := g++ +LD := g++ +CP := cp + +PROG := abc + +#MODULES := src/base/abc src/base/abci src/base/seq src/base/cmd src/base/io src/base/main \ +# src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/parse src/bdd/reo \ +# src/map/fpga src/map/pga src/map/mapper src/map/mio src/map/super \ +# src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/vec \ +# src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr src/opt/sim \ +# src/sat/asat src/sat/csat src/sat/msat src/sat/fraig + +MODULES := src/base/abc src/base/abci src/base/seq src/base/cmd src/base/io src/base/main \ + src/bdd/dsd src/bdd/parse src/bdd/reo \ + src/map/fpga src/map/pga src/map/mapper src/map/mio src/map/super \ + src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/espresso src/misc/vec \ + src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr src/opt/sim \ + src/sat/asat src/sat/csat src/sat/msat src/sat/fraig + +default: lib$(PROG).a + +OPTFLAGS := -DNDEBUG -O3 +#OPTFLAGS := -g + +# for linux +CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES)) + +# for solaris +#CFLAGS += -Wall $(OPTFLAGS) $(patsubst %, -I%, $(MODULES)) + +CFLAGS += -I../cudd-2.3.1/cudd -I../cudd-2.3.1/dddmp -I../cudd-2.3.1/epd -I../cudd-2.3.1/mtr -I../cudd-2.3.1/st -I../cudd-2.3.1/util +CXXFLAGS += $(CFLAGS) + +LIBS := -ldl -rdynamic +SRC := +GARBAGE := core core.* *.stackdump ./tags $(PROG) + +.PHONY: tags clean docs + +include $(patsubst %, %/module.make, $(MODULES)) + +OBJ := \ + $(patsubst %.cc, %.o, $(filter %.cc, $(SRC))) \ + $(patsubst %.c, %.o, $(filter %.c, $(SRC))) \ + $(patsubst %.y, %.o, $(filter %.y, $(SRC))) + +DEP := $(OBJ:.o=.d) + +# implicit rules + +%.d: %.c + ./depends.sh $(CC) `dirname $*.c` $(CFLAGS) $*.c > $@ + +%.d: %.cc + ./depends.sh $(CXX) `dirname $*.cc` $(CXXFLAGS) $(CFLAGS) $*.cc > $@ + +-include $(DEP) + +# Actual targets + +depend: $(DEP) + +clean: + rm -rf $(PROG) $(OBJ) $(GARBAGE) $(OBJ:.o=.d) + +tags: + ctags -R . + +$(PROG): $(OBJ) + $(LD) -o $@ $^ $(LIBS) + +lib$(PROG).a: $(OBJ) + ar rv $@ $? + ranlib $@ + +docs: + doxygen doxygen.conf + @@ -42,7 +42,7 @@ RSC=rc.exe # 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 /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # 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 /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c # SUBTRACT CPP /X # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -182,7 +182,11 @@ SOURCE=.\src\base\abci\abcBalance.c # End Source File # Begin Source File -SOURCE=.\src\base\abci\abcCollapse.c +SOURCE=.\src\base\abci\abcClpBdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcClpSop.c # End Source File # Begin Source File @@ -194,6 +198,10 @@ SOURCE=.\src\base\abci\abcDsd.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcEspresso.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcFpga.c # End Source File # Begin Source File @@ -214,6 +222,10 @@ SOURCE=.\src\base\abci\abcMiter.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcNewAig.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcNtbdd.c # End Source File # Begin Source File @@ -226,6 +238,10 @@ 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\abcReconv.c # End Source File # Begin Source File @@ -238,6 +254,10 @@ SOURCE=.\src\base\abci\abcRenode.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcRestruct.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcRewrite.c # End Source File # Begin Source File @@ -906,6 +926,14 @@ SOURCE=.\src\sat\asat\added.c # End Source File # Begin Source File +SOURCE=.\src\sat\asat\asatmem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\asat\asatmem.h +# End Source File +# Begin Source File + SOURCE=.\src\sat\asat\solver.c # End Source File # Begin Source File @@ -1134,6 +1162,10 @@ SOURCE=.\src\sat\aig\fraigTrav.c # End Source File # Begin Source File +SOURCE=.\src\sat\aig\rwrMffc.c +# End Source File +# Begin Source File + SOURCE=.\src\sat\aig\rwrTruth.c # End Source File # End Group @@ -1704,6 +1736,10 @@ SOURCE=.\src\misc\extra\extraUtilProgress.c SOURCE=.\src\misc\extra\extraUtilReader.c # End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilUtil.c +# End Source File # End Group # Begin Group "st" @@ -1725,153 +1761,289 @@ SOURCE=.\src\misc\st\stmm.c SOURCE=.\src\misc\st\stmm.h # End Source File # End Group -# Begin Group "util" +# Begin Group "mvc" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\util\cpu_stats.c +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\util\cpu_time.c +SOURCE=.\src\misc\mvc\mvcCube.c # End Source File # Begin Source File -SOURCE=.\src\misc\util\datalimit.c +SOURCE=.\src\misc\mvc\mvcDivide.c # End Source File # Begin Source File -SOURCE=.\src\misc\util\getopt.c +SOURCE=.\src\misc\mvc\mvcDivisor.c # End Source File # Begin Source File -SOURCE=.\src\misc\util\leaks.h +SOURCE=.\src\misc\mvc\mvcList.c # End Source File # Begin Source File -SOURCE=.\src\misc\util\pathsearch.c +SOURCE=.\src\misc\mvc\mvcLits.c # End Source File # Begin Source File -SOURCE=.\src\misc\util\safe_mem.c +SOURCE=.\src\misc\mvc\mvcMan.c # End Source File # Begin Source File -SOURCE=.\src\misc\util\stdlib_hack.h +SOURCE=.\src\misc\mvc\mvcOpAlg.c # End Source File # Begin Source File -SOURCE=.\src\misc\util\strsav.c +SOURCE=.\src\misc\mvc\mvcOpBool.c # End Source File # Begin Source File -SOURCE=.\src\misc\util\texpand.c +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\util\util.h +SOURCE=.\src\misc\mvc\mvcUtils.c # End Source File # End Group -# Begin Group "mvc" +# Begin Group "vec" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\mvc\mvc.c +SOURCE=.\src\misc\vec\vec.h # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvc.h +SOURCE=.\src\misc\vec\vecInt.h # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcApi.c +SOURCE=.\src\misc\vec\vecPtr.h # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcCompare.c +SOURCE=.\src\misc\vec\vecStr.h # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcContain.c +SOURCE=.\src\misc\vec\vecVec.h # End Source File +# End Group +# Begin Group "espresso" + +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\misc\mvc\mvcCover.c +SOURCE=.\src\misc\espresso\cofactor.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcCube.c +SOURCE=.\src\misc\espresso\cols.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcDivide.c +SOURCE=.\src\misc\espresso\compl.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcDivisor.c +SOURCE=.\src\misc\espresso\contain.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcList.c +SOURCE=.\src\misc\espresso\cubehack.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcLits.c +SOURCE=.\src\misc\espresso\cubestr.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcMan.c +SOURCE=.\src\misc\espresso\cvrin.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcOpAlg.c +SOURCE=.\src\misc\espresso\cvrm.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcOpBool.c +SOURCE=.\src\misc\espresso\cvrmisc.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcPrint.c +SOURCE=.\src\misc\espresso\cvrout.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcSort.c +SOURCE=.\src\misc\espresso\dominate.c # End Source File # Begin Source File -SOURCE=.\src\misc\mvc\mvcUtils.c +SOURCE=.\src\misc\espresso\equiv.c # End Source File -# End Group -# Begin Group "vec" +# Begin Source File -# PROP Default_Filter "" +SOURCE=.\src\misc\espresso\espresso.c +# End Source File # Begin Source File -SOURCE=.\src\misc\vec\vec.h +SOURCE=.\src\misc\espresso\espresso.h # End Source File # Begin Source File -SOURCE=.\src\misc\vec\vecInt.h +SOURCE=.\src\misc\espresso\essen.c # End Source File # Begin Source File -SOURCE=.\src\misc\vec\vecPtr.h +SOURCE=.\src\misc\espresso\exact.c # End Source File # Begin Source File -SOURCE=.\src\misc\vec\vecStr.h +SOURCE=.\src\misc\espresso\expand.c # End Source File # Begin Source File -SOURCE=.\src\misc\vec\vecVec.h +SOURCE=.\src\misc\espresso\gasp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\gimpel.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\globals.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\hack.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\indep.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\irred.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\map.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\matrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\opo.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\pair.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\part.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\primes.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\reduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\rows.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\set.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\setc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sharp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sminterf.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\solution.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\unate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\verify.c # End Source File # End Group -# Begin Group "npn" +# Begin Group "util" # PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\util\util_hack.h +# End Source File # End Group # End Group # End Group @@ -0,0 +1,84 @@ +# global parameters +#set check # checks intermediate networks +#set checkfio # prints warnings when fanins/fanouts are duplicated +set checkread # checks 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 + +# 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 + +# standard aliases +alias b balance +alias cl cleanup +alias clp collapse +alias esd ext_seq_dcs +alias f fraig +alias fs fraig_sweep +alias fsto fraig_store +alias fres fraig_restore +alias ft fraig_trust +alias mu renode -m +alias pex print_exdc -d +alias pf print_factor +alias pfan print_fanio +alias pl print_level +alias pio print_io +alias pk print_kmap +alias ps print_stats +alias psu print_supp +alias psy print_symm +alias pun print_unate +alias q quit +alias r read +alias ren renode +alias rl read_blif +alias rb read_bench +alias ret retime +alias rp read_pla +alias rv read_verilog +alias rsup read_super mcnc5_old.super +alias rlib read_library +alias rw rewrite +alias rwz rewrite -z +alias rf refactor +alias rfz refactor -z +alias rs restructure +alias rsz restructure -z +alias sa set autoexec ps +alias so source -x +alias st strash +alias sw sweep +alias ssw ssweep +alias scl scleanup +alias u undo +alias wb write_blif +alias wl write_blif +alias wp write_pla +alias wv write_verilog + +# standard scripts +alias opt "b; ren; b" +alias share "b; ren; fx; b" +alias sharem "b; ren -m; fx; b" +alias sharedsd "b; ren; dsd -g; sw; fx; b" +alias resyn "b; rw; rwz; b; rwz; b" +alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" +alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b" +alias compress "b; rw -l; rwz -l; b; rwz -l; b" +alias compress2 "b; rw -l; rf -l; b; rw -l; rwz -l; b; rfz -l; rwz -l; b" +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; rf -l; b -l; rw -l; rf -l" +alias t "r c/4/csat_101_opt.blif; st; ps; test" +alias t2 "r c/5/csat_026.bench; st; ps; test" +alias r1 "r c/4/csat_101_opt.blif; st; ps" + + @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir "abclib\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 /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mapp" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -64,7 +64,7 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "abclib\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 /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mapp" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -171,6 +171,10 @@ 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 @@ -187,6 +191,10 @@ SOURCE=.\src\base\abci\abcDsd.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcEspresso.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcFpga.c # End Source File # Begin Source File @@ -207,6 +215,10 @@ SOURCE=.\src\base\abci\abcMiter.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcNewAig.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcNtbdd.c # End Source File # Begin Source File @@ -219,6 +231,10 @@ 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\abcReconv.c # End Source File # Begin Source File @@ -255,6 +271,10 @@ 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 @@ -895,6 +915,14 @@ SOURCE=.\src\sat\asat\added.c # End Source File # Begin Source File +SOURCE=.\src\sat\asat\asatmem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\asat\asatmem.h +# End Source File +# Begin Source File + SOURCE=.\src\sat\asat\solver.c # End Source File # Begin Source File @@ -1519,6 +1547,10 @@ SOURCE=.\src\misc\extra\extra.h # End Source File # Begin Source File +SOURCE=.\src\misc\extra\extraBddAuto.c +# End Source File +# Begin Source File + SOURCE=.\src\misc\extra\extraBddKmap.c # End Source File # Begin Source File @@ -1531,6 +1563,10 @@ SOURCE=.\src\misc\extra\extraBddSymm.c # End Source File # Begin Source File +SOURCE=.\src\misc\extra\extraBddUnate.c +# End Source File +# Begin Source File + SOURCE=.\src\misc\extra\extraUtilBitMatrix.c # End Source File # Begin Source File @@ -1557,6 +1593,10 @@ SOURCE=.\src\misc\extra\extraUtilProgress.c SOURCE=.\src\misc\extra\extraUtilReader.c # End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilUtil.c +# End Source File # End Group # Begin Group "st" @@ -1607,6 +1647,10 @@ SOURCE=.\src\misc\util\pathsearch.c # End Source File # Begin Source File +SOURCE=.\src\misc\util\prtime.c +# End Source File +# Begin Source File + SOURCE=.\src\misc\util\safe_mem.c # End Source File # Begin Source File @@ -1726,6 +1770,190 @@ SOURCE=.\src\misc\vec\vecStr.h SOURCE=.\src\misc\vec\vecVec.h # End Source File # End Group +# Begin Group "espresso" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\espresso\cofactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cols.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\compl.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\contain.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cubehack.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cubestr.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrin.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrmisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrout.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\dominate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\equiv.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\espresso.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\espresso.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\essen.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\exact.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\expand.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\gasp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\gimpel.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\globals.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\hack.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\indep.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\irred.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\map.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\matrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\opo.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\pair.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\part.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\primes.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\reduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\rows.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\set.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\setc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sharp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sminterf.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\solution.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\unate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\util_old.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\verify.c +# End Source File +# End Group # End Group # End Group # Begin Group "Header Files" @@ -0,0 +1,10 @@ +Often the code comes directly from a Windows computer. +The following steps may be needed to compile it on UNIX: + +>> dos2unix Makefile Makefile +>> dos2unix depends.sh depends.sh +>> chmod 755 depends.sh +>> make + +If compiling as a static library, it is necessary to uncomment +#define _LIB in "src/abc/main/main.c" diff --git a/regtest.script b/regtest.script index f8a4ea17..a4461e7f 100644 --- a/regtest.script +++ b/regtest.script @@ -8,5 +8,5 @@ r examples/s444.blif; b; esd -v; dsd; cec; ps r examples/i10.blif; fpga; cec; ps; u; map; cec; ps r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps r examples/s6669.blif; fpga; ps; sec; u; sfpga; ps; sec; u; fpga; ret; ps; sec -r examples/s5378.blif; map -s; ps; sec; u; smap; ps; sec; u; map; ret; ps; sec +#r examples/s5378.blif; map -s; ps; sec; u; smap; ps; sec; u; map; ret; ps; sec time diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 7ace4880..e36f133e 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -410,6 +410,8 @@ extern bool Abc_AigCheck( Abc_Aig_t * pMan ); extern int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk ); extern Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); extern Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ); +extern 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_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); extern Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); extern Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ); @@ -425,7 +427,7 @@ extern void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ); /*=== abcAttach.c ==========================================================*/ extern int Abc_NtkAttach( Abc_Ntk_t * pNtk ); /*=== abcBalance.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective ); +extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ); /*=== abcCheck.c ==========================================================*/ extern bool Abc_NtkCheck( Abc_Ntk_t * pNtk ); extern bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk ); @@ -435,7 +437,7 @@ extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * /*=== abcCollapse.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose ); /*=== abcCut.c ==========================================================*/ -extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj ); +extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fMulti ); extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fMulti ); extern void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst ); extern void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ); @@ -559,8 +561,9 @@ extern void Abc_NtkFinalizeLatches( Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_NtkStartRead( char * pName ); extern void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAllCis ); -extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); +extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ); +extern Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ); +extern Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); extern Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); extern Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ); extern void Abc_NtkDelete( Abc_Ntk_t * pNtk ); @@ -575,6 +578,8 @@ extern void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, in extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ); extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); +/*=== abcProve.c ==========================================================*/ +extern int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, int nConfLimit, int nImpLimit, int fUseRewrite, int fUseFraig, int fVerbose ); /*=== abcReconv.c ==========================================================*/ extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); extern void Abc_NtkManCutStop( Abc_ManCut_t * p ); @@ -590,13 +595,14 @@ extern int Abc_NodeMffcSize( Abc_Obj_t * pNode ); extern int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode ); extern int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ); extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode ); -extern int Abc_NodeMffcLabelFast( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); -extern Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode ); +extern void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); +extern int Abc_NodeDeref_rec( Abc_Obj_t * pNode ); +extern int Abc_NodeRef_rec( Abc_Obj_t * pNode ); /*=== abcRenode.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple ); extern DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ); /*=== abcSat.c ==========================================================*/ -extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose ); +extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fVerbose ); extern solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk ); /*=== abcSop.c ==========================================================*/ extern char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ); @@ -681,6 +687,7 @@ extern int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDup extern void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ); extern bool Abc_NodeIsExorType( Abc_Obj_t * pNode ); extern bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ); extern Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ); extern 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 void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c index 167e7552..e5f39127 100644 --- a/src/base/abc/abcAig.c +++ b/src/base/abc/abcAig.c @@ -54,7 +54,6 @@ struct Abc_Aig_t_ 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 * vStackDelete; // the nodes to be deleted 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 @@ -83,8 +82,7 @@ static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_O 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, int fUpdateLevel ); -static void Abc_AigDelete_int( Abc_Aig_t * pMan ); +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 ); @@ -116,7 +114,6 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) pMan->pBins = ALLOC( Abc_Obj_t *, pMan->nBins ); memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); pMan->vNodes = Vec_PtrAlloc( 100 ); - pMan->vStackDelete = Vec_PtrAlloc( 100 ); pMan->vStackReplaceOld = Vec_PtrAlloc( 100 ); pMan->vStackReplaceNew = Vec_PtrAlloc( 100 ); pMan->vLevels = Vec_VecAlloc( 100 ); @@ -139,13 +136,11 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) ***********************************************************************/ void Abc_AigFree( Abc_Aig_t * pMan ) { - assert( Vec_PtrSize( pMan->vStackDelete ) == 0 ); assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 ); assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 ); // free the table Vec_VecFree( pMan->vLevels ); Vec_VecFree( pMan->vLevelsR ); - Vec_PtrFree( pMan->vStackDelete ); Vec_PtrFree( pMan->vStackReplaceOld ); Vec_PtrFree( pMan->vStackReplaceNew ); Vec_PtrFree( pMan->vNodes ); @@ -166,18 +161,21 @@ void Abc_AigFree( Abc_Aig_t * pMan ) ***********************************************************************/ int Abc_AigCleanup( Abc_Aig_t * pMan ) { + Vec_Ptr_t * vDangles; Abc_Obj_t * pAnd; - int i, Counter; + int i, nNodesOld; + nNodesOld = pMan->nEntries; // collect the AND nodes that do not fanout - assert( Vec_PtrSize( pMan->vStackDelete ) == 0 ); + vDangles = Vec_PtrAlloc( 100 ); for ( i = 0; i < pMan->nBins; i++ ) Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) if ( Abc_ObjFanoutNum(pAnd) == 0 ) - Vec_PtrPush( pMan->vStackDelete, pAnd ); + Vec_PtrPush( vDangles, pAnd ); // process the dangling nodes and their MFFCs - for ( Counter = 0; Vec_PtrSize(pMan->vStackDelete) > 0; Counter++ ) - Abc_AigDelete_int( pMan ); - return Counter; + Vec_PtrForEachEntry( vDangles, pAnd, i ) + Abc_AigDeleteNode( pMan, pAnd ); + Vec_PtrFree( vDangles ); + return nNodesOld - pMan->nEntries; } /**Function************************************************************* @@ -383,6 +381,74 @@ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) /**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 [] @@ -662,11 +728,16 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool { assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 ); assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 ); - assert( Vec_PtrSize(pMan->vStackDelete) == 0 ); Vec_PtrPush( pMan->vStackReplaceOld, pOld ); Vec_PtrPush( pMan->vStackReplaceNew, pNew ); + assert( !Abc_ObjIsComplement(pOld) ); + // process the replacements while ( Vec_PtrSize(pMan->vStackReplaceOld) ) - Abc_AigReplace_int( pMan, fUpdateLevel ); + { + pOld = Vec_PtrPop( pMan->vStackReplaceOld ); + pNew = Vec_PtrPop( pMan->vStackReplaceNew ); + Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel ); + } if ( fUpdateLevel ) { Abc_AigUpdateLevel_int( pMan ); @@ -685,14 +756,10 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool SeeAlso [] ***********************************************************************/ -void Abc_AigReplace_int( Abc_Aig_t * pMan, int fUpdateLevel ) +void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) { - Abc_Obj_t * pOld, * pNew, * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout; - int k, v, iFanin; - // get the pair of nodes to replace - assert( Vec_PtrSize(pMan->vStackReplaceOld) > 0 ); - pOld = Vec_PtrPop( pMan->vStackReplaceOld ); - pNew = Vec_PtrPop( pMan->vStackReplaceNew ); + 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) ); @@ -775,88 +842,58 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, int fUpdateLevel ) SeeAlso [] ***********************************************************************/ -void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld ) -{ - assert( Vec_PtrSize(pMan->vStackDelete) == 0 ); - Vec_PtrPush( pMan->vStackDelete, pOld ); - while ( Vec_PtrSize(pMan->vStackDelete) ) - Abc_AigDelete_int( pMan ); -} - -/**Function************************************************************* - - Synopsis [Performs internal deletion step.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigDelete_int( Abc_Aig_t * pMan ) +void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) { - Vec_Ptr_t * vNodes; - Abc_Obj_t * pRoot, * pObj; - int k; - // get the node to delete - assert( Vec_PtrSize(pMan->vStackDelete) > 0 ); - pRoot = Vec_PtrPop( pMan->vStackDelete ); + Abc_Obj_t * pNode0, * pNode1, * pTemp; + int i, k; // make sure the node is regular and dangling - assert( !Abc_ObjIsComplement(pRoot) ); - assert( Abc_ObjIsNode(pRoot) ); - assert( Abc_ObjFaninNum(pRoot) == 2 ); - assert( Abc_ObjFanoutNum(pRoot) == 0 ); - - // collect the MFFC - vNodes = Abc_NodeMffcCollect( pRoot ); - - // if reverse levels are specified, schedule fanins of MFFC for updating - // currently, we do not do it because we do not know the correct level of the fanins - // also, it is unlikely that this will make a difference since we are - // processing the network forward while at this point fanins are left behind... -/* - if ( pObj->pNtk->vLevelsR ) - Vec_PtrForEachEntry( vNodes, pObj, k ) + 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( pMan->vStackReplaceOld, pTemp, i ) + if ( pNode == pTemp ) { - Abc_Obj_t * pFanin; - if ( Abc_ObjIsCi(pObj) ) - continue; - pFanin = Abc_ObjFanin0(pObj); - if ( pFanin->fMarkB == 0 ) - { - pFanin->fMarkB = 1; - Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanin), pFanin ); - } - pFanin = Abc_ObjFanin1(pObj); - if ( pFanin->fMarkB == 0 ) + // remove the entry from the replacement array + for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ ) { - pFanin->fMarkB = 1; - Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanin), pFanin ); + pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1]; + pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1]; } + pMan->vStackReplaceOld->nSize--; + pMan->vStackReplaceNew->nSize--; } -*/ - // delete the nodes in MFFC - Vec_PtrForEachEntry( vNodes, pObj, k ) - { - if ( Abc_ObjIsCi(pObj) ) - continue; - assert( Abc_ObjFanoutNum(pObj) == 0 ); - // remove the node from the table - Abc_AigAndDelete( pMan, pObj ); - // if the node is in the level structure, remove it - if ( pObj->fMarkA ) - Abc_AigRemoveFromLevelStructure( pMan->vLevels, pObj ); - if ( pObj->fMarkB ) - Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pObj ); - // remove the node from the network - Abc_NtkDeleteObj( pObj ); - } - Vec_PtrFree( vNodes ); + // when deleting a new node that should replace another node, do not delete + Vec_PtrForEachEntry( pMan->vStackReplaceNew, pTemp, i ) + if ( pNode == Abc_ObjRegular(pTemp) ) + return; + + // remember the node's fanins + pNode0 = Abc_ObjFanin0( pNode ); + pNode1 = Abc_ObjFanin1( pNode ); + + // 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.] diff --git a/src/base/abc/abcNames.c b/src/base/abc/abcNames.c index b366890f..ccbd2c85 100644 --- a/src/base/abc/abcNames.c +++ b/src/base/abc/abcNames.c @@ -306,7 +306,7 @@ Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ) int i; vNodes = Vec_PtrAlloc( 100 ); Abc_ObjForEachFanin( pNode, pFanin, i ) - Vec_PtrPush( vNodes, util_strsav(Abc_ObjName(pFanin)) ); + Vec_PtrPush( vNodes, Extra_UtilStrsav(Abc_ObjName(pFanin)) ); return vNodes; } @@ -341,7 +341,7 @@ Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ) Buffer[1] = '0' + i/26; Buffer[2] = 0; } - Vec_PtrPush( vNames, util_strsav(Buffer) ); + Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); } return vNames; } diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 82367c09..31b4c5f4 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -117,8 +117,8 @@ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_ // start the network pNtkNew = Abc_NtkAlloc( Type, Func ); // duplicate the name and the spec - pNtkNew->pName = util_strsav(pNtk->pName); - pNtkNew->pSpec = util_strsav(pNtk->pSpec); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pCopy = NULL; @@ -235,8 +235,8 @@ Abc_Ntk_t * Abc_NtkStartRead( char * pName ) // allocate the empty network pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP ); // set the specs - pNtkNew->pName = util_strsav( Extra_FileNameGeneric(pName) ); - pNtkNew->pSpec = util_strsav( pName ); + pNtkNew->pName = Extra_FileNameGeneric(pName); + pNtkNew->pSpec = Extra_UtilStrsav(pName); return pNtkNew; } @@ -359,7 +359,7 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) /**Function************************************************************* - Synopsis [Creates the network composed of one output.] + Synopsis [Creates the network composed of one logic cone.] Description [] @@ -368,22 +368,22 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAllCis ) +Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ) { - Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin; + 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_ObjIsCo(pNode) ); + assert( Abc_ObjIsNode(pNode) ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc ); // set the name - sprintf( Buffer, "%s_%s", pNtk->pName, Abc_ObjName(pNode) ); - pNtkNew->pName = util_strsav(Buffer); + sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); // establish connection between the constant nodes Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkNew); @@ -399,7 +399,9 @@ Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAl Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) ); } } - + // add the PO corresponding to this output + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + Abc_NtkLogicStoreName( pNodeCoNew, pNodeName ); // copy the nodes Vec_PtrForEachEntry( vNodes, pObj, i ) { @@ -415,15 +417,83 @@ Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAl Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } } + // connect the internal nodes to the new CO + Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); Vec_PtrFree( vNodes ); - // add the PO corresponding to this output - pNode->pCopy = Abc_NtkCreatePo( pNtkNew ); - Abc_ObjAddFanin( pNode->pCopy, Abc_ObjFanin0(pNode)->pCopy ); - Abc_NtkLogicStoreName( pNode->pCopy, Abc_ObjName(pNode) ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + return pNtkNew; +} + +/**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 ); + // set the name + sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkNew); + + // collect the nodes in MFFC + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffsConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + // create the PIs + Vec_PtrForEachEntry( vSupp, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) ); + } + // create the PO + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + Abc_NtkLogicStoreName( pNodeCoNew, pNodeName ); + // copy the nodes + Vec_PtrForEachEntry( vCone, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj ); + 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_NtkCreateOutput(): Network check has failed.\n" ); + fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" ); return pNtkNew; } @@ -438,7 +508,7 @@ Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAl SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) +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; @@ -450,7 +520,7 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * // start the network Abc_NtkCleanCopy( pNtk ); pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); - pNtkNew->pName = util_strsav(pNtk->pName); + 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 ); @@ -483,7 +553,7 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * Abc_ObjAddFanin( pNodePo, pFinal ); Abc_NtkLogicStoreName( pNodePo, "miter" ); if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" ); return pNtkNew; } @@ -505,7 +575,7 @@ Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) int i; // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc ); - pNtkNew->pName = util_strsav(Abc_ObjName(pNode)); + pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode)); // add the PIs corresponding to the fanins of the node Abc_ObjForEachFanin( pNode, pFanin, i ) { @@ -544,7 +614,7 @@ Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) int i, nVars; // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP ); - pNtkNew->pName = util_strsav("ex"); + pNtkNew->pName = Extra_UtilStrsav("ex"); // create PIs Vec_PtrPush( pNtkNew->vObjs, NULL ); nVars = Abc_SopGetVarNum( pSop ); diff --git a/src/base/abc/abcRefs.c b/src/base/abc/abcRefs.c index 5d0c68d1..808bfae8 100644 --- a/src/base/abc/abcRefs.c +++ b/src/base/abc/abcRefs.c @@ -24,10 +24,8 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes ); -static int Abc_NodeMffcCountSupp( Vec_Ptr_t * vNodes ); +static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ); static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ); -static int Abc_NodeDeref( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -52,8 +50,8 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode ) assert( Abc_ObjIsNode( pNode ) ); if ( Abc_ObjFaninNum(pNode) == 0 ) return 0; - nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, NULL ); // dereference - nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference assert( nConeSize1 == nConeSize2 ); assert( nConeSize1 > 0 ); return nConeSize1; @@ -61,36 +59,6 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode ) /**Function************************************************************* - Synopsis [Returns the MFFC size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vNodes; - int nSuppSize, nConeSize1, nConeSize2; - assert( Abc_NtkIsStrash(pNode->pNtk) ); - assert( !Abc_ObjIsComplement( pNode ) ); - assert( Abc_ObjIsNode( pNode ) ); - if ( Abc_ObjFaninNum(pNode) == 0 ) - return 0; - vNodes = Vec_PtrAlloc( 10 ); - nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, vNodes ); // dereference - nSuppSize = Abc_NodeMffcCountSupp(vNodes); - nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference - assert( nConeSize1 == nConeSize2 ); - assert( nConeSize1 > 0 ); - Vec_PtrFree(vNodes); - return nSuppSize; -} - -/**Function************************************************************* - Synopsis [Returns the MFFC size while stopping at the complemented edges.] Description [] @@ -129,12 +97,13 @@ int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ) int Abc_NodeMffcLabel( 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, NULL ); // dereference - nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference assert( nConeSize1 == nConeSize2 ); assert( nConeSize1 > 0 ); return nConeSize1; @@ -142,88 +111,64 @@ int Abc_NodeMffcLabel( Abc_Obj_t * pNode ) /**Function************************************************************* - Synopsis [Returns the MFFC size.] + Synopsis [References/references the node and returns MFFC size.] - Description [Profiling shows that this procedure runs the same as - the above one, not faster.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_NodeMffcLabelFast( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ) { - Abc_Obj_t * pTemp; - int nConeSize, i; - - assert( !Abc_ObjIsComplement( pNode ) ); - assert( Abc_ObjIsNode( pNode ) ); - if ( Abc_ObjFaninNum(pNode) == 0 ) + Abc_Obj_t * pNode0, * pNode1; + int Counter; + // label visited nodes + if ( fLabel ) + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCi(pNode) ) return 0; - - Vec_PtrClear( vNodes ); - nConeSize = Abc_NodeDeref( pNode, vNodes ); - // label the nodes with the current ID and ref their children - Vec_PtrForEachEntry( vNodes, pTemp, i ) + // 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 { - Abc_NodeSetTravIdCurrent( pTemp ); - if ( Abc_ObjIsCi(pTemp) ) - continue; - Abc_ObjFanin0(pTemp)->vFanouts.nSize++; - Abc_ObjFanin1(pTemp)->vFanouts.nSize++; + 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 nConeSize; + return Counter; } -/**Function************************************************************* - - Synopsis [Collects the nodes in MFFC in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vNodes; - int nConeSize1, nConeSize2; - assert( !Abc_ObjIsComplement( pNode ) ); - assert( Abc_ObjIsNode( pNode ) ); - vNodes = Vec_PtrAlloc( 8 ); - if ( Abc_ObjFaninNum(pNode) == 0 ) - return vNodes; - nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, vNodes ); // dereference - nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference - assert( nConeSize1 == nConeSize2 ); - assert( nConeSize1 > 0 ); - return vNodes; -} /**Function************************************************************* Synopsis [References/references the node and returns MFFC size.] - Description [] + Description [Stops at the complemented edges.] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes ) +int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ) { Abc_Obj_t * pNode0, * pNode1; int Counter; - // label visited nodes - if ( fLabel ) - Abc_NodeSetTravIdCurrent( pNode ); - // collect visited nodes - if ( vNodes ) - Vec_PtrPush( vNodes, pNode ); // skip the CI if ( Abc_ObjIsCi(pNode) ) return 0; @@ -233,26 +178,29 @@ int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t Counter = 1; if ( fReference ) { - if ( pNode0->vFanouts.nSize++ == 0 ) - Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes ); - if ( pNode1->vFanouts.nSize++ == 0 ) - Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes ); + if ( pNode0->vFanouts.nSize++ == 0 && !Abc_ObjFaninC0(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode0, fReference ); + if ( pNode1->vFanouts.nSize++ == 0 && !Abc_ObjFaninC1(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode1, fReference ); } else { assert( pNode0->vFanouts.nSize > 0 ); assert( pNode1->vFanouts.nSize > 0 ); - if ( --pNode0->vFanouts.nSize == 0 ) - Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes ); - if ( --pNode1->vFanouts.nSize == 0 ) - Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes ); + if ( --pNode0->vFanouts.nSize == 0 && !Abc_ObjFaninC0(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode0, fReference ); + if ( --pNode1->vFanouts.nSize == 0 && !Abc_ObjFaninC1(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode1, fReference ); } return Counter; } + + + /**Function************************************************************* - Synopsis [References/references the node and returns MFFC supp size.] + Synopsis [Dereferences the node's MFFC.] Description [] @@ -261,53 +209,24 @@ int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t SeeAlso [] ***********************************************************************/ -int Abc_NodeMffcCountSupp( Vec_Ptr_t * vNodes ) +int Abc_NodeDeref_rec( Abc_Obj_t * pNode ) { - Abc_Obj_t * pNode, * pNode0, * pNode1; - int i, Counter = 0; - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_ObjIsCi(pNode) ) - { - if ( pNode->fMarkB == 0 ) - { - pNode->fMarkB = 1; - Counter++; - } - continue; - } - pNode0 = Abc_ObjFanin0(pNode); - if ( pNode0->vFanouts.nSize > 0 && pNode0->fMarkB == 0 ) - { - pNode0->fMarkB = 1; - Counter++; - } - pNode1 = Abc_ObjFanin1(pNode); - if ( pNode1->vFanouts.nSize > 0 && pNode1->fMarkB == 0 ) - { - pNode1->fMarkB = 1; - Counter++; - } - } - Vec_PtrForEachEntry( vNodes, pNode, i ) + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) { - if ( Abc_ObjIsCi(pNode) ) - { - pNode->fMarkB = 0; - continue; - } - pNode0 = Abc_ObjFanin0(pNode); - pNode0->fMarkB = 0; - pNode1 = Abc_ObjFanin1(pNode); - pNode1->fMarkB = 0; + assert( pFanin->vFanouts.nSize > 0 ); + if ( --pFanin->vFanouts.nSize == 0 ) + Counter += Abc_NodeDeref_rec( pFanin ); } return Counter; - } /**Function************************************************************* - Synopsis [References/references the node and returns MFFC size.] + Synopsis [References the node's MFFC.] Description [] @@ -316,69 +235,98 @@ int Abc_NodeMffcCountSupp( Vec_Ptr_t * vNodes ) SeeAlso [] ***********************************************************************/ -int Abc_NodeDeref( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +int Abc_NodeRef_rec( Abc_Obj_t * pNode ) { - Abc_Obj_t * pNode0, * pNode1; - int Counter; - // collect visited nodes - Vec_PtrPush( vNodes, pNode ); - // skip the CI + Abc_Obj_t * pFanin; + int i, Counter = 1; if ( Abc_ObjIsCi(pNode) ) return 0; - // process the internal node - pNode0 = Abc_ObjFanin0(pNode); - pNode1 = Abc_ObjFanin1(pNode); - assert( pNode0->vFanouts.nSize > 0 ); - assert( pNode1->vFanouts.nSize > 0 ); - Counter = 1; - if ( --pNode0->vFanouts.nSize == 0 ) - Counter += Abc_NodeDeref( pNode0, vNodes ); - if ( --pNode1->vFanouts.nSize == 0 ) - Counter += Abc_NodeDeref( pNode1, vNodes ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pFanin->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRef_rec( pFanin ); + } return Counter; } /**Function************************************************************* - Synopsis [References/references the node and returns MFFC size.] + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] - Description [Stops at the complemented edges.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ) +void Abc_NodeMffsConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost ) { - 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 ( pNode0->vFanouts.nSize++ == 0 && !Abc_ObjFaninC0(pNode) ) - Counter += Abc_NodeRefDerefStop( pNode0, fReference ); - if ( pNode1->vFanouts.nSize++ == 0 && !Abc_ObjFaninC1(pNode) ) - Counter += Abc_NodeRefDerefStop( pNode1, fReference ); - } - else + 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) ) { - assert( pNode0->vFanouts.nSize > 0 ); - assert( pNode1->vFanouts.nSize > 0 ); - if ( --pNode0->vFanouts.nSize == 0 && !Abc_ObjFaninC0(pNode) ) - Counter += Abc_NodeRefDerefStop( pNode0, fReference ); - if ( --pNode1->vFanouts.nSize == 0 && !Abc_ObjFaninC1(pNode) ) - Counter += Abc_NodeRefDerefStop( pNode1, fReference ); + Vec_PtrPush( vSupp, pNode ); + return; } - return Counter; + // recur on the children + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NodeMffsConeSupp_rec( pFanin, vCone, vSupp, 0 ); + // collect the internal node + Vec_PtrPush( vCone, pNode ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) +{ + assert( Abc_ObjIsNode(pNode) ); + assert( !Abc_ObjIsComplement(pNode) ); + Vec_PtrClear( vCone ); + Vec_PtrClear( vSupp ); + Abc_NtkIncrementTravId( pNode->pNtk ); + Abc_NodeMffsConeSupp_rec( pNode, vCone, vSupp, 1 ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vCone, * vSupp; + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffsConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + printf( "Cone = %6d. Supp = %6d. \n", Vec_PtrSize(vCone), Vec_PtrSize(vSupp) ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); } + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index 1e52e4a6..122cf589 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -28,8 +28,6 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fFanouts, bool fReference ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -605,6 +603,35 @@ bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ) /**Function************************************************************* + Synopsis [Returns 1 if the node is the control type of the MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool 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. diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 119f8cdf..d2422b64 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -62,6 +62,7 @@ static int Abc_CommandDisjoint ( 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_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -80,6 +81,7 @@ 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_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandXyz ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -110,6 +112,7 @@ static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -161,6 +164,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) 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, "Various", "logic", Abc_CommandLogic, 1 ); Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 ); @@ -171,14 +175,15 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 ); Cmd_CommandAdd( pAbc, "Various", "sat", Abc_CommandSat, 0 ); Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 ); - Cmd_CommandAdd( pAbc, "Various", "one_output", Abc_CommandOneOutput, 1 ); - Cmd_CommandAdd( pAbc, "Various", "one_node", Abc_CommandOneNode, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandOneOutput, 1 ); + Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandOneNode, 1 ); Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 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", "cut", Abc_CommandCut, 0 ); Cmd_CommandAdd( pAbc, "Various", "xyz", Abc_CommandXyz, 1 ); + Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 ); Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 ); @@ -209,6 +214,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 ); // Rwt_Man4ExploreStart(); // Map_Var3Print(); @@ -258,8 +264,8 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) // set the defaults fShort = 1; fFactor = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "sfh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sfh" ) ) != EOF ) { switch ( c ) { @@ -321,8 +327,8 @@ int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv ) // set the defaults fShort = 1; fPrintDc = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "sdh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF ) { switch ( c ) { @@ -407,8 +413,8 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -425,18 +431,18 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc > util_optind + 1 ) + if ( argc > globalUtilOptind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == util_optind + 1 ) + if ( argc == globalUtilOptind + 1 ) { - pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } Abc_NodePrintFanio( pOut, pNode ); @@ -476,8 +482,8 @@ int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -526,8 +532,8 @@ int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -580,8 +586,8 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fUseRealNames = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) { switch ( c ) { @@ -607,18 +613,18 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc > util_optind + 1 ) + if ( argc > globalUtilOptind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == util_optind + 1 ) + if ( argc == globalUtilOptind + 1 ) { - pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } Abc_NodePrintFactor( pOut, pNode, fUseRealNames ); @@ -664,8 +670,8 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fListNodes = 0; fProfile = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "nph" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF ) { switch ( c ) { @@ -694,18 +700,18 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc > util_optind + 1 ) + if ( argc > globalUtilOptind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == util_optind + 1 ) + if ( argc == globalUtilOptind + 1 ) { - pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } Abc_NodePrintLevel( pOut, pNode ); @@ -752,8 +758,8 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { @@ -829,8 +835,8 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) fUseBdds = 0; fNaive = 0; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "bnvh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF ) { switch ( c ) { @@ -906,8 +912,8 @@ int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) fUseBdds = 1; fUseNaive = 0; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "bnvh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF ) { switch ( c ) { @@ -978,19 +984,19 @@ int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv ) Output = -1; fNaive = 0; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Onvh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF ) { switch ( c ) { case 'O': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } - Output = atoi(argv[util_optind]); - util_optind++; + Output = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( Output < 0 ) goto usage; break; @@ -1058,8 +1064,8 @@ int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fUseRealNames = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) { switch ( c ) { @@ -1084,12 +1090,12 @@ int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Visualizing Karnaugh map works for BDD logic networks (run \"bdd\").\n" ); return 1; } - if ( argc > util_optind + 1 ) + if ( argc > globalUtilOptind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == util_optind ) + if ( argc == globalUtilOptind ) { pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); if ( !Abc_ObjIsNode(pNode) ) @@ -1100,10 +1106,10 @@ int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } } @@ -1145,8 +1151,8 @@ int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fUseLibrary = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { @@ -1208,8 +1214,8 @@ int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fUseLibrary = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { @@ -1269,8 +1275,8 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1293,12 +1299,12 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc > util_optind + 1 ) + if ( argc > globalUtilOptind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == util_optind ) + if ( argc == globalUtilOptind ) { pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); if ( !Abc_ObjIsNode(pNode) ) @@ -1309,10 +1315,10 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } } @@ -1359,30 +1365,30 @@ int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults nNodeSizeMax = 10; nConeSizeMax = ABC_INFINITY; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "NCh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF ) { switch ( c ) { case 'N': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } - nNodeSizeMax = atoi(argv[util_optind]); - util_optind++; + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nNodeSizeMax < 0 ) goto usage; break; case 'C': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } - nConeSizeMax = atoi(argv[util_optind]); - util_optind++; + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nConeSizeMax < 0 ) goto usage; break; @@ -1404,16 +1410,16 @@ int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" ); return 1; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); @@ -1459,8 +1465,8 @@ int Abc_CommandShowAig( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fMulti = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "mh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) { switch ( c ) { @@ -1533,8 +1539,8 @@ int Abc_CommandShowNtk( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fGateNames = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "gh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) { switch ( c ) { @@ -1595,8 +1601,8 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1671,8 +1677,8 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fAllNodes = 0; fCleanup = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ach" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF ) { switch ( c ) { @@ -1733,19 +1739,24 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; bool fDuplicate; bool fSelective; + bool fUpdateLevel; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fDuplicate = 0; - fSelective = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "dsh" ) ) != EOF ) + fDuplicate = 0; + fSelective = 0; + fUpdateLevel = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ldsh" ) ) != EOF ) { switch ( c ) { + case 'l': + fUpdateLevel ^= 1; + break; case 'd': fDuplicate ^= 1; break; @@ -1773,7 +1784,7 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the new network if ( Abc_NtkIsStrash(pNtk) ) { - pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective ); + pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel ); } else { @@ -1783,7 +1794,7 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Strashing before balancing has failed.\n" ); return 1; } - pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective ); + pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel ); Abc_NtkDelete( pNtkTemp ); } @@ -1798,8 +1809,9 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: balance [-dsh]\n" ); + fprintf( pErr, "usage: balance [-ldsh]\n" ); fprintf( pErr, "\t transforms the current network into a well-balanced AIG\n" ); + fprintf( pErr, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); fprintf( pErr, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); @@ -1836,30 +1848,30 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv ) fCnf = 0; fMulti = 0; fSimple = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "TFmcsh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsh" ) ) != EOF ) { switch ( c ) { case 'T': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } - nThresh = atoi(argv[util_optind]); - util_optind++; + nThresh = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nThresh < 0 ) goto usage; break; case 'F': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } - nFaninMax = atoi(argv[util_optind]); - util_optind++; + nFaninMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nFaninMax < 0 ) goto usage; break; @@ -1938,8 +1950,8 @@ int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1993,8 +2005,8 @@ int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -2062,30 +2074,30 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) p->fUse0 = 0; p->fUseCompl = 1; p->fVerbose = 0; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "LNsdzcvh")) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "LNsdzcvh")) != EOF ) { switch (c) { case 'L': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } - p->nPairsMax = atoi(argv[util_optind]); - util_optind++; + p->nPairsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( p->nPairsMax < 0 ) goto usage; break; case 'N': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } - p->nNodesExt = atoi(argv[util_optind]); - util_optind++; + p->nNodesExt = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( p->nNodesExt < 0 ) goto usage; break; @@ -2184,8 +2196,8 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) fVerbose = 0; fPrint = 0; fShort = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "grvpsh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF ) { switch ( c ) { @@ -2309,8 +2321,8 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) fPrecompute = 0; fUseZeros = 0; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "lxzvh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvh" ) ) != EOF ) { switch ( c ) { @@ -2371,7 +2383,7 @@ usage: fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; -} +} /**Function************************************************************* @@ -2404,34 +2416,34 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults nNodeSizeMax = 10; nConeSizeMax = 16; - fUpdateLevel = 0; + fUpdateLevel = 1; fUseZeros = 0; fUseDcs = 0; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "NClzdvh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF ) { switch ( c ) { case 'N': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } - nNodeSizeMax = atoi(argv[util_optind]); - util_optind++; + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nNodeSizeMax < 0 ) goto usage; break; case 'C': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } - nConeSizeMax = atoi(argv[util_optind]); - util_optind++; + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nConeSizeMax < 0 ) goto usage; break; @@ -2497,6 +2509,109 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nCutMax; + bool fUpdateLevel; + bool fUseZeros; + bool fVerbose; + extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCutMax = 5; + fUpdateLevel = 0; + fUseZeros = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nCutMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutMax < 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 ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( nCutMax < 4 || nCutMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRestructure( pNtk, nCutMax, fUpdateLevel, fUseZeros, fVerbose ) ) + { + fprintf( pErr, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: restructure [-K num] [-lzvh]\n" ); + fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" ); + fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutMax ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* @@ -2520,8 +2635,8 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -2591,8 +2706,8 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fComb = 1; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -2604,8 +2719,8 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - pArgvNew = argv + util_optind; - nArgcNew = argc - util_optind; + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; @@ -2662,19 +2777,19 @@ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fInitial = 0; nFrames = 5; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Fih" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fih" ) ) != EOF ) { switch ( c ) { case 'F': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } - nFrames = atoi(argv[util_optind]); - util_optind++; + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nFrames <= 0 ) goto usage; break; @@ -2744,8 +2859,8 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -2804,8 +2919,8 @@ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -2866,8 +2981,8 @@ int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { @@ -2926,8 +3041,8 @@ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -2987,29 +3102,43 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; int RetValue; int fVerbose; - int nSeconds; + int nConfLimit; + int nImpLimit; + int clk; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fVerbose = 0; - nSeconds = 20; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Tvh" ) ) != EOF ) + fVerbose = 0; + nConfLimit = 100000; + nImpLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) { switch ( c ) { - case 'T': - if ( util_optind >= argc ) + case 'C': + if ( globalUtilOptind >= argc ) { - fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } - nSeconds = atoi(argv[util_optind]); - util_optind++; - if ( nSeconds < 0 ) + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nImpLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nImpLimit < 0 ) goto usage; break; case 'v': @@ -3038,46 +3167,42 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } -/* - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( stdout, "This command can only be applied to logic network (run \"renode -c\").\n" ); - return 0; - } - if ( Abc_NtkIsMappedLogic(pNtk) ) - Abc_NtkUnmap(pNtk); - if ( Abc_NtkIsSopLogic(pNtk) ) - Abc_NtkSopToBdd(pNtk); -*/ if ( Abc_NtkIsStrash(pNtk) ) { - RetValue = Abc_NtkMiterSat( pNtk, nSeconds, fVerbose ); + clk = clock(); + RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, fVerbose ); if ( RetValue == -1 ) - printf( "The miter is UNDECIDED (SAT solver timed out).\n" ); + printf( "UNDECIDED " ); else if ( RetValue == 0 ) - printf( "The miter is SATISFIABLE.\n" ); + printf( "SATISFIABLE " ); else - printf( "The miter is UNSATISFIABLE.\n" ); + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + PRT( "Time", clock() - clk ); } else { Abc_Ntk_t * pTemp; pTemp = Abc_NtkStrash( pNtk, 0, 0 ); - RetValue = Abc_NtkMiterSat( pTemp, nSeconds, fVerbose ); + clk = clock(); + RetValue = Abc_NtkMiterSat( pTemp, nConfLimit, nImpLimit, fVerbose ); if ( RetValue == -1 ) - printf( "The miter is UNDECIDED (SAT solver timed out).\n" ); + printf( "UNDECIDED " ); else if ( RetValue == 0 ) - printf( "The miter is SATISFIABLE.\n" ); + printf( "SATISFIABLE " ); else - printf( "The miter is UNSATISFIABLE.\n" ); + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + PRT( "Time", clock() - clk ); Abc_NtkDelete( pTemp ); } return 0; usage: - fprintf( pErr, "usage: sat [-T num] [-vh]\n" ); + fprintf( pErr, "usage: sat [-C num] [-I num] [-vh]\n" ); fprintf( pErr, "\t solves the combinational miter\n" ); - fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit ); fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -3109,8 +3234,8 @@ int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { @@ -3169,9 +3294,10 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkRes; - Abc_Obj_t * pNode; + Abc_Obj_t * pNode, * pNodeCo; int c; int fUseAllCis; + int fUseMffc; int Output; pNtk = Abc_FrameReadNtk(pAbc); @@ -3180,23 +3306,26 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fUseAllCis = 0; + fUseMffc = 0; Output = -1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Oah" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Omah" ) ) != EOF ) { switch ( c ) { case 'O': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } - Output = atoi(argv[util_optind]); - util_optind++; + Output = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( Output < 0 ) goto usage; break; + case 'm': + fUseMffc ^= 1; case 'a': fUseAllCis ^= 1; break; @@ -3219,27 +3348,31 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc > util_optind + 1 ) + if ( argc > globalUtilOptind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - if ( argc == util_optind + 1 ) + if ( argc == globalUtilOptind + 1 ) { - pNode = Abc_NtkFindCo( pNtk, argv[util_optind] ); + pNodeCo = Abc_NtkFindCo( pNtk, argv[globalUtilOptind] ); + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find CO node \"%s\".\n", argv[util_optind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } - pNtkRes = Abc_NtkCreateOutput( pNtk, pNode, fUseAllCis ); + if ( fUseMffc ) + pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] ); + else + pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis ); } else { if ( Output == -1 ) { - fprintf( pErr, "The output is not specified.\n" ); + fprintf( pErr, "The node is not specified.\n" ); return 1; } if ( Output >= Abc_NtkCoNum(pNtk) ) @@ -3247,11 +3380,17 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) ); return 1; } - pNtkRes = Abc_NtkCreateOutput( pNtk, Abc_NtkCo(pNtk,Output), fUseAllCis ); + pNodeCo = Abc_NtkCo( pNtk, Output ); + if ( fUseMffc ) + pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) ); + else + pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis ); } + if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) ) + printf( "The extracted cone represents the complement function of the CO.\n" ); if ( pNtkRes == NULL ) { - fprintf( pErr, "Splitting one output has failed.\n" ); + fprintf( pErr, "Writing the logic cone of one node has failed.\n" ); return 1; } // replace the current network @@ -3259,12 +3398,13 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: one_output [-O num] [-ah] <name>\n" ); - fprintf( pErr, "\t replaces the current network by the logic cone of one output\n" ); + fprintf( pErr, "usage: cone [-O num] [-amh] <name>\n" ); + fprintf( pErr, "\t replaces the current network by one logic cone\n" ); fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); + fprintf( pErr, "\t-m : toggle writing only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" ); fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t-O num : (optional) the 0-based number of the output\n"); - fprintf( pErr, "\tname : (optional) the name of the output\n"); + fprintf( pErr, "\t-O num : (optional) the 0-based number of the CO to extract\n"); + fprintf( pErr, "\tname : (optional) the name of the node to extract\n"); return 1; } @@ -3291,8 +3431,8 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -3315,16 +3455,16 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { fprintf( pErr, "Wrong number of auguments.\n" ); goto usage; } - pNode = Abc_NtkFindNode( pNtk, argv[util_optind] ); + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] ); + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } @@ -3340,7 +3480,7 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: one_node [-h] <name>\n" ); + fprintf( pErr, "usage: node [-h] <name>\n" ); fprintf( pErr, "\t replaces the current network by the network composed of one node\n" ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\tname : the node name\n"); @@ -3371,8 +3511,8 @@ int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -3420,8 +3560,8 @@ int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -3480,8 +3620,8 @@ int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -3538,8 +3678,8 @@ int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -3556,13 +3696,13 @@ int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -3639,30 +3779,30 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) pParams->fDrop = 0; // drop cuts on the fly pParams->fMulti = 0; // use multi-input AND-gates pParams->fVerbose = 0; // the verbosiness flag - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "KMtfdmvoh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdmvoh" ) ) != EOF ) { switch ( c ) { case 'K': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } - pParams->nVarsMax = atoi(argv[util_optind]); - util_optind++; + pParams->nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( pParams->nVarsMax < 0 ) goto usage; break; case 'M': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } - pParams->nKeepMax = atoi(argv[util_optind]); - util_optind++; + pParams->nKeepMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( pParams->nKeepMax < 0 ) goto usage; break; @@ -3729,7 +3869,7 @@ usage: fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); - fprintf( pErr, "\t-m : toggle using multi-input AND-gates [default = %s]\n", pParams->fMulti? "yes": "no" ); + fprintf( pErr, "\t-m : toggle computing only factor-cuts [default = %s]\n", pParams->fMulti? "yes": "no" ); fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -3767,30 +3907,30 @@ int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv ) pParams->fFilter = 1; // filter dominated cuts pParams->fSeq = 1; // compute sequential cuts pParams->fVerbose = 0; // the verbosiness flag - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "KMtvh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF ) { switch ( c ) { case 'K': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } - pParams->nVarsMax = atoi(argv[util_optind]); - util_optind++; + pParams->nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( pParams->nVarsMax < 0 ) goto usage; break; case 'M': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } - pParams->nKeepMax = atoi(argv[util_optind]); - util_optind++; + pParams->nKeepMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( pParams->nKeepMax < 0 ) goto usage; break; @@ -3868,19 +4008,19 @@ int Abc_CommandXyz( Abc_Frame_t * pAbc, int argc, char ** argv ) fVerbose = 0; fUseInvs = 1; nFaninMax = 128; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Nivh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nivh" ) ) != EOF ) { switch ( c ) { case 'N': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } - nFaninMax = atoi(argv[util_optind]); - util_optind++; + nFaninMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nFaninMax < 0 ) goto usage; break; @@ -3931,6 +4071,66 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fVerbose; + extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(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 ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "SOP minimization is possible for logic networks (run \"renode\").\n" ); + return 1; + } + Abc_NtkEspresso( pNtk, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: espresso [-vh]\n" ); + fprintf( pErr, "\t minimizes SOPs of the local functions using Espresso\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* @@ -3948,15 +4148,15 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkRes; int c; -// extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ); + extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -3984,8 +4184,8 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) // run the command // pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 ); -// pNtkRes = Abc_NtkNewAig( pNtk ); - pNtkRes = NULL; + pNtkRes = Abc_NtkNewAig( pNtk ); +// pNtkRes = NULL; if ( pNtkRes == NULL ) { fprintf( pErr, "Command has failed.\n" ); @@ -4044,41 +4244,41 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) pParams->fTryProve = 0; // tries to solve the final miter pParams->fVerbose = 0; // the verbosiness flag pParams->fVerboseP = 0; // the verbosiness flag - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "RDBrscpvaeh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "RDBrscpvaeh" ) ) != EOF ) { switch ( c ) { case 'R': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } - pParams->nPatsRand = atoi(argv[util_optind]); - util_optind++; + pParams->nPatsRand = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( pParams->nPatsRand < 0 ) goto usage; break; case 'D': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } - pParams->nPatsDyna = atoi(argv[util_optind]); - util_optind++; + pParams->nPatsDyna = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( pParams->nPatsDyna < 0 ) goto usage; break; case 'B': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); goto usage; } - pParams->nBTLimit = atoi(argv[util_optind]); - util_optind++; + pParams->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( pParams->nBTLimit < 0 ) goto usage; break; @@ -4189,8 +4389,8 @@ int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fDuplicate = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { @@ -4253,8 +4453,8 @@ int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fDuplicate = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { @@ -4314,8 +4514,8 @@ int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fDuplicate = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { @@ -4378,8 +4578,8 @@ int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fDuplicate = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { @@ -4432,8 +4632,8 @@ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) fUseInv = 1; fExdc = 0; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ievh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ievh" ) ) != EOF ) { switch ( c ) { @@ -4521,19 +4721,19 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) fSweep = 1; fSwitching = 0; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Daspvh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF ) { switch ( c ) { case 'D': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } - DelayTarget = (float)atof(argv[util_optind]); - util_optind++; + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; if ( DelayTarget <= 0.0 ) goto usage; break; @@ -4576,7 +4776,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Strashing before mapping has failed.\n" ); return 1; } - pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtk == NULL ) { @@ -4652,8 +4852,8 @@ int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -4713,8 +4913,8 @@ int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -4776,8 +4976,8 @@ int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -4853,8 +5053,8 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) fSwitching = 0; fVerbose = 0; DelayTarget =-1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "apvhD" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "apvhD" ) ) != EOF ) { switch ( c ) { @@ -4870,13 +5070,13 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'h': goto usage; case 'D': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } - DelayTarget = (float)atof(argv[util_optind]); - util_optind++; + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; if ( DelayTarget <= 0.0 ) goto usage; break; @@ -4906,7 +5106,7 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); return 1; } - pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtk == NULL ) { @@ -4985,8 +5185,8 @@ int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv ) pParams->fSwitching = 0; pParams->fDropCuts = 0; pParams->fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "fapdvh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "fapdvh" ) ) != EOF ) { switch ( c ) { @@ -5029,7 +5229,7 @@ int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); return 1; } - pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtk == NULL ) { @@ -5106,8 +5306,8 @@ int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv ) fOnes = 0; fRandom = 0; fDontCare = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "zordh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "zordh" ) ) != EOF ) { switch ( c ) { @@ -5211,19 +5411,19 @@ int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults nLatches = 5; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Lh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF ) { switch ( c ) { case 'L': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-L\" should be followed by a positive integer.\n" ); goto usage; } - nLatches = atoi(argv[util_optind]); - util_optind++; + nLatches = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nLatches < 0 ) goto usage; break; @@ -5286,8 +5486,8 @@ int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -5364,8 +5564,8 @@ int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fShare = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "sh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) { switch ( c ) { @@ -5445,19 +5645,19 @@ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) fInitial = 1; fVerbose = 0; nMaxIters = 15; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Ifbivh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ifbivh" ) ) != EOF ) { switch ( c ) { case 'I': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); goto usage; } - nMaxIters = atoi(argv[util_optind]); - util_optind++; + nMaxIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nMaxIters < 0 ) goto usage; break; @@ -5568,19 +5768,19 @@ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults nMaxIters = 15; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Ivh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) { switch ( c ) { case 'I': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); goto usage; } - nMaxIters = atoi(argv[util_optind]); - util_optind++; + nMaxIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nMaxIters < 0 ) goto usage; break; @@ -5625,7 +5825,7 @@ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0 ); + pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtkNew == NULL ) { @@ -5692,19 +5892,19 @@ int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults nMaxIters = 15; fVerbose = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Ivh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) { switch ( c ) { case 'I': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); goto usage; } - nMaxIters = atoi(argv[util_optind]); - util_optind++; + nMaxIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nMaxIters < 0 ) goto usage; break; @@ -5749,7 +5949,7 @@ int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0 ); + pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtkNew == NULL ) { @@ -5824,19 +6024,19 @@ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) fExdc = 1; fImp = 0; fVerbose = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Feivh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Feivh" ) ) != EOF ) { switch ( c ) { case 'F': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } - nFrames = atoi(argv[util_optind]); - util_optind++; + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nFrames <= 0 ) goto usage; break; @@ -5927,8 +6127,8 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -5983,8 +6183,10 @@ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) int fSat; int fVerbose; int nSeconds; + int nConfLimit; + int nImpLimit; - extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds ); + extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nImpLimit ); extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); @@ -5996,22 +6198,46 @@ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) fSat = 0; fVerbose = 0; nSeconds = 20; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "Tsvh" ) ) != EOF ) + nConfLimit = 10000; + nImpLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TCIsvh" ) ) != EOF ) { switch ( c ) { case 'T': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } - nSeconds = atoi(argv[util_optind]); - util_optind++; + nSeconds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nSeconds < 0 ) goto usage; break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "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 ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nImpLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nImpLimit < 0 ) + goto usage; + break; case 's': fSat ^= 1; break; @@ -6023,14 +6249,14 @@ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - pArgvNew = argv + util_optind; - nArgcNew = argc - util_optind; + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; // perform equivalence checking if ( fSat ) - Abc_NtkCecSat( pNtk1, pNtk2, nSeconds ); + Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nImpLimit ); else Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose ); @@ -6039,9 +6265,11 @@ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: cec [-T num] [-svh] <file1> <file2>\n" ); + fprintf( pErr, "usage: cec [-T num] [-C num] [-I num] [-svh] <file1> <file2>\n" ); fprintf( pErr, "\t performs combinational equivalence checking\n" ); fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit ); fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); @@ -6075,8 +6303,10 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) int fVerbose; int nFrames; int nSeconds; + int nConfLimit; + int nImpLimit; - extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames ); + extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nImpLimit, int nFrames ); extern void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); @@ -6089,33 +6319,57 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) fVerbose = 0; nFrames = 3; nSeconds = 20; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "FTsvh" ) ) != EOF ) + nConfLimit = 10000; + nImpLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsvh" ) ) != EOF ) { switch ( c ) { case 'F': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } - nFrames = atoi(argv[util_optind]); - util_optind++; + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nFrames <= 0 ) goto usage; break; case 'T': - if ( util_optind >= argc ) + if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } - nSeconds = atoi(argv[util_optind]); - util_optind++; + nSeconds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nSeconds < 0 ) goto usage; break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "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 ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nImpLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nImpLimit < 0 ) + goto usage; + break; case 'v': fVerbose ^= 1; break; @@ -6127,14 +6381,14 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - pArgvNew = argv + util_optind; - nArgcNew = argc - util_optind; + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; // perform equivalence checking if ( fSat ) - Abc_NtkSecSat( pNtk1, pNtk2, nSeconds, nFrames ); + Abc_NtkSecSat( pNtk1, pNtk2, nConfLimit, nImpLimit, nFrames ); else Abc_NtkSecFraig( pNtk1, pNtk2, nSeconds, nFrames, fVerbose ); @@ -6143,13 +6397,15 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: sec [-F num] [-T num] [-svh] <file1> <file2>\n" ); + fprintf( pErr, "usage: sec [-F num] [-T num] [-C num] [-I num] [-svh] <file1> <file2>\n" ); fprintf( pErr, "\t performs bounded sequential equivalence checking\n" ); fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames ); fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit ); fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); @@ -6157,6 +6413,137 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp; + int c; + int RetValue; + int fVerbose; + int fRewrite; + int fFraig; + int nConfLimit; + int nImpLimit; + int clk; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + fRewrite = 1; + fFraig = 1; + nConfLimit = 300000; + nImpLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CIrfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "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 ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nImpLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nImpLimit < 0 ) + goto usage; + break; + case 'r': + fRewrite ^= 1; + break; + case 'f': + fFraig ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkCoNum(pNtk) != 1 ) + { + fprintf( stdout, "Currently can only solve the miter with one output.\n" ); + return 0; + } + if ( Abc_NtkIsSeq(pNtk) ) + { + fprintf( stdout, "This command cannot be applied to the sequential AIG.\n" ); + return 0; + } + + clk = clock(); + + if ( Abc_NtkIsStrash(pNtk) ) + pNtkTemp = Abc_NtkDup( pNtk ); + else + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 ); + + RetValue = Abc_NtkMiterProve( &pNtkTemp, nConfLimit, nImpLimit, fRewrite, fFraig, fVerbose ); + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + + PRT( "Time", clock() - clk ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); + return 0; + +usage: + fprintf( pErr, "usage: prove [-C num] [-I num] [-rfvh]\n" ); + fprintf( pErr, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit ); + fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", fRewrite? "yes": "no" ); + fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", fFraig? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c index effae853..919ea3b2 100644 --- a/src/base/abci/abcBalance.c +++ b/src/base/abci/abcBalance.c @@ -24,8 +24,8 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective ); -static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective ); +static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ); +static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel ); static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, bool fSelective ); static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ); static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ); @@ -45,7 +45,7 @@ static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ); SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective ) +Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ) { Abc_Ntk_t * pNtkAig; assert( Abc_NtkIsStrash(pNtk) ); @@ -57,7 +57,7 @@ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective ) } // perform balancing pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective ); + Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel ); Abc_NtkFinalize( pNtk, pNtkAig ); // undo the required times if ( fSelective ) @@ -88,7 +88,7 @@ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective ) SeeAlso [] ***********************************************************************/ -void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective ) +void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ) { int fCheck = 1; ProgressBar * pProgress; @@ -107,7 +107,7 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica Extra_ProgressBarUpdate( pProgress, i, NULL ); // strash the driver node pDriver = Abc_ObjFanin0(pNode); - Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective ); + Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel ); } Extra_ProgressBarStop( pProgress ); Vec_VecFree( vStorage ); @@ -115,38 +115,93 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica /**Function************************************************************* - Synopsis [Randomizes the node positions.] + Synopsis [Finds the left bound on the next candidate to be paired.] - Description [] + 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 [] ***********************************************************************/ -void Abc_NodeBalanceRandomize( Vec_Ptr_t * vSuper ) +int Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) { - Abc_Obj_t * pNode1, * pNode2; - int i, Signature; + 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 = 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 = 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 = 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; - pNode1 = Vec_PtrEntry( vSuper, Vec_PtrSize(vSuper)-2 ); - pNode2 = Vec_PtrEntry( vSuper, Vec_PtrSize(vSuper)-3 ); - if ( Abc_ObjRegular(pNode1)->Level != Abc_ObjRegular(pNode2)->Level ) - return; - // some reordering will be performed - Signature = rand(); - for ( i = Vec_PtrSize(vSuper)-2; i > 0; i-- ) + // get the two last nodes + pNode1 = Vec_PtrEntry( vSuper, RightBound + 1 ); + pNode2 = Vec_PtrEntry( vSuper, RightBound ); + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pNode3 = Vec_PtrEntry( vSuper, i ); + if ( Abc_AigAndLookup( 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 { - pNode1 = Vec_PtrEntry( vSuper, i ); - pNode2 = Vec_PtrEntry( vSuper, i-1 ); - if ( Abc_ObjRegular(pNode1)->Level != Abc_ObjRegular(pNode2)->Level ) + int Choice = rand() % (RightBound - LeftBound + 1); + pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pNode3 == pNode2 ) return; - if ( Signature & (1 << (i % 10)) ) - continue; - Vec_PtrWriteEntry( vSuper, i, pNode2 ); - Vec_PtrWriteEntry( vSuper, i-1, pNode1 ); + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); } +*/ } /**Function************************************************************* @@ -160,12 +215,12 @@ void Abc_NodeBalanceRandomize( Vec_Ptr_t * vSuper ) SeeAlso [] ***********************************************************************/ -Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective ) +Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel ) { Abc_Aig_t * pMan = pNtkNew->pManFunc; Abc_Obj_t * pNodeNew, * pNode1, * pNode2; Vec_Ptr_t * vSuper; - int i; + int i, LeftBound; assert( !Abc_ObjIsComplement(pNodeOld) ); // return if the result if known if ( pNodeOld->pCopy ) @@ -181,7 +236,7 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_ // for each old node, derive the new well-balanced node for ( i = 0; i < vSuper->nSize; i++ ) { - pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective ); + pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel ); vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) ); } if ( vSuper->nSize < 2 ) @@ -192,8 +247,10 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_ assert( vSuper->nSize > 1 ); while ( vSuper->nSize > 1 ) { - // randomize the node positions -// Abc_NodeBalanceRandomize( vSuper ); + // 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 = Vec_PtrPop(vSuper); pNode2 = Vec_PtrPop(vSuper); diff --git a/src/base/abci/abcCollapse.c b/src/base/abci/abcClpBdd.c index 59c76e09..59c76e09 100644 --- a/src/base/abci/abcCollapse.c +++ b/src/base/abci/abcClpBdd.c diff --git a/src/base/abci/abcClpSop.c b/src/base/abci/abcClpSop.c new file mode 100644 index 00000000..de92243f --- /dev/null +++ b/src/base/abci/abcClpSop.c @@ -0,0 +1,53 @@ +/**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 "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collapses the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCollapseSop( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + pNtkNew = NULL; + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c index 3e34602d..1ee9a712 100644 --- a/src/base/abci/abcCut.c +++ b/src/base/abci/abcCut.c @@ -57,10 +57,41 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); assert( Abc_NtkIsStrash(pNtk) ); - +/* if ( pParams->fMulti ) - Abc_NtkBalanceAttach(pNtk); - + { + Abc_Obj_t * pNode, * pNodeA, * pNodeB, * pNodeC; + int nFactors; + // lebel the nodes, which will be the roots of factor-cuts + // mark the multiple-fanout nodes + Abc_AigForEachAnd( pNtk, pNode, i ) + if ( pNode->vFanouts.nSize > 1 ) + pNode->fMarkB = 1; + // unmark the control inputs of MUXes and inputs of EXOR gates + Abc_AigForEachAnd( pNtk, pNode, i ) + { + if ( !Abc_NodeIsMuxType(pNode) ) + continue; + + pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeA, &pNodeB ); + // if real children are used, skip + if ( Abc_ObjFanin0(pNode)->vFanouts.nSize > 1 || Abc_ObjFanin1(pNode)->vFanouts.nSize > 1 ) + continue; + + if ( pNodeC->vFanouts.nSize == 2 ) + pNodeC->fMarkB = 0; + if ( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) && Abc_ObjRegular(pNodeA)->vFanouts.nSize == 2 ) + Abc_ObjRegular(pNodeA)->fMarkB = 0; + } + // mark the PO drivers +// Abc_NtkForEachCo( pNtk, pNode, i ) +// Abc_ObjFanin0(pNode)->fMarkB = 1; + nFactors = 0; + Abc_AigForEachAnd( pNtk, pNode, i ) + nFactors += pNode->fMarkB; + printf( "Total nodes = %6d. Total factors = %6d.\n", Abc_NtkNodeNum(pNtk), nFactors ); + } +*/ // start the manager pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); p = Cut_ManStart( pParams ); @@ -104,8 +135,13 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) } Vec_PtrFree( vNodes ); Vec_IntFree( vChoices ); +/* if ( pParams->fMulti ) - Abc_NtkBalanceDetach(pNtk); + { + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->fMarkB = 0; + } +*/ PRT( "Total", clock() - clk ); //Abc_NtkPrintCuts_( p, pNtk, 0 ); // Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); @@ -282,14 +318,14 @@ printf( "Converged after %d iterations.\n", nIters ); SeeAlso [] ***********************************************************************/ -void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj ) +void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fMulti ) { void * pList; if ( pList = Abc_NodeReadCuts( p, pObj ) ) return pList; - Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj) ); - Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj) ); - return Abc_NodeGetCuts( p, pObj, 0 ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fMulti ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fMulti ); + return Abc_NodeGetCuts( p, pObj, fMulti ); } /**Function************************************************************* @@ -305,7 +341,8 @@ void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj ) ***********************************************************************/ void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fMulti ) { - int fTriv = (!fMulti) || (pObj->pCopy != NULL); +// int fTriv = (!fMulti) || pObj->fMarkB; + int fTriv = (!fMulti) || (pObj->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pObj)); assert( Abc_NtkIsStrash(pObj->pNtk) ); assert( Abc_ObjFaninNum(pObj) == 2 ); return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c index a73ab2b5..9dd5ea3a 100644 --- a/src/base/abci/abcDsd.c +++ b/src/base/abci/abcDsd.c @@ -446,7 +446,7 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager /**Function************************************************************* - Synopsis [Performs decomposition of one node.] + Synopsis [Checks if the node should be decomposed by DSD.] Description [] diff --git a/src/base/abci/abcEspresso.c b/src/base/abci/abcEspresso.c new file mode 100644 index 00000000..ee6598c9 --- /dev/null +++ b/src/base/abci/abcEspresso.c @@ -0,0 +1,244 @@ +/**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 "abc.h" +#include "espresso.h" + +//////////////////////////////////////////////////////////////////////// +/// 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_NtkUnmap(pNtk); + else if ( Abc_NtkHasBdd(pNtk) ) + Abc_NtkBddToSop(pNtk); + // 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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcFraig.c b/src/base/abci/abcFraig.c index d59f21a0..4aae6ba5 100644 --- a/src/base/abci/abcFraig.c +++ b/src/base/abci/abcFraig.c @@ -26,7 +26,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); +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 ); diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c index 128e054a..39bf15aa 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -105,7 +105,7 @@ clk = clock(); Map_ManFree( pMan ); return NULL; } - Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), clock()-clk ); +// Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), clock()-clk ); // reconstruct the network after mapping pNtkNew = Abc_NtkFromMap( pMan, pNtk ); diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c index 44130a20..30fc3a79 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -90,7 +90,7 @@ Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) // start the new network pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); - pNtkMiter->pName = util_strsav(Buffer); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); // perform strashing Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb ); @@ -308,7 +308,7 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In // start the new network pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) ); - pNtkMiter->pName = util_strsav(Buffer); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); // get the root output pRoot = Abc_NtkCo( pNtk, Out ); @@ -372,7 +372,7 @@ Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ) // start the new network pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); - pNtkMiter->pName = util_strsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); + pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); // get the root output pRoot = Abc_NtkCo( pNtk, 0 ); @@ -384,14 +384,16 @@ Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ) // add the first cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); // save the output - pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; +// 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_NtkConst1( pNtkMiter ); // add the second cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); // save the output - pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; +// pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; + pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); // create the miter of the two outputs if ( fExist ) @@ -461,7 +463,7 @@ int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ) assert( Abc_NtkIsStrash(pMiter) ); Abc_NtkForEachPo( pMiter, pNodePo, i ) { - pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) ); + pChild = Abc_ObjChild0( pNodePo ); if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) ) { assert( Abc_ObjRegular(pChild) == Abc_NtkConst1(pMiter) ); @@ -552,7 +554,7 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial ) // start the new network pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); - pNtkFrames->pName = util_strsav(Buffer); + pNtkFrames->pName = Extra_UtilStrsav(Buffer); // create new latches (or their initial values) and remember them in the new latches if ( !fInitial ) { @@ -682,7 +684,7 @@ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFram // start the new network pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); - pNtkFrames->pName = util_strsav(Buffer); + pNtkFrames->pName = Extra_UtilStrsav(Buffer); // create new latches (or their initial values) and remember them in the new latches if ( !fInitial ) { diff --git a/src/base/abci/abcNewAig.c b/src/base/abci/abcNewAig.c index 33f58135..ce76195a 100644 --- a/src/base/abci/abcNewAig.c +++ b/src/base/abci/abcNewAig.c @@ -56,9 +56,11 @@ Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ) { Aig_Man_t * pMan; Abc_Ntk_t * pNtkAig; - Aig_ProofType_t RetValue; +// Aig_ProofType_t RetValue; int fCleanup = 1; int nNodes; + extern void Aig_MffcTest( Aig_Man_t * pMan ); + assert( !Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkIsSeq(pNtk) ); @@ -70,6 +72,10 @@ Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ) // convert to the AIG manager pMan = Abc_NtkToAig( pNtk ); + + Aig_MffcTest( pMan ); + +/* // execute a command in the AIG manager RetValue = Aig_FraigProve( pMan ); if ( RetValue == AIG_PROOF_SAT ) @@ -80,6 +86,7 @@ Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ) printf( "Undecided.\n" ); else assert( 0 ); +*/ // convert from the AIG manager pNtkAig = Abc_NtkFromAig( pNtk, pMan ); @@ -173,6 +180,8 @@ Aig_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtkOld ) Abc_NtkConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); Abc_NtkForEachCi( pNtkOld, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Aig_NodeCreatePi(pMan); + Abc_NtkForEachCo( pNtkOld, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Aig_NodeCreatePo(pMan); // perform the conversion of the internal nodes Abc_NtkStrashPerformAig( pNtkOld, pMan ); // create the POs @@ -180,7 +189,7 @@ Aig_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtkOld ) { pFanin = (Aig_Node_t *)Abc_ObjFanin0(pObj)->pCopy; pFanin = Aig_NotCond( pFanin, Abc_ObjFaninC0(pObj) ); - pObj->pCopy = (Abc_Obj_t *)Aig_NodeCreatePo( pMan, pFanin ); + Aig_NodeConnectPo( pMan, (Aig_Node_t *)pObj->pCopy, pFanin ); } return pMan; } diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index 6257bd08..b961ec15 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -79,7 +79,7 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo // start the network pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD ); - pNtk->pName = util_strsav(pNamePo); + pNtk->pName = Extra_UtilStrsav(pNamePo); // make sure the new manager has enough inputs Cudd_bddIthVar( pNtk->pManFunc, Vec_PtrSize(vNamesPi) ); // add the PIs corresponding to the names diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c new file mode 100644 index 00000000..18ee9a3f --- /dev/null +++ b/src/base/abci/abcProve.c @@ -0,0 +1,232 @@ +/**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 "abc.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose ); +extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool 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, int * pRetValue ); +static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int 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, int nConfLimit, int nImpLimit, int fUseRewrite, int fUseFraig, int fVerbose ) +{ + Abc_Ntk_t * pNtk, * pNtkTemp; + int nConfsStart = 1000, nImpsStart = 0, nBTLimitStart = 2; + int nConfs, nImps, nBTLimit, RetValue; + int nIter = 0, clk, timeStart = clock(); + + // get the starting network + pNtk = *ppNtk; + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + + // set the initial limits + nConfs = !nConfLimit? nConfsStart : ABC_MIN( nConfsStart, nConfLimit ); + nImps = !nImpLimit ? nImpsStart : ABC_MIN( nImpsStart , nImpLimit ); + nBTLimit = nBTLimitStart; + + if ( fVerbose ) + printf( "Global resource limits: ConfsLim = %6d. ImpsLim = %d.\n", nConfLimit, nImpLimit ); + + // if SAT only, solve without iteration + if ( !fUseRewrite && !fUseFraig ) + { + clk = clock(); + RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, 0 ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose ); + *ppNtk = pNtk; + return RetValue; + } + + // check the current resource limits + do { + nIter++; + + if ( fVerbose ) + printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter, nConfs, nBTLimit ); + + // try brute-force SAT + clk = clock(); + RetValue = Abc_NtkMiterSat( pNtk, nConfs, nImps, 0 ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose ); + if ( RetValue >= 0 ) + break; + + if ( fUseRewrite ) + { + clk = clock(); + + // try rewriting + Abc_NtkRewrite( pNtk, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + + Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, fVerbose ); + } + + if ( fUseFraig ) + { + // try FRAIGing + clk = clock(); + pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, nBTLimit, &RetValue ); Abc_NtkDelete( pNtkTemp ); + Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, fVerbose ); + if ( RetValue >= 0 ) + break; + } + + // increase resource limits + nConfs = ABC_MIN( nConfs * 3 / 2, 1000000000 ); + nImps = ABC_MIN( nImps * 3 / 2, 1000000000 ); + nBTLimit = ABC_MIN( nBTLimit * 8, 1000000000 ); + + // timeout at 5 minutes + if ( clock() - timeStart >= 300 * CLOCKS_PER_SEC ) + break; + if ( nIter == 4 ) + break; + } + while ( (nConfLimit == 0 || nConfs <= nConfLimit) && + (nImpLimit == 0 || nImps <= nImpLimit ) ); + + // try to prove it using brute force SAT + if ( RetValue < 0 ) + { + clk = clock(); + RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, 0 ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose ); + } + + *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, int * pRetValue ) +{ + 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_MIN( 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; + + // transform the target into a fraig + pMan = Abc_NtkToFraig( pNtk, pParams, 0, 0 ); + Fraig_ManProveMiter( pMan ); + RetValue = Fraig_ManCheckMiter( pMan ); + + // save model + if ( RetValue == 0 ) + { + pModel = Fraig_ManReadModel( pMan ); + FREE( pNtk->pModel ); + pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) ); + memcpy( pNtk->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtk) ); + } + // create the network + pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); + // delete the fraig manager + Fraig_ManFree( pMan ); + *pRetValue = RetValue; + 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, int clk, int fVerbose ) +{ + if ( !fVerbose ) + return; + printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), Abc_AigGetLevelNum(pNtk) ); + PRT( pString, clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcRenode.c b/src/base/abci/abcRenode.c index ea2f808c..cfb05aee 100644 --- a/src/base/abci/abcRenode.c +++ b/src/base/abci/abcRenode.c @@ -407,7 +407,7 @@ void Abc_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ) continue; if ( pNode->fMarkA == 0 ) continue; - // continue cutting branches ntil it meets the fanin limit + // continue cutting branches until it meets the fanin limit while ( Abc_NtkRenodeLimit(pNode, vCone, nFaninMax) ); assert( vCone->nSize <= nFaninMax ); } diff --git a/src/base/abci/abcRestruct.c b/src/base/abci/abcRestruct.c new file mode 100644 index 00000000..0b4c80c8 --- /dev/null +++ b/src/base/abci/abcRestruct.c @@ -0,0 +1,1026 @@ +/**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 "abc.h" +#include "dec.h" +#include "dsd.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +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 + // 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_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 fMulti ); +static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool 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, bool fUpdateLevel, bool fUseZeros, bool fVerbose ) +{ + ProgressBar * pProgress; + Abc_ManRst_t * pManRst; + Cut_Man_t * pManCut; + Cut_Cut_t * pCutList; + Dec_Graph_t * pGraph; + Abc_Obj_t * pNode; + int clk, clkStart = clock(); + int fMulti = 1; + int i, nNodes; + + assert( Abc_NtkIsStrash(pNtk) ); + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); + Abc_NtkCleanCopy(pNtk); + + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk ); + + // start the restructuring manager + pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose ); + pManRst->pNtk = pNtk; + // start the cut manager +clk = clock(); + pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti ); +pManRst->timeCut += 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 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 = clock(); + pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti ); +pManRst->timeCut += clock() - clk; + // evaluate these cuts +clk = clock(); + pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList ); +pManRst->timeRes += clock() - clk; + if ( pGraph == NULL ) + continue; + // acceptable replacement found, update the graph +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain ); +pManRst->timeNtk += clock() - clk; + Dec_GraphFree( pGraph ); + } + Extra_ProgressBarStop( pProgress ); +pManRst->timeTotal = 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_NtkGetLevelNum( 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 ) +{ + Abc_Obj_t * pNode, * pFanin, * pFanout; + int i, k; + // start with the leaves + Vec_PtrClear( p->vDecs ); + Vec_PtrForEachEntry( p->vLeaves, pNode, i ) + { + Vec_PtrPush( p->vDecs, pNode ); + assert( pNode->fMarkC == 0 ); + pNode->fMarkC = 1; + } + // explore the fanouts + Vec_PtrForEachEntry( 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( p->vDecs, pNode, i ) + pNode->fMarkC = 0; + // print the nodes + Vec_PtrForEachEntryStart( p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) ) + { + printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " ); + // find the first fanin + Vec_PtrForEachEntry( 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( 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" ); + } +} + + +/**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 ) +{ + 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_NodeReadRequiredLevel(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 = 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 += 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 = clock(); + // try disjoint support decomposition + pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc ); +p->timeDsd += 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( p->vLeaves, pLeaf, i ) + pLeaf->vFanouts.nSize++; + // label MFFC with current traversal ID + Abc_NtkIncrementTravId( pRoot->pNtk ); + nNodesSaved = Abc_NodeMffcLabel( pRoot ); + // unmark the fanin boundary and set the fanins as leaves in the form + Vec_PtrForEachEntry( p->vLeaves, pLeaf, i ) + pLeaf->vFanouts.nSize--; + + + 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; + } + + // detect how many new nodes will be added (while taking into account reused nodes) +clk = clock(); + pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded ); +// pGraph = NULL; +p->timeEval += clock() - clk; + + // quit if there is no improvement + if ( 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 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = 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 = 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( 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( 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 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = 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( 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_MAX(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 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = 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( 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_MAX(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( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + pTemp = Abc_AigAndLookup( 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 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode3 = 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( 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_MAX( ABC_MAX(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( pManRst->pNtk->pManFunc, pNode1, pNode2 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + if ( !pNode1 || !pNode3 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + } + else + { + if ( !pNode1 || !pNode2 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + if ( !pNode1 || !pNode3 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( 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 = 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 = 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 fMulti ) +{ + 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->fMulti = fMulti; // compute factor-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, bool fUpdateLevel, bool fUseZeros, bool fVerbose ) +{ + Abc_ManRst_t * p; + p = 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 ); + 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 ); + 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 ); + PRT( "Cuts ", p->timeCut ); + PRT( "Resynthesis", p->timeRes ); + PRT( " BDD ", p->timeBdd ); + PRT( " DSD ", p->timeDsd ); + PRT( " Eval ", p->timeEval ); + PRT( "AIG update ", p->timeNtk ); + PRT( "TOTAL ", p->timeTotal ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcRewrite.c b/src/base/abci/abcRewrite.c index b3b30d9a..f3360421 100644 --- a/src/base/abci/abcRewrite.c +++ b/src/base/abci/abcRewrite.c @@ -96,6 +96,14 @@ Rwr_ManAddTimeCuts( pManRwr, clock() - clk ); { Dec_Graph_t * pGraph = Rwr_ManReadDecs(pManRwr); int fCompl = Rwr_ManReadCompl(pManRwr); +/* + if ( nGain > 0 ) + { // print stats on the MFFC + extern void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode ); + printf( "Node %6d : Gain = %4d ", pNode->Id, nGain ); + Abc_NodeMffsConeSuppPrint( pNode ); + } +*/ // complement the FF if needed if ( fCompl ) Dec_GraphComplement( pGraph ); clk = clock(); diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c index 9c650aa9..5376444b 100644 --- a/src/base/abci/abcSat.c +++ b/src/base/abci/abcSat.c @@ -24,13 +24,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static int Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars ); -static int Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ); - -static solver * Abc_NtkMiterSatCreate2( Abc_Ntk_t * pNtk ); - static Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); - static nMuxes; //////////////////////////////////////////////////////////////////////// @@ -48,13 +42,13 @@ static nMuxes; SeeAlso [] ***********************************************************************/ -int Abc_NtkMiterSat_OldAndRusty( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose ) +int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fVerbose ) { solver * pSat; lbool status; int RetValue, clk; - assert( Abc_NtkIsBddLogic(pNtk) ); + assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkLatchNum(pNtk) == 0 ); if ( Abc_NtkPoNum(pNtk) > 1 ) @@ -84,7 +78,7 @@ int Abc_NtkMiterSat_OldAndRusty( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose ) clk = clock(); if ( fVerbose ) pSat->verbosity = 1; - status = solver_solve( pSat, NULL, NULL, nSeconds ); + status = solver_solve( pSat, NULL, NULL, nConfLimit, nImpLimit ); if ( status == l_Undef ) { // printf( "The problem timed out.\n" ); @@ -107,277 +101,6 @@ int Abc_NtkMiterSat_OldAndRusty( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose ) // if the problem is SAT, get the counterexample if ( status == l_True ) { - Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk ); - pNtk->pModel = solver_get_model( pSat, vCiIds->pArray, vCiIds->nSize ); - Vec_IntFree( vCiIds ); - } - // free the solver - solver_delete( pSat ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Sets up the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk ) -{ - solver * pSat; - Extra_MmFlex_t * pMmFlex; - Abc_Obj_t * pNode; - Vec_Str_t * vCube; - Vec_Int_t * vVars; - char * pSop0, * pSop1; - int i, clk = clock(); - - assert( Abc_NtkIsBddLogic(pNtk) ); - - // start the data structures - pSat = solver_new(); - pMmFlex = Extra_MmFlexStart(); - 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, &pSop0, &pSop1 ); - // add the clauses to the solver - if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) ) - { - solver_delete( pSat ); - return NULL; - } - } - // add clauses for the POs - if ( !Abc_NodeAddClausesTop( pSat, Abc_NtkPo(pNtk, Abc_NtkPoNum(pNtk)-1), vVars ) ) - { - solver_delete( pSat ); - return NULL; - } -// Asat_SolverWriteDimacs( pSat, "test.cnf", NULL, NULL, 0 ); - - PRT( "Creating solver", clock() - clk ); - - // delete - Vec_StrFree( vCube ); - Vec_IntFree( vVars ); - Extra_MmFlexStop( pMmFlex, 0 ); - return pSat; -} - -/**Function************************************************************* - - Synopsis [Adds clauses for the internal node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars ) -{ - Abc_Obj_t * pFanin; - int i, c, nFanins; - char * pCube; - - nFanins = Abc_ObjFaninNum( pNode ); - assert( nFanins == Abc_SopGetVarNum( pSop0 ) ); - - if ( nFanins == 0 ) - { - vVars->nSize = 0; - if ( Abc_SopIsConst1(pSop1) ) - Vec_IntPush( vVars, toLit(pNode->Id) ); - else - Vec_IntPush( vVars, neg(toLit(pNode->Id)) ); - return solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - } - - // 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, neg(toLit(pFanin->Id)) ); - } - Vec_IntPush( vVars, neg(toLit(pNode->Id)) ); - if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - 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, neg(toLit(pFanin->Id)) ); - } - Vec_IntPush( vVars, toLit(pNode->Id) ); - if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds clauses for the PO node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) -{ - Abc_Obj_t * pFanin; - - pFanin = Abc_ObjFanin0(pNode); - if ( Abc_ObjFaninC0(pNode) ) - { - vVars->nSize = 0; - Vec_IntPush( vVars, toLit(pFanin->Id) ); - Vec_IntPush( vVars, toLit(pNode->Id) ); - if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - - vVars->nSize = 0; - Vec_IntPush( vVars, neg(toLit(pFanin->Id)) ); - Vec_IntPush( vVars, neg(toLit(pNode->Id)) ); - if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - } - else - { - vVars->nSize = 0; - Vec_IntPush( vVars, neg(toLit(pFanin->Id)) ); - Vec_IntPush( vVars, toLit(pNode->Id) ); - if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - - vVars->nSize = 0; - Vec_IntPush( vVars, toLit(pFanin->Id) ); - Vec_IntPush( vVars, neg(toLit(pNode->Id)) ); - if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - } - - vVars->nSize = 0; - Vec_IntPush( vVars, toLit(pNode->Id) ); - return solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); -} - - - - - - - - - - - -/**Function************************************************************* - - Synopsis [Attempts to solve the miter using an internal SAT solver.] - - Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose ) -{ - solver * pSat; - lbool status; - int RetValue, clk; - - assert( Abc_NtkIsStrash(pNtk) ); - 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 solver - clk = clock(); - pSat = Abc_NtkMiterSatCreate2( pNtk ); - if ( pSat == NULL ) - return 1; -// printf( "Created SAT problem with %d variable and %d clauses. ", solver_nvars(pSat), solver_nclauses(pSat) ); -// PRT( "Time", clock() - clk ); - - // simplify the problem - clk = clock(); - status = solver_simplify(pSat); -// printf( "Simplified the problem to %d variables and %d clauses. ", solver_nvars(pSat), solver_nclauses(pSat) ); -// PRT( "Time", clock() - clk ); - if ( status == 0 ) - { - solver_delete( pSat ); -// printf( "The problem is UNSATISFIABLE after simplification.\n" ); - return 1; - } - - // solve the miter - clk = clock(); - if ( fVerbose ) - pSat->verbosity = 1; - status = solver_solve( pSat, NULL, NULL, nSeconds ); - 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 solver time", clock() - clk ); - - // 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 = solver_get_model( pSat, vCiIds->pArray, vCiIds->nSize ); @@ -411,7 +134,6 @@ Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ) } - /**Function************************************************************* @@ -669,7 +391,7 @@ void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNo SeeAlso [] ***********************************************************************/ -int Abc_NtkMiterSatCreate2Int( solver * pSat, Abc_Ntk_t * pNtk ) +int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE; Vec_Ptr_t * vNodes, * vSuper; @@ -787,7 +509,7 @@ int Abc_NtkMiterSatCreate2Int( solver * pSat, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -solver * Abc_NtkMiterSatCreate2( Abc_Ntk_t * pNtk ) +solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk ) { solver * pSat; Abc_Obj_t * pNode; @@ -796,7 +518,7 @@ solver * Abc_NtkMiterSatCreate2( Abc_Ntk_t * pNtk ) nMuxes = 0; pSat = solver_new(); - RetValue = Abc_NtkMiterSatCreate2Int( pSat, pNtk ); + RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk ); Abc_NtkForEachObj( pNtk, pNode, i ) pNode->fMarkA = 0; // Asat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 ); @@ -805,8 +527,8 @@ solver * Abc_NtkMiterSatCreate2( Abc_Ntk_t * pNtk ) solver_delete(pSat); return NULL; } - printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); - PRT( "Creating solver", clock() - clk ); +// printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); +// PRT( "Creating solver", clock() - clk ); return pSat; } diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c index 00370002..34757145 100644 --- a/src/base/abci/abcUnreach.c +++ b/src/base/abci/abcUnreach.c @@ -285,7 +285,7 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn // start the new network pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD ); - pNtkNew->pName = util_strsav( "exdc" ); + pNtkNew->pName = Extra_UtilStrsav( "exdc" ); pNtkNew->pSpec = NULL; // create PIs corresponding to LOs diff --git a/src/base/abci/abcVanEijk.c b/src/base/abci/abcVanEijk.c index f8d659a0..d719df4f 100644 --- a/src/base/abci/abcVanEijk.c +++ b/src/base/abci/abcVanEijk.c @@ -517,13 +517,13 @@ Abc_Ntk_t * Abc_NtkVanEijkFrames( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCorresp, int nF pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); if ( fShortNames ) { - pNtkFrames->pName = util_strsav(pNtk->pName); - pNtkFrames->pSpec = util_strsav(pNtk->pSpec); + pNtkFrames->pName = Extra_UtilStrsav(pNtk->pName); + pNtkFrames->pSpec = Extra_UtilStrsav(pNtk->pSpec); } else { sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames + fAddLast ); - pNtkFrames->pName = util_strsav(Buffer); + pNtkFrames->pName = Extra_UtilStrsav(Buffer); } // map the constant nodes Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkFrames); @@ -722,7 +722,7 @@ Abc_Ntk_t * Abc_NtkVanEijkDeriveExdc( Abc_Ntk_t * pNtk, Vec_Ptr_t * vClasses ) // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc ); - pNtkNew->pName = util_strsav("exdc"); + pNtkNew->pName = Extra_UtilStrsav("exdc"); pNtkNew->pSpec = NULL; // map the constant nodes diff --git a/src/base/abci/abcVanImp.c b/src/base/abci/abcVanImp.c index 693d0af7..1805378c 100644 --- a/src/base/abci/abcVanImp.c +++ b/src/base/abci/abcVanImp.c @@ -878,7 +878,7 @@ Abc_Ntk_t * Abc_NtkVanImpDeriveExdc( Abc_Ntk_t * pNtk, Vec_Ptr_t * vZeros, Vec_I // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc ); - pNtkNew->pName = util_strsav( "exdc" ); + pNtkNew->pName = Extra_UtilStrsav( "exdc" ); pNtkNew->pSpec = NULL; // map the constant nodes diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c index 99392e48..5c7b525e 100644 --- a/src/base/abci/abcVerify.c +++ b/src/base/abci/abcVerify.c @@ -46,7 +46,7 @@ static void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, SeeAlso [] ***********************************************************************/ -void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds ) +void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nImpLimit ) { Abc_Ntk_t * pMiter; Abc_Ntk_t * pCnf; @@ -87,7 +87,7 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds ) } // solve the CNF using the SAT solver - RetValue = Abc_NtkMiterSat( pCnf, nSeconds, 0 ); + RetValue = Abc_NtkMiterSat( pCnf, nConfLimit, nImpLimit, 0 ); if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out).\n" ); else if ( RetValue == 0 ) @@ -184,7 +184,7 @@ void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fV SeeAlso [] ***********************************************************************/ -void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames ) +void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nImpLimit, int nFrames ) { Abc_Ntk_t * pMiter; Abc_Ntk_t * pFrames; @@ -244,7 +244,7 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFra } // solve the CNF using the SAT solver - RetValue = Abc_NtkMiterSat( pCnf, nSeconds, 0 ); + RetValue = Abc_NtkMiterSat( pCnf, nConfLimit, nImpLimit, 0 ); if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out).\n" ); else if ( RetValue == 0 ) diff --git a/src/base/abci/module.make b/src/base/abci/module.make index 5b15641b..3ca188b7 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -2,9 +2,11 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcAttach.c \ src/base/abci/abcAuto.c \ src/base/abci/abcBalance.c \ - src/base/abci/abcCollapse.c \ + src/base/abci/abcClpBdd.c \ + src/base/abci/abcClpSop.c \ src/base/abci/abcCut.c \ src/base/abci/abcDsd.c \ + src/base/abci/abcEspresso.c \ src/base/abci/abcFpga.c \ src/base/abci/abcFraig.c \ src/base/abci/abcFxu.c \ @@ -13,6 +15,7 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcNtbdd.c \ src/base/abci/abcPga.c \ src/base/abci/abcPrint.c \ + src/base/abci/abcProve.c \ src/base/abci/abcReconv.c \ src/base/abci/abcRefactor.c \ src/base/abci/abcRenode.c \ diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index b2a90806..21dba247 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -142,8 +142,8 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -154,7 +154,7 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) } } - if ( argc != util_optind ) + if ( argc != globalUtilOptind ) { goto usage; } @@ -188,8 +188,8 @@ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv ) int c; int n = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "hn" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF ) { switch ( c ) { @@ -204,7 +204,7 @@ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv ) } } - for ( i = util_optind; i < argc; i++ ) + for ( i = globalUtilOptind; i < argc; i++ ) fprintf( pAbc->Out, "%s ", argv[i] ); if ( n ) fprintf( pAbc->Out, "\n" ); @@ -234,8 +234,8 @@ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "hs" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF ) { switch ( c ) { @@ -250,7 +250,7 @@ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv ) } } - if ( argc != util_optind ) + if ( argc != globalUtilOptind ) goto usage; return -1; @@ -294,8 +294,8 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) int i, c, num, size; num = 20; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -309,8 +309,8 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) goto usage; // get the number of commands to print - if ( argc == util_optind + 1 ) - num = atoi(argv[util_optind]); + if ( argc == globalUtilOptind + 1 ) + num = atoi(argv[globalUtilOptind]); // print the commands size = pAbc->aHistory->nSize; num = ( num < size ) ? num : size; @@ -342,8 +342,8 @@ int CmdCommandAlias( Abc_Frame_t * pAbc, int argc, char **argv ) char *key, *value; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -399,8 +399,8 @@ int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv ) char *key, *value; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -450,8 +450,8 @@ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv ) int c; fPrintAll = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ah" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) { switch ( c ) { @@ -468,7 +468,7 @@ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv ) } } - if ( argc != util_optind ) + if ( argc != globalUtilOptind ) goto usage; CmdCommandPrint( pAbc, fPrintAll ); @@ -503,8 +503,8 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) interactive = silent = prompt = echo = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "hipsx" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "hipsx" ) ) != EOF ) { switch ( c ) { @@ -529,12 +529,12 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) } /* added to avoid core-dumping when no script file is specified */ - if ( argc == util_optind ) + if ( argc == globalUtilOptind ) { goto usage; } - lp_file_index = util_optind; + lp_file_index = globalUtilOptind; lp_count = 0; /* @@ -568,7 +568,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) } else { - prompt_string = NIL( char ); + prompt_string = NULL; } /* clear errors -- e.g., EOF reached from stdin */ @@ -602,7 +602,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pAbc->Out, "abc - > %s", line ); } command = CmdHistorySubstitution( pAbc, line, &did_subst ); - if ( command == NIL( char ) ) + if ( command == NULL ) { status = 1; break; @@ -620,8 +620,8 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) } if ( interactive && *line != '\0' ) { - Cmd_HistoryAddCommand( pAbc, util_strsav(line) ); - if ( pAbc->Hst != NIL( FILE ) ) + Cmd_HistoryAddCommand( pAbc, Extra_UtilStrsav(line) ); + if ( pAbc->Hst != NULL ) { fprintf( pAbc->Hst, "%s\n", line ); ( void ) fflush( pAbc->Hst ); @@ -674,8 +674,8 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) char *flag_value, *key, *value; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -703,9 +703,9 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) FREE( value ); } - flag_value = argc == 2 ? util_strsav( "" ) : util_strsav( argv[2] ); -// flag_value = argc == 2 ? NULL : util_strsav(argv[2]); - st_insert( pAbc->tFlags, util_strsav(argv[1]), flag_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 ) { @@ -713,7 +713,7 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) fclose( pAbc->Out ); if ( strcmp( flag_value, "" ) == 0 ) flag_value = "-"; - pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 ); + pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); if ( pAbc->Out == NULL ) pAbc->Out = stdout; #if HAVE_SETVBUF @@ -726,7 +726,7 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) fclose( pAbc->Err ); if ( strcmp( flag_value, "" ) == 0 ) flag_value = "-"; - pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 ); + pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); if ( pAbc->Err == NULL ) pAbc->Err = stderr; #if HAVE_SETVBUF @@ -735,15 +735,15 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) } if ( strcmp( argv[1], "history" ) == 0 ) { - if ( pAbc->Hst != NIL( FILE ) ) + if ( pAbc->Hst != NULL ) fclose( pAbc->Hst ); if ( strcmp( flag_value, "" ) == 0 ) - pAbc->Hst = NIL( FILE ); + pAbc->Hst = NULL; else { - pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 ); + pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); if ( pAbc->Hst == NULL ) - pAbc->Hst = NIL( FILE ); + pAbc->Hst = NULL; } } return 0; @@ -774,8 +774,8 @@ int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) char *key, *value; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -867,8 +867,8 @@ int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv ) } - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -979,8 +979,8 @@ int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1021,7 +1021,7 @@ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) Abc_Ntk_t * pNtkTemp; int id, c; - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1032,12 +1032,12 @@ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) goto usage; } } - if (util_optind <= argc) { + if (globalUtilOptind <= argc) { pNtkTemp = pAbc->pNtk; pAbc->pNtk = pAbc->pNtkSaved; pAbc->pNtkSaved = pNtkTemp; } - id = atoi(argv[util_optind]); + id = atoi(argv[globalUtilOptind]); pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id); if (!pNtkTemp) fprintf( pAbc->Err, "Snapshot %d does not exist\n", id); @@ -1095,8 +1095,8 @@ int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv ) int fPrintedNewLine; char c; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "lb") ) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF ) { switch (c) { @@ -1294,7 +1294,7 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) if ( pNtk->pSpec ) { FREE( pNtkNew->pSpec ); - pNtkNew->pSpec = util_strsav( pNtk->pSpec ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); @@ -1430,7 +1430,7 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) if ( pNtk->pSpec ) { FREE( pNtkNew->pSpec ); - pNtkNew->pSpec = util_strsav( pNtk->pSpec ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); diff --git a/src/base/cmd/cmdAlias.c b/src/base/cmd/cmdAlias.c index beb7a566..0ec3feea 100644 --- a/src/base/cmd/cmdAlias.c +++ b/src/base/cmd/cmdAlias.c @@ -45,11 +45,11 @@ void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** arg int fStatus, i; pAlias = ALLOC(Abc_Alias, 1); - pAlias->sName = util_strsav(sName); + pAlias->sName = Extra_UtilStrsav(sName); pAlias->argc = argc; pAlias->argv = ALLOC(char *, pAlias->argc); for(i = 0; i < argc; i++) - pAlias->argv[i] = util_strsav(argv[i]); + pAlias->argv[i] = Extra_UtilStrsav(argv[i]); fStatus = st_insert( pAbc->tAliases, pAlias->sName, (char *) pAlias ); assert(!fStatus); } diff --git a/src/base/cmd/cmdApi.c b/src/base/cmd/cmdApi.c index cc3d5806..7167e22b 100644 --- a/src/base/cmd/cmdApi.c +++ b/src/base/cmd/cmdApi.c @@ -57,8 +57,8 @@ void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFu // create the new command pCommand = ALLOC( Abc_Command, 1 ); - pCommand->sName = util_strsav( sName ); - pCommand->sGroup = util_strsav( sGroup ); + pCommand->sName = Extra_UtilStrsav( sName ); + pCommand->sGroup = Extra_UtilStrsav( sGroup ); pCommand->pFunc = pFunc; pCommand->fChange = fChanges; fStatus = st_insert( pAbc->tCommands, sName, (char *)pCommand ); diff --git a/src/base/cmd/cmdFlag.c b/src/base/cmd/cmdFlag.c index 267f8e06..993f2a49 100644 --- a/src/base/cmd/cmdFlag.c +++ b/src/base/cmd/cmdFlag.c @@ -35,8 +35,7 @@ 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 NIL(char) is returned if the flag has not been - set.] + named flag is returned, or NULL is returned if the flag has not been set.] SideEffects [] @@ -65,9 +64,9 @@ void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value ) if ( !key ) return; if ( value ) - newValue = util_strsav(value); + newValue = Extra_UtilStrsav(value); else - newValue = util_strsav(""); + newValue = Extra_UtilStrsav(""); // newValue = NULL; if ( st_delete(pAbc->tFlags, &key, &oldValue) ) FREE(oldValue); diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c index dae293d7..12750d16 100644 --- a/src/base/cmd/cmdHist.c +++ b/src/base/cmd/cmdHist.c @@ -47,7 +47,7 @@ void Cmd_HistoryAddCommand( Abc_Frame_t * p, char * command ) strcpy( Buffer, command ); if ( command[strlen(command)-1] != '\n' ) strcat( Buffer, "\n" ); - Vec_PtrPush( p->aHistory, util_strsav(Buffer) ); + Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c index 9b7fb49f..47e54bb3 100644 --- a/src/base/cmd/cmdUtils.c +++ b/src/base/cmd/cmdUtils.c @@ -121,10 +121,10 @@ int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char **argv ) } // execute the command - clk = util_cpu_time(); + clk = Extra_CpuTime(); pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc; fError = (*pFunc)( pAbc, argc, argv ); - pAbc->TimeCommand += (util_cpu_time() - clk); + pAbc->TimeCommand += (Extra_CpuTime() - clk); // automatic execution of arbitrary command after each command // usually this is a passive command ... @@ -270,7 +270,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) } for ( i = 1; i <= added; i++ ) { - argv[i] = NIL( char ); + argv[i] = NULL; } argc += added; } @@ -278,7 +278,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) for ( i = 0, offset = 0; i < alias->argc; i++, offset++ ) { arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst ); - if ( arg == NIL( char ) ) + if ( arg == NULL ) { *argcp = argc; *argvp = argv; @@ -383,11 +383,11 @@ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFi if (strcmp(sFileName, "-") == 0) { if (strcmp(sMode, "w") == 0) { - sRealName = util_strsav( "stdout" ); + sRealName = Extra_UtilStrsav( "stdout" ); pFile = stdout; } else { - sRealName = util_strsav( "stdin" ); + sRealName = Extra_UtilStrsav( "stdin" ); pFile = stdin; } } @@ -403,24 +403,24 @@ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFi sPathAll = NULL; } else if ( sPathUsr == NULL ) { - sPathAll = util_strsav( sPathLib ); + sPathAll = Extra_UtilStrsav( sPathLib ); } else if ( sPathLib == NULL ) { - sPathAll = util_strsav( sPathUsr ); + sPathAll = Extra_UtilStrsav( sPathUsr ); } else { sPathAll = ALLOC( char, strlen(sPathLib)+strlen(sPathUsr)+5 ); sprintf( sPathAll, "%s:%s",sPathUsr, sPathLib ); } - if ( sPathAll != NIL(char) ) { - sRealName = util_file_search(sFileName, sPathAll, "r"); + if ( sPathAll != NULL ) { + sRealName = Extra_UtilFileSearch(sFileName, sPathAll, "r"); FREE( sPathAll ); } } - if (sRealName == NIL(char)) { - sRealName = util_tilde_expand(sFileName); + if (sRealName == NULL) { + sRealName = Extra_UtilTildeExpand(sFileName); } - if ((pFile = fopen(sRealName, sMode)) == NIL(FILE)) { + if ((pFile = fopen(sRealName, sMode)) == NULL) { if (! silent) { perror(sRealName); } diff --git a/src/base/io/io.c b/src/base/io/io.c index 69b60000..2725eb8a 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -120,8 +120,8 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -135,13 +135,13 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -192,8 +192,8 @@ int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -207,13 +207,13 @@ int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -265,8 +265,8 @@ int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -280,13 +280,13 @@ int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -346,8 +346,8 @@ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -361,13 +361,13 @@ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -426,8 +426,8 @@ int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -441,13 +441,13 @@ int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -506,8 +506,8 @@ int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -521,13 +521,13 @@ int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -586,8 +586,8 @@ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -601,13 +601,13 @@ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -666,8 +666,8 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fCheck = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { @@ -681,13 +681,13 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); @@ -745,8 +745,8 @@ int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; fHex = 0; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "xh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF ) { switch ( c ) { @@ -760,16 +760,16 @@ int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) } } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // convert truth table to SOP if ( fHex ) - pSopCover = Abc_SopFromTruthHex(argv[util_optind]); + pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]); else - pSopCover = Abc_SopFromTruthBin(argv[util_optind]); + pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]); if ( pSopCover == NULL ) { fprintf( pAbc->Err, "Reading truth table has failed.\n" ); @@ -814,8 +814,8 @@ int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv ) char * FileName; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { @@ -833,11 +833,11 @@ int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // check the network type if ( !Abc_NtkIsStrash(pNtk) ) @@ -875,8 +875,8 @@ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) int c; fWriteLatches = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { @@ -897,11 +897,11 @@ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // check the network type if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSeq(pNtk) ) @@ -941,8 +941,8 @@ int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv ) int c; fWriteLatches = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { @@ -963,12 +963,12 @@ int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( !Abc_NtkIsStrash(pNtk) ) { @@ -1012,8 +1012,8 @@ int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv ) char * FileName; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1026,17 +1026,22 @@ int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv ) if ( pAbc->pNtkCur == NULL ) { - fprintf( pAbc->Out, "Empty network.\n" ); + printf( "Empty network.\n" ); return 0; } + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + printf( "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // write the file if ( !Io_WriteCnf( pAbc->pNtkCur, FileName ) ) { @@ -1070,8 +1075,8 @@ int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) Vec_Ptr_t * vNodes; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1094,13 +1099,13 @@ int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // write the file vNodes = Abc_NtkCollectObjects( pAbc->pNtkCur ); Io_WriteDotAig( pAbc->pNtkCur, vNodes, NULL, FileName, 0 ); @@ -1132,8 +1137,8 @@ int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) char * FileName; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1151,7 +1156,7 @@ int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } @@ -1163,7 +1168,7 @@ int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // write the file // get rid of complemented covers if present if ( Abc_NtkIsSopLogic(pNtk) ) @@ -1203,8 +1208,8 @@ int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) char * FileName; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1227,13 +1232,13 @@ int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // write the file Io_WriteGml( pAbc->pNtkCur, FileName ); return 0; @@ -1264,8 +1269,8 @@ int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv ) int c; fUseHost = 1; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) { switch ( c ) { @@ -1291,13 +1296,13 @@ int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // write the file Io_WriteList( pAbc->pNtkCur, FileName, fUseHost ); return 0; @@ -1328,8 +1333,8 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) char * FileName; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1359,12 +1364,12 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // derive the netlist pNtkTemp = Abc_NtkLogicToNetlist(pNtk); @@ -1402,8 +1407,8 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) char * FileName; int c; - util_getopt_reset(); - while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF ) + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { @@ -1421,12 +1426,12 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; // derive the netlist pNtkTemp = Abc_NtkLogicToNetlist(pNtk); diff --git a/src/base/io/ioReadBaf.c b/src/base/io/ioReadBaf.c index 2d6c3ca6..e2aa2109 100644 --- a/src/base/io/ioReadBaf.c +++ b/src/base/io/ioReadBaf.c @@ -74,8 +74,8 @@ Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ) // allocate the empty AIG pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); - pNtkNew->pName = util_strsav( pName ); - pNtkNew->pSpec = util_strsav( pFileName ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); // prepare the array of nodes vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c index c05f444e..39b85a10 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -230,7 +230,7 @@ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) vTokens->nSize--; // load them into the new array for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) ); + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); // load as long as there is the line break while ( 1 ) @@ -249,12 +249,12 @@ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) vTokens->nSize--; // load them into the new array for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) ); + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); continue; } // otherwise, load them and break for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) ); + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); break; } return p->vNewTokens; @@ -294,8 +294,8 @@ Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) pModelName = vTokens->pArray[1]; // allocate the empty network p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP ); - p->pNtk->pName = util_strsav( pModelName ); - p->pNtk->pSpec = util_strsav( p->pFileName ); + p->pNtk->pName = Extra_UtilStrsav( pModelName ); + p->pNtk->pSpec = Extra_UtilStrsav( p->pFileName ); } else p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP ); @@ -681,7 +681,7 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) return 1; } // set the arrival time - Abc_NtkTimeSetArrival( p->pNtk, pNet->Id, (float)TimeRise, (float)TimeFall ); + Abc_NtkTimeSetArrival( p->pNtk, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); return 0; } diff --git a/src/base/io/ioReadEdif.c b/src/base/io/ioReadEdif.c index f100a45f..3bdf2567 100644 --- a/src/base/io/ioReadEdif.c +++ b/src/base/io/ioReadEdif.c @@ -181,7 +181,7 @@ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) else if ( strcmp( vTokens->pArray[0], "design" ) == 0 ) { free( pNtk->pName ); - pNtk->pName = util_strsav( vTokens->pArray[3] ); + pNtk->pName = Extra_UtilStrsav( vTokens->pArray[3] ); break; } } diff --git a/src/base/io/ioReadEqn.c b/src/base/io/ioReadEqn.c index a5a46f40..4fb313f4 100644 --- a/src/base/io/ioReadEqn.c +++ b/src/base/io/ioReadEqn.c @@ -145,7 +145,7 @@ Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) continue; } // determine unique variables - pCubesCopy = util_strsav( pCubesCopy ); + pCubesCopy = Extra_UtilStrsav( pCubesCopy ); // find the names of the fanins of this node Io_ReadEqnStrCutAt( pCubesCopy, "!*+", 1, vVars ); // create the node diff --git a/src/base/io/ioReadVerilog.c b/src/base/io/ioReadVerilog.c index 58071e39..a4610cac 100644 --- a/src/base/io/ioReadVerilog.c +++ b/src/base/io/ioReadVerilog.c @@ -272,8 +272,8 @@ Abc_Ntk_t * Io_ReadVerNetwork( Io_ReadVer_t * p ) // allocate the empty network pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP ); - pNtk->pName = util_strsav( pModelName ); - pNtk->pSpec = util_strsav( p->pFileName ); + pNtk->pName = Extra_UtilStrsav( pModelName ); + pNtk->pSpec = Extra_UtilStrsav( p->pFileName ); // create constant nodes and nets Abc_NtkFindOrCreateNet( pNtk, "1'b0" ); @@ -334,7 +334,7 @@ Abc_Ntk_t * Io_ReadVerNetwork( Io_ReadVer_t * p ) } // add the tri-state element to the skipped ones sprintf( Buffer, "%s %s", vTokens->pArray[0], vTokens->pArray[1] ); - Vec_PtrPush( p->vSkipped, util_strsav(Buffer) ); + Vec_PtrPush( p->vSkipped, Extra_UtilStrsav(Buffer) ); } Extra_ProgressBarStop( pProgress ); diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index e817bee8..fc37bc3f 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -223,7 +223,7 @@ FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mo { char ActualFileName[4096]; FILE * fp = 0; - t = util_strsav( c ); + t = Extra_UtilStrsav( c ); for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") ) { #ifdef WIN32 diff --git a/src/base/io/ioWriteCnf.c b/src/base/io/ioWriteCnf.c index f2131257..9e5ceb9f 100644 --- a/src/base/io/ioWriteCnf.c +++ b/src/base/io/ioWriteCnf.c @@ -42,19 +42,19 @@ int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName ) { solver * pSat; - if ( !Abc_NtkIsBddLogic(pNtk) ) + if ( !Abc_NtkIsStrash(pNtk) ) { - fprintf( stdout, "Io_WriteCnf(): Currently can only process logic networks with BDDs.\n" ); + fprintf( stdout, "Io_WriteCnf(): Currently can only process AIGs.\n" ); return 0; } if ( Abc_NtkPoNum(pNtk) != 1 ) { - fprintf( stdout, "Io_WriteCnf(): Currently can only solve the miter (the network with one PO).\n" ); + 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 solve the miter for combinational circuits.\n" ); + fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" ); return 0; } // create solver with clauses diff --git a/src/base/main/main.c b/src/base/main/main.c index a9f27bf8..1c6cbcb0 100644 --- a/src/base/main/main.c +++ b/src/base/main/main.c @@ -75,21 +75,21 @@ int main( int argc, char * argv[] ) sprintf( sReadCmd, "read" ); sprintf( sWriteCmd, "write" ); - util_getopt_reset(); - while ((c = util_getopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) { + Extra_UtilGetoptReset(); + while ((c = Extra_UtilGetopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) { switch(c) { case 'c': - strcpy( sCommandUsr, util_optarg ); + strcpy( sCommandUsr, globalUtilOptarg ); fBatch = 1; break; case 'f': - sprintf(sCommandUsr, "source %s", util_optarg); + sprintf(sCommandUsr, "source %s", globalUtilOptarg); fBatch = 1; break; case 'F': - sprintf(sCommandUsr, "source -x %s", util_optarg); + sprintf(sCommandUsr, "source -x %s", globalUtilOptarg); fBatch = 1; break; @@ -98,7 +98,7 @@ int main( int argc, char * argv[] ) break; case 'o': - sOutFile = util_optarg; + sOutFile = globalUtilOptarg; fFinalWrite = 1; break; @@ -107,12 +107,12 @@ int main( int argc, char * argv[] ) break; case 't': - if ( TypeCheck( pAbc, util_optarg ) ) + if ( TypeCheck( pAbc, globalUtilOptarg ) ) { - if ( !strcmp(util_optarg, "none") == 0 ) + if ( !strcmp(globalUtilOptarg, "none") == 0 ) { fInitRead = 1; - sprintf( sReadCmd, "read_%s", util_optarg ); + sprintf( sReadCmd, "read_%s", globalUtilOptarg ); } } else { @@ -122,12 +122,12 @@ int main( int argc, char * argv[] ) break; case 'T': - if ( TypeCheck( pAbc, util_optarg ) ) + if ( TypeCheck( pAbc, globalUtilOptarg ) ) { - if (!strcmp(util_optarg, "none") == 0) + if (!strcmp(globalUtilOptarg, "none") == 0) { fFinalWrite = 1; - sprintf( sWriteCmd, "write_%s", util_optarg); + sprintf( sWriteCmd, "write_%s", globalUtilOptarg); } } else { @@ -151,14 +151,14 @@ int main( int argc, char * argv[] ) { pAbc->fBatchMode = 1; - if (argc - util_optind == 0) + if (argc - globalUtilOptind == 0) { sInFile = NULL; } - else if (argc - util_optind == 1) + else if (argc - globalUtilOptind == 1) { fInitRead = 1; - sInFile = argv[util_optind]; + sInFile = argv[globalUtilOptind]; } else { @@ -221,10 +221,7 @@ int main( int argc, char * argv[] ) // if the memory should be freed, quit packages if ( fStatus < 0 ) { - // perform uninitializations - Abc_FrameEnd( pAbc ); - // stop the framework - Abc_FrameDeallocate( pAbc ); + Abc_Stop(); } return 0; @@ -250,16 +247,12 @@ usage: void Abc_Start() { Abc_Frame_t * pAbc; - // added to detect memory leaks: #ifdef _DEBUG _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif - - // get global frame (singleton pattern) - // will be initialized on first call + // start the glocal frame pAbc = Abc_FrameGetGlobalFrame(); - // source the resource file // Abc_UtilsSource( pAbc ); } @@ -278,17 +271,11 @@ void Abc_Start() void Abc_Stop() { Abc_Frame_t * pAbc; - int fStatus = 0; - - // if the memory should be freed, quit packages - if ( fStatus == -2 ) - { - pAbc = Abc_FrameGetGlobalFrame(); - // perform uninitializations - Abc_FrameEnd( pAbc ); - // stop the framework - Abc_FrameDeallocate( pAbc ); - } + pAbc = Abc_FrameGetGlobalFrame(); + // perform uninitializations + Abc_FrameEnd( pAbc ); + // stop the framework + Abc_FrameDeallocate( pAbc ); } /**Function******************************************************************** diff --git a/src/base/main/main.h b/src/base/main/main.h index c5f311aa..d5a463f5 100644 --- a/src/base/main/main.h +++ b/src/base/main/main.h @@ -40,17 +40,10 @@ typedef struct Abc_Frame_t_ Abc_Frame_t; // it is used to catch memory leaks on Windows #include "leaks.h" -// standard includes -#include <stdio.h> -#include <string.h> - -// includes from GLU -#include "util.h" -#include "st.h" - // data structure packages #include "extra.h" #include "vec.h" +#include "st.h" // core packages #include "abc.h" diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c index e9e243af..b3208740 100644 --- a/src/base/main/mainFrame.c +++ b/src/base/main/mainFrame.c @@ -48,8 +48,8 @@ int Abc_FrameReadNtkStoreSize() { return s_GlobalFrame->nSt void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; } void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; } void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; } -void * Abc_FrameReadManDd() { return s_GlobalFrame->dd; } -void * Abc_FrameReadManDec() { return s_GlobalFrame->pManDec; } +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; } +void * Abc_FrameReadManDec() { if ( s_GlobalFrame->pManDec == NULL ) s_GlobalFrame->pManDec = Dec_ManStart(); return s_GlobalFrame->pManDec; } char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); } void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ) { s_GlobalFrame->pStored = pNtk; } @@ -97,7 +97,8 @@ bool Abc_FrameIsFlagEnabled( char * pFlag ) 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 = ALLOC( Abc_Frame_t, 1 ); memset( p, 0, sizeof(Abc_Frame_t) ); @@ -111,8 +112,8 @@ Abc_Frame_t * Abc_FrameAllocate() p->nSteps = 1; p->fBatchMode = 0; // initialize decomposition manager - p->pManDec = Dec_ManStart(); - p->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + define_cube_size(20); + set_espresso_flags(); return p; } @@ -130,11 +131,13 @@ Abc_Frame_t * Abc_FrameAllocate() ***********************************************************************/ void Abc_FrameDeallocate( Abc_Frame_t * p ) { - Dec_ManStop( p->pManDec ); - Extra_StopManager( p->dd ); + extern void undefine_cube_size(); + undefine_cube_size(); + if ( p->pManDec ) Dec_ManStop( p->pManDec ); + if ( p->dd ) Extra_StopManager( p->dd ); Abc_FrameDeleteAllNetworks( p ); free( p ); - p = NULL; + s_GlobalFrame = NULL; } /**Function************************************************************* diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index aa8b63d0..3d0bdc33 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -139,8 +139,8 @@ void Abc_UtilsSource( Abc_Frame_t * pAbc ) // 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 = util_file_search(".rc", "~/", "r"); - sPath2 = util_file_search(".rc", ".", "r"); + sPath1 = Extra_UtilFileSearch(".rc", "~/", "r"); + sPath2 = Extra_UtilFileSearch(".rc", ".", "r"); if ( sPath1 && sPath2 ) { /* ~/.rc == .rc : Source the file only once */ diff --git a/src/base/seq/seqAigCore.c b/src/base/seq/seqAigCore.c index ed2a33fc..e74f3fa7 100644 --- a/src/base/seq/seqAigCore.c +++ b/src/base/seq/seqAigCore.c @@ -343,7 +343,7 @@ int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int } // get the miter cone - pNtkMiter = Abc_NtkCreateCone( pNtkProb, pNtkProb->vCos, vValues ); + pNtkMiter = Abc_NtkCreateTarget( pNtkProb, pNtkProb->vCos, vValues ); Abc_NtkDelete( pNtkProb ); Vec_IntFree( vValues ); @@ -358,7 +358,7 @@ int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int // solve the miter clk = clock(); // RetValue = Abc_NtkMiterSat_OldAndRusty( pNtkCnf, 30, 0 ); - RetValue = Abc_NtkMiterSat( pNtkCnf, 30, 0 ); + RetValue = Abc_NtkMiterSat( pNtkCnf, 500000, 50000000, 0 ); if ( fVerbose ) if ( clock() - clk > 100 ) { diff --git a/src/base/seq/seqCreate.c b/src/base/seq/seqCreate.c index d94e8e82..b0c2e084 100644 --- a/src/base/seq/seqCreate.c +++ b/src/base/seq/seqCreate.c @@ -88,8 +88,8 @@ Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk ) // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG ); // duplicate the name and the spec - pNtkNew->pName = util_strsav(pNtk->pName); - pNtkNew->pSpec = util_strsav(pNtk->pSpec); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // map the constant nodes Abc_NtkCleanCopy( pNtk ); diff --git a/src/base/seq/seqRetCore.c b/src/base/seq/seqRetCore.c index b4795039..4aba069d 100644 --- a/src/base/seq/seqRetCore.c +++ b/src/base/seq/seqRetCore.c @@ -112,8 +112,8 @@ Abc_Ntk_t * Seq_NtkRetimeDerive( Abc_Ntk_t * pNtk, int fVerbose ) // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG ); // duplicate the name and the spec - pNtkNew->pName = util_strsav(pNtk->pName); - pNtkNew->pSpec = util_strsav(pNtk->pSpec); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // map the constant nodes Abc_NtkCleanCopy( pNtk ); diff --git a/src/bdd/cudd/cuddAPI.c b/src/bdd/cudd/cuddAPI.c index 2acde7cd..a16b82cf 100644 --- a/src/bdd/cudd/cuddAPI.c +++ b/src/bdd/cudd/cuddAPI.c @@ -164,7 +164,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddAbs.c b/src/bdd/cudd/cuddAddAbs.c index 27039908..b256ad0f 100644 --- a/src/bdd/cudd/cuddAddAbs.c +++ b/src/bdd/cudd/cuddAddAbs.c @@ -32,7 +32,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddApply.c b/src/bdd/cudd/cuddAddApply.c index 67649913..60c06de6 100644 --- a/src/bdd/cudd/cuddAddApply.c +++ b/src/bdd/cudd/cuddAddApply.c @@ -42,7 +42,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddFind.c b/src/bdd/cudd/cuddAddFind.c index 3399527a..0469b014 100644 --- a/src/bdd/cudd/cuddAddFind.c +++ b/src/bdd/cudd/cuddAddFind.c @@ -27,7 +27,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddInv.c b/src/bdd/cudd/cuddAddInv.c index cb6dbfbe..fc4a340b 100644 --- a/src/bdd/cudd/cuddAddInv.c +++ b/src/bdd/cudd/cuddAddInv.c @@ -24,7 +24,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddAddIte.c b/src/bdd/cudd/cuddAddIte.c index 77c4d18a..71f8070f 100644 --- a/src/bdd/cudd/cuddAddIte.c +++ b/src/bdd/cudd/cuddAddIte.c @@ -33,7 +33,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddAddNeg.c b/src/bdd/cudd/cuddAddNeg.c index 2420df64..bdb08ddc 100644 --- a/src/bdd/cudd/cuddAddNeg.c +++ b/src/bdd/cudd/cuddAddNeg.c @@ -26,7 +26,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddAddWalsh.c b/src/bdd/cudd/cuddAddWalsh.c index 980ee215..c6a67e34 100644 --- a/src/bdd/cudd/cuddAddWalsh.c +++ b/src/bdd/cudd/cuddAddWalsh.c @@ -26,7 +26,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddAndAbs.c b/src/bdd/cudd/cuddAndAbs.c index 3a6ce85f..5ec47beb 100644 --- a/src/bdd/cudd/cuddAndAbs.c +++ b/src/bdd/cudd/cuddAndAbs.c @@ -24,7 +24,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddAnneal.c b/src/bdd/cudd/cuddAnneal.c index dfc81e86..3d8b56b9 100644 --- a/src/bdd/cudd/cuddAnneal.c +++ b/src/bdd/cudd/cuddAnneal.c @@ -35,7 +35,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddApa.c b/src/bdd/cudd/cuddApa.c index 805a4dde..47ab51e8 100644 --- a/src/bdd/cudd/cuddApa.c +++ b/src/bdd/cudd/cuddApa.c @@ -28,7 +28,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddApprox.c b/src/bdd/cudd/cuddApprox.c index eb6813ff..debcf48b 100644 --- a/src/bdd/cudd/cuddApprox.c +++ b/src/bdd/cudd/cuddApprox.c @@ -51,7 +51,7 @@ #else #define DBL_MAX_EXP 1024 #endif -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddBddAbs.c b/src/bdd/cudd/cuddBddAbs.c index 20a8f15a..9552464e 100644 --- a/src/bdd/cudd/cuddBddAbs.c +++ b/src/bdd/cudd/cuddBddAbs.c @@ -35,7 +35,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddBddCorr.c b/src/bdd/cudd/cuddBddCorr.c index 47395ec7..c99324a8 100644 --- a/src/bdd/cudd/cuddBddCorr.c +++ b/src/bdd/cudd/cuddBddCorr.c @@ -30,7 +30,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddBddIte.c b/src/bdd/cudd/cuddBddIte.c index fe0c6500..b44e40de 100644 --- a/src/bdd/cudd/cuddBddIte.c +++ b/src/bdd/cudd/cuddBddIte.c @@ -44,7 +44,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddBridge.c b/src/bdd/cudd/cuddBridge.c index e7e5c89f..ccc0893f 100644 --- a/src/bdd/cudd/cuddBridge.c +++ b/src/bdd/cudd/cuddBridge.c @@ -44,7 +44,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddCache.c b/src/bdd/cudd/cuddCache.c index 6598948a..d9e40921 100644 --- a/src/bdd/cudd/cuddCache.c +++ b/src/bdd/cudd/cuddCache.c @@ -36,7 +36,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddCheck.c b/src/bdd/cudd/cuddCheck.c index 3db08dd6..aec8246d 100644 --- a/src/bdd/cudd/cuddCheck.c +++ b/src/bdd/cudd/cuddCheck.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddClip.c b/src/bdd/cudd/cuddClip.c index 3c728a56..4da296ef 100644 --- a/src/bdd/cudd/cuddClip.c +++ b/src/bdd/cudd/cuddClip.c @@ -33,7 +33,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddCof.c b/src/bdd/cudd/cuddCof.c index 0dfeff6c..f79e3f91 100644 --- a/src/bdd/cudd/cuddCof.c +++ b/src/bdd/cudd/cuddCof.c @@ -29,7 +29,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddCompose.c b/src/bdd/cudd/cuddCompose.c index 11c6cb7b..8c858051 100644 --- a/src/bdd/cudd/cuddCompose.c +++ b/src/bdd/cudd/cuddCompose.c @@ -55,7 +55,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddDecomp.c b/src/bdd/cudd/cuddDecomp.c index d9c28482..4fde7392 100644 --- a/src/bdd/cudd/cuddDecomp.c +++ b/src/bdd/cudd/cuddDecomp.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddEssent.c b/src/bdd/cudd/cuddEssent.c index 7bd48c5a..db4b8b49 100644 --- a/src/bdd/cudd/cuddEssent.c +++ b/src/bdd/cudd/cuddEssent.c @@ -25,7 +25,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddExact.c b/src/bdd/cudd/cuddExact.c index 6a81406b..6852be68 100644 --- a/src/bdd/cudd/cuddExact.c +++ b/src/bdd/cudd/cuddExact.c @@ -40,7 +40,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddExport.c b/src/bdd/cudd/cuddExport.c index d7b9645b..d148be42 100644 --- a/src/bdd/cudd/cuddExport.c +++ b/src/bdd/cudd/cuddExport.c @@ -35,7 +35,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddGenCof.c b/src/bdd/cudd/cuddGenCof.c index 59ae55d7..142ee27e 100644 --- a/src/bdd/cudd/cuddGenCof.c +++ b/src/bdd/cudd/cuddGenCof.c @@ -46,7 +46,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddGenetic.c b/src/bdd/cudd/cuddGenetic.c index 8341dcbd..9fe03dad 100644 --- a/src/bdd/cudd/cuddGenetic.c +++ b/src/bdd/cudd/cuddGenetic.c @@ -53,7 +53,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddGroup.c b/src/bdd/cudd/cuddGroup.c index f84f7881..81c05d2c 100644 --- a/src/bdd/cudd/cuddGroup.c +++ b/src/bdd/cudd/cuddGroup.c @@ -49,7 +49,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddHarwell.c b/src/bdd/cudd/cuddHarwell.c index 10746186..063f1922 100644 --- a/src/bdd/cudd/cuddHarwell.c +++ b/src/bdd/cudd/cuddHarwell.c @@ -21,7 +21,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddInit.c b/src/bdd/cudd/cuddInit.c index aec8d286..8e06a425 100644 --- a/src/bdd/cudd/cuddInit.c +++ b/src/bdd/cudd/cuddInit.c @@ -29,7 +29,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #define CUDD_MAIN #include "cuddInt.h" #undef CUDD_MAIN diff --git a/src/bdd/cudd/cuddInteract.c b/src/bdd/cudd/cuddInteract.c index 5a4ec79a..96613639 100644 --- a/src/bdd/cudd/cuddInteract.c +++ b/src/bdd/cudd/cuddInteract.c @@ -47,7 +47,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddLCache.c b/src/bdd/cudd/cuddLCache.c index 72fbd48a..8bd37ba0 100644 --- a/src/bdd/cudd/cuddLCache.c +++ b/src/bdd/cudd/cuddLCache.c @@ -45,7 +45,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddLevelQ.c b/src/bdd/cudd/cuddLevelQ.c index c4c621e7..3cc8e8d8 100644 --- a/src/bdd/cudd/cuddLevelQ.c +++ b/src/bdd/cudd/cuddLevelQ.c @@ -50,7 +50,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddLinear.c b/src/bdd/cudd/cuddLinear.c index cec7c255..7f6b3678 100644 --- a/src/bdd/cudd/cuddLinear.c +++ b/src/bdd/cudd/cuddLinear.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddLiteral.c b/src/bdd/cudd/cuddLiteral.c index 69594486..43740690 100644 --- a/src/bdd/cudd/cuddLiteral.c +++ b/src/bdd/cudd/cuddLiteral.c @@ -25,7 +25,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddMatMult.c b/src/bdd/cudd/cuddMatMult.c index b10975ec..345e7921 100644 --- a/src/bdd/cudd/cuddMatMult.c +++ b/src/bdd/cudd/cuddMatMult.c @@ -29,7 +29,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddPriority.c b/src/bdd/cudd/cuddPriority.c index bb0b83d3..788fc712 100644 --- a/src/bdd/cudd/cuddPriority.c +++ b/src/bdd/cudd/cuddPriority.c @@ -43,7 +43,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddRead.c b/src/bdd/cudd/cuddRead.c index eea4c7f3..2c4a86d8 100644 --- a/src/bdd/cudd/cuddRead.c +++ b/src/bdd/cudd/cuddRead.c @@ -23,7 +23,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddRef.c b/src/bdd/cudd/cuddRef.c index af08d048..a9241f3d 100644 --- a/src/bdd/cudd/cuddRef.c +++ b/src/bdd/cudd/cuddRef.c @@ -38,7 +38,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddReorder.c b/src/bdd/cudd/cuddReorder.c index e2b3470b..1387196f 100644 --- a/src/bdd/cudd/cuddReorder.c +++ b/src/bdd/cudd/cuddReorder.c @@ -45,7 +45,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSat.c b/src/bdd/cudd/cuddSat.c index dde33a5b..1755a1c1 100644 --- a/src/bdd/cudd/cuddSat.c +++ b/src/bdd/cudd/cuddSat.c @@ -42,7 +42,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSign.c b/src/bdd/cudd/cuddSign.c index 62477e7f..fcaa65c4 100644 --- a/src/bdd/cudd/cuddSign.c +++ b/src/bdd/cudd/cuddSign.c @@ -25,7 +25,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/cudd/cuddSolve.c b/src/bdd/cudd/cuddSolve.c index 058e0c08..d9c4a2e7 100644 --- a/src/bdd/cudd/cuddSolve.c +++ b/src/bdd/cudd/cuddSolve.c @@ -28,7 +28,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSplit.c b/src/bdd/cudd/cuddSplit.c index af7d6372..e21ea7cb 100644 --- a/src/bdd/cudd/cuddSplit.c +++ b/src/bdd/cudd/cuddSplit.c @@ -32,7 +32,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSubsetHB.c b/src/bdd/cudd/cuddSubsetHB.c index 43aaf744..24d41ce5 100644 --- a/src/bdd/cudd/cuddSubsetHB.c +++ b/src/bdd/cudd/cuddSubsetHB.c @@ -46,7 +46,7 @@ #else #define DBL_MAX_EXP 1024 #endif -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSubsetSP.c b/src/bdd/cudd/cuddSubsetSP.c index 0f7209dd..55ee3470 100644 --- a/src/bdd/cudd/cuddSubsetSP.c +++ b/src/bdd/cudd/cuddSubsetSP.c @@ -41,7 +41,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddSymmetry.c b/src/bdd/cudd/cuddSymmetry.c index 7b2013e4..e5488b17 100644 --- a/src/bdd/cudd/cuddSymmetry.c +++ b/src/bdd/cudd/cuddSymmetry.c @@ -38,7 +38,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddTable.c b/src/bdd/cudd/cuddTable.c index b118b76a..7f14aed1 100644 --- a/src/bdd/cudd/cuddTable.c +++ b/src/bdd/cudd/cuddTable.c @@ -54,7 +54,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddUtil.c b/src/bdd/cudd/cuddUtil.c index c366d534..d5fa18e2 100644 --- a/src/bdd/cudd/cuddUtil.c +++ b/src/bdd/cudd/cuddUtil.c @@ -76,7 +76,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddWindow.c b/src/bdd/cudd/cuddWindow.c index 3e6d5686..9ceb79b2 100644 --- a/src/bdd/cudd/cuddWindow.c +++ b/src/bdd/cudd/cuddWindow.c @@ -31,7 +31,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddCount.c b/src/bdd/cudd/cuddZddCount.c index 29cf0c14..6c6ec1df 100644 --- a/src/bdd/cudd/cuddZddCount.c +++ b/src/bdd/cudd/cuddZddCount.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddFuncs.c b/src/bdd/cudd/cuddZddFuncs.c index f938e1de..9dc27a95 100644 --- a/src/bdd/cudd/cuddZddFuncs.c +++ b/src/bdd/cudd/cuddZddFuncs.c @@ -48,7 +48,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddGroup.c b/src/bdd/cudd/cuddZddGroup.c index 35f28881..621fa43f 100644 --- a/src/bdd/cudd/cuddZddGroup.c +++ b/src/bdd/cudd/cuddZddGroup.c @@ -40,7 +40,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddIsop.c b/src/bdd/cudd/cuddZddIsop.c index 0918461c..f4b057ea 100644 --- a/src/bdd/cudd/cuddZddIsop.c +++ b/src/bdd/cudd/cuddZddIsop.c @@ -34,7 +34,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddLin.c b/src/bdd/cudd/cuddZddLin.c index 9369bb05..ef2cd298 100644 --- a/src/bdd/cudd/cuddZddLin.c +++ b/src/bdd/cudd/cuddZddLin.c @@ -32,7 +32,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddMisc.c b/src/bdd/cudd/cuddZddMisc.c index d55bb768..6a4ddd09 100644 --- a/src/bdd/cudd/cuddZddMisc.c +++ b/src/bdd/cudd/cuddZddMisc.c @@ -33,7 +33,7 @@ ******************************************************************************/ #include <math.h> -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddPort.c b/src/bdd/cudd/cuddZddPort.c index 1700ab2b..6d4a3236 100644 --- a/src/bdd/cudd/cuddZddPort.c +++ b/src/bdd/cudd/cuddZddPort.c @@ -32,7 +32,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddReord.c b/src/bdd/cudd/cuddZddReord.c index e14ae2ad..e2da37f2 100644 --- a/src/bdd/cudd/cuddZddReord.c +++ b/src/bdd/cudd/cuddZddReord.c @@ -46,7 +46,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddSetop.c b/src/bdd/cudd/cuddZddSetop.c index cf05210f..f1bd72f3 100644 --- a/src/bdd/cudd/cuddZddSetop.c +++ b/src/bdd/cudd/cuddZddSetop.c @@ -46,7 +46,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddSymm.c b/src/bdd/cudd/cuddZddSymm.c index c9ffaab4..54019892 100644 --- a/src/bdd/cudd/cuddZddSymm.c +++ b/src/bdd/cudd/cuddZddSymm.c @@ -40,7 +40,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddZddUtil.c b/src/bdd/cudd/cuddZddUtil.c index 0795f123..616d16d4 100644 --- a/src/bdd/cudd/cuddZddUtil.c +++ b/src/bdd/cudd/cuddZddUtil.c @@ -35,7 +35,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/testcudd.c b/src/bdd/cudd/testcudd.c index 451bb190..d8affadc 100644 --- a/src/bdd/cudd/testcudd.c +++ b/src/bdd/cudd/testcudd.c @@ -23,7 +23,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "cuddInt.h" diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h index 3fd365d7..04385933 100644 --- a/src/bdd/dsd/dsd.h +++ b/src/bdd/dsd/dsd.h @@ -101,6 +101,7 @@ 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 ); @@ -109,6 +110,7 @@ extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, in 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_NodePrint( FILE * pFile, Dsd_Node_t * pNode ); /*=== dsdLocal.c =======================================================*/ extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ); diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c index 7905cbdd..2f83ddd5 100644 --- a/src/bdd/dsd/dsdTree.c +++ b/src/bdd/dsd/dsdTree.c @@ -29,7 +29,7 @@ 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 /// @@ -243,6 +243,58 @@ void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ) /**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 @@ -631,27 +683,21 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); - fprintf( pFile, "%s: ", pOutputName ); + if ( !fComp ) + fprintf( pFile, "%s = ", pOutputName ); + else + fprintf( pFile, "NOT(%s) = ", pOutputName ); pInputNums = ALLOC( int, pNode->nDecs ); if ( pNode->Type == DSD_NODE_CONST1 ) { - if ( fComp ) - fprintf( pFile, " Constant 0.\n" ); - else - fprintf( pFile, " Constant 1.\n" ); + fprintf( pFile, " Constant 1.\n" ); } else if ( pNode->Type == DSD_NODE_BUF ) { - if ( fComp ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); if ( fShortNames ) - fprintf( pFile, "%d", pNode->S->index ); + fprintf( pFile, "%d", 'a' + pNode->S->index ); else fprintf( pFile, "%s", pInputNames[pNode->S->index] ); - if ( fComp ) - fprintf( pFile, ")" ); fprintf( pFile, "\n" ); } else if ( pNode->Type == DSD_NODE_PRIME ) @@ -664,25 +710,25 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp 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 ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); if ( fShortNames ) fprintf( pFile, "%d", pInput->S->index ); else fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - if ( fCompNew ) - fprintf( pFile, ")" ); } else { pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); + fprintf( pFile, "<%d>", pInputNums[i] ); } + if ( fCompNew ) + fprintf( pFile, ")" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks @@ -690,43 +736,39 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); + 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 - if ( fComp ) - fprintf( pFile, "AND(" ); - else - fprintf( pFile, "OR(" ); + 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 ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); if ( fShortNames ) - fprintf( pFile, "%d", pInput->S->index ); + fprintf( pFile, "%c", 'a' + pInput->S->index ); else fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - if ( fCompNew ) - fprintf( pFile, ")" ); } else { pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); + fprintf( pFile, "<%d>", pInputNums[i] ); } + if ( fCompNew ) + fprintf( pFile, ")" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks @@ -734,43 +776,199 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fComp ^ fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); + 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 - if ( fComp ) - fprintf( pFile, "NEXOR(" ); - else - fprintf( pFile, "EXOR(" ); + 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 ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); if ( fShortNames ) - fprintf( pFile, "%d", pInput->S->index ); + fprintf( pFile, "%c", 'a' + pInput->S->index ); else fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - if ( fCompNew ) - fprintf( pFile, ")" ); + } + 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 ); + } + } + free( pInputNums ); +} + +/**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 = 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" ); + // 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 @@ -778,9 +976,8 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); + Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); } } free( pInputNums ); diff --git a/src/bdd/epd/epd.c b/src/bdd/epd/epd.c index a843b986..a80240bc 100644 --- a/src/bdd/epd/epd.c +++ b/src/bdd/epd/epd.c @@ -25,7 +25,7 @@ #include <stdlib.h> #include <string.h> #include <math.h> -#include "util.h" +#include "util_hack.h" #include "epd.h" diff --git a/src/bdd/mtr/mtrBasic.c b/src/bdd/mtr/mtrBasic.c index 2aec8d6b..94105282 100644 --- a/src/bdd/mtr/mtrBasic.c +++ b/src/bdd/mtr/mtrBasic.c @@ -33,7 +33,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "mtrInt.h" diff --git a/src/bdd/mtr/mtrGroup.c b/src/bdd/mtr/mtrGroup.c index ae9c5c2f..363b776b 100644 --- a/src/bdd/mtr/mtrGroup.c +++ b/src/bdd/mtr/mtrGroup.c @@ -33,7 +33,7 @@ ******************************************************************************/ -#include "util.h" +#include "util_hack.h" #include "mtrInt.h" /*---------------------------------------------------------------------------*/ diff --git a/src/map/fpga/fpga.c b/src/map/fpga/fpga.c index 31894590..c663aa74 100644 --- a/src/map/fpga/fpga.c +++ b/src/map/fpga/fpga.c @@ -111,8 +111,8 @@ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) // set the defaults fVerbose = 1; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "vh")) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { @@ -128,13 +128,13 @@ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); @@ -201,8 +201,8 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) // set the defaults fVerbose = 1; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "vh")) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { @@ -218,7 +218,7 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != util_optind ) + if ( argc != globalUtilOptind ) { goto usage; } diff --git a/src/map/fpga/fpgaLib.c b/src/map/fpga/fpgaLib.c index bf27397a..00832bce 100644 --- a/src/map/fpga/fpgaLib.c +++ b/src/map/fpga/fpgaLib.c @@ -70,7 +70,7 @@ Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose ) p = ALLOC( Fpga_LutLib_t, 1 ); memset( p, 0, sizeof(Fpga_LutLib_t) ); - p->pName = util_strsav( FileName ); + p->pName = Extra_UtilStrsav( FileName ); i = 1; while ( fgets( pBuffer, 1000, pFile ) != NULL ) @@ -125,7 +125,7 @@ Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p ) Fpga_LutLib_t * pNew; pNew = ALLOC( Fpga_LutLib_t, 1 ); *pNew = *p; - pNew->pName = util_strsav( pNew->pName ); + pNew->pName = Extra_UtilStrsav( pNew->pName ); return pNew; } diff --git a/src/map/mapper/mapper.c b/src/map/mapper/mapper.c index 4d77df8f..b18b68c0 100644 --- a/src/map/mapper/mapper.c +++ b/src/map/mapper/mapper.c @@ -95,16 +95,16 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) fVerbose = 1; fAlgorithm = 1; ExcludeFile = 0; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "eovh")) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "eovh")) != EOF ) { switch (c) { case 'e': - ExcludeFile = argv[util_optind]; + ExcludeFile = argv[globalUtilOptind]; if ( ExcludeFile == 0 ) goto usage; - util_optind++; + globalUtilOptind++; break; case 'o': fAlgorithm ^= 1; @@ -121,13 +121,13 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) // if ( (pFile = fopen( FileName, "r" )) == NULL ) { diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index a5dd8f95..10a5af9d 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -139,8 +139,8 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) // set the defaults fVerbose = 1; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "vh")) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { @@ -156,13 +156,13 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); @@ -229,8 +229,8 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) // set the defaults fVerbose = 1; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "vh")) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { @@ -246,7 +246,7 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != util_optind ) + if ( argc != globalUtilOptind ) { goto usage; } diff --git a/src/map/mio/mioFunc.c b/src/map/mio/mioFunc.c index b63cadda..78c98fbe 100644 --- a/src/map/mio/mioFunc.c +++ b/src/map/mio/mioFunc.c @@ -253,7 +253,7 @@ int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ) break; if ( i == nPins ) { // cannot find this name; save it - pPinNames[nPins++] = util_strsav(pTemp); + pPinNames[nPins++] = Extra_UtilStrsav(pTemp); } // get the next name pTemp = strtok( NULL, " " ); diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c index 0c2000a3..847acc27 100644 --- a/src/map/mio/mioRead.c +++ b/src/map/mio/mioRead.c @@ -99,7 +99,7 @@ Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fE // allocate the genlib structure pLib = ALLOC( Mio_Library_t, 1 ); memset( pLib, 0, sizeof(Mio_Library_t) ); - pLib->pName = util_strsav( FileName ); + pLib->pName = Extra_UtilStrsav( FileName ); pLib->tName2Gate = st_init_table(strcmp, st_strhash); pLib->pMmFlex = Extra_MmFlexStart(); pLib->vCube = Vec_StrAlloc( 100 ); @@ -251,7 +251,7 @@ Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat ) // read the name pToken = strtok( NULL, " \t\r\n" ); - pGate->pName = util_strsav( pToken ); + pGate->pName = Extra_UtilStrsav( pToken ); // read the area pToken = strtok( NULL, " \t\r\n" ); @@ -265,7 +265,7 @@ Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat ) // then rest of the expression pToken = strtok( NULL, ";" ); - pGate->pForm = util_strsav( pToken ); + pGate->pForm = Extra_UtilStrsav( pToken ); // read the pin info // start the linked list of pins @@ -319,7 +319,7 @@ Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat ) // read the name pToken = strtok( NULL, " \t\r\n" ); - pPin->pName = util_strsav( pToken ); + pPin->pName = Extra_UtilStrsav( pToken ); // read the pin phase pToken = strtok( NULL, " \t\r\n" ); @@ -507,7 +507,7 @@ int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * t while (1 == fscanf( pEx, "%127s", buffer )) { //printf ("Read: '%s'\n", buffer ); - st_insert( tExcludeGate, util_strsav( buffer ), (char *)0 ); + st_insert( tExcludeGate, Extra_UtilStrsav( buffer ), (char *)0 ); nDel++; } diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c index b051584e..05cf59ad 100644 --- a/src/map/mio/mioUtils.c +++ b/src/map/mio/mioUtils.c @@ -120,7 +120,7 @@ Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ) pPinNew = ALLOC( Mio_Pin_t, 1 ); *pPinNew = *pPin; - pPinNew->pName = (pPinNew->pName ? util_strsav(pPinNew->pName) : NULL); + pPinNew->pName = (pPinNew->pName ? Extra_UtilStrsav(pPinNew->pName) : NULL); pPinNew->pNext = NULL; return pPinNew; diff --git a/src/map/pga/pgaMatch.c b/src/map/pga/pgaMatch.c index 77d82b86..a4c57089 100644 --- a/src/map/pga/pgaMatch.c +++ b/src/map/pga/pgaMatch.c @@ -73,7 +73,7 @@ void Pga_MappingMatches( Pga_Man_t * p, int Mode ) continue; // get the cuts clk = clock(); - pList = Abc_NodeGetCutsRecursive( p->pManCut, pObj ); + pList = Abc_NodeGetCutsRecursive( p->pManCut, pObj, 0 ); p->timeCuts += clock() - clk; // match the node Pga_MappingMatchNode( p, pObj->Id, pList, Mode ); diff --git a/src/map/super/super.c b/src/map/super/super.c index 4b4968dd..97420c5c 100644 --- a/src/map/super/super.c +++ b/src/map/super/super.c @@ -90,20 +90,20 @@ int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv ) nVarsMax = 4; nLevels = 3; fVerbose = 0; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "ilvh")) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "ilvh")) != EOF ) { switch (c) { case 'i': - nVarsMax = atoi(argv[util_optind]); - util_optind++; + nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nVarsMax < 0 ) goto usage; break; case 'l': - nLevels = atoi(argv[util_optind]); - util_optind++; + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nLevels < 0 ) goto usage; break; @@ -172,44 +172,44 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) fWriteOldFormat = 0; ExcludeFile = 0; - util_getopt_reset(); - while ( (c = util_getopt(argc, argv, "eiltdasovh")) != EOF ) + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "eiltdasovh")) != EOF ) { switch (c) { case 'e': - ExcludeFile = argv[util_optind]; + ExcludeFile = argv[globalUtilOptind]; if ( ExcludeFile == 0 ) goto usage; - util_optind++; + globalUtilOptind++; break; case 'i': - nVarsMax = atoi(argv[util_optind]); - util_optind++; + nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nVarsMax < 0 ) goto usage; break; case 'l': - nLevels = atoi(argv[util_optind]); - util_optind++; + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( nLevels < 0 ) goto usage; break; case 't': - TimeLimit = atoi(argv[util_optind]); - util_optind++; + TimeLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; if ( TimeLimit < 0 ) goto usage; break; case 'd': - DelayLimit = (float)atof(argv[util_optind]); - util_optind++; + DelayLimit = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; if ( DelayLimit <= 0.0 ) goto usage; break; case 'a': - AreaLimit = (float)atof(argv[util_optind]); - util_optind++; + AreaLimit = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; if ( AreaLimit <= 0.0 ) goto usage; break; @@ -231,7 +231,7 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) } - if ( argc != util_optind + 1 ) + if ( argc != globalUtilOptind + 1 ) { fprintf( pErr, "The GENLIB library file should be given on the command line.\n" ); goto usage; @@ -244,7 +244,7 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) } // get the input file name - FileName = argv[util_optind]; + FileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) // if ( (pFile = fopen( FileName, "r" )) == NULL ) { diff --git a/src/misc/espresso/cofactor.c b/src/misc/espresso/cofactor.c new file mode 100644 index 00000000..b851a639 --- /dev/null +++ b/src/misc/espresso/cofactor.c @@ -0,0 +1,382 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +/* + 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<last;w++) + {x=p[w]&c[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{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(p[w]&c[w]&mask[w])goto nextvar;goto false;nextvar:;}} +#endif + + *Tc++ = p; + false: ; + } + } + + *Tc++ = (pcube) NULL; /* sentinel */ + Tc_save[1] = (pcube) Tc; /* save pointer to last */ + return Tc_save; +} + +/* + scofactor -- compute the cofactor of a cover with respect to a cube, + where the cube is "active" in only a single variable. + + This routine has been optimized for speed. +*/ + +pcube *scofactor(T, c, var) +IN pcube *T, c; +IN int var; +{ + pcube *Tc, *Tc_save; + register pcube p, mask = cube.temp[1], *T1; + register int first = cube.first_word[var], last = cube.last_word[var]; + 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(mask, cube.fullset, c)); + Tc++; + + /* Setup for the quick distance check */ + (void) set_and(mask, cube.var_mask[var], c); + + /* Loop for each cube in the list, determine suitability, and save */ + for(T1 = T+2; (p = *T1++) != NULL; ) + if (p != c) { + register int i = first; + do + if (p[i] & mask[i]) { + *Tc++ = p; + break; + } + while (++i <= last); + } + + *Tc++ = (pcube) NULL; /* sentinel */ + Tc_save[1] = (pcube) Tc; /* save pointer to last */ + return Tc_save; +} + +void massive_count(T) +IN pcube *T; +{ + int *count = cdata.part_zeros; + pcube *T1; + + /* Clear the column counts (count of # zeros in each column) */ + { register int i; + for(i = cube.size - 1; i >= 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; +} + +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 */ +} diff --git a/src/misc/espresso/cols.c b/src/misc/espresso/cols.c new file mode 100644 index 00000000..ec3797e6 --- /dev/null +++ b/src/misc/espresso/cols.c @@ -0,0 +1,314 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +//#include "port.h" +#include "sparse_int.h" + + +/* + * 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); + } +} diff --git a/src/misc/espresso/compl.c b/src/misc/espresso/compl.c new file mode 100644 index 00000000..8f1c6606 --- /dev/null +++ b/src/misc/espresso/compl.c @@ -0,0 +1,680 @@ +/* + * 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" + +#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; + } +} diff --git a/src/misc/espresso/contain.c b/src/misc/espresso/contain.c new file mode 100644 index 00000000..180dceb6 --- /dev/null +++ b/src/misc/espresso/contain.c @@ -0,0 +1,441 @@ +/* + * 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" + + +/* + 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, *pcheck, 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, *pcheck, 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; +} diff --git a/src/misc/espresso/cubehack.c b/src/misc/espresso/cubehack.c new file mode 100644 index 00000000..8e1724fc --- /dev/null +++ b/src/misc/espresso/cubehack.c @@ -0,0 +1,138 @@ +/* + * 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" + + +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; +} diff --git a/src/misc/espresso/cubestr.c b/src/misc/espresso/cubestr.c new file mode 100644 index 00000000..77389e73 --- /dev/null +++ b/src/misc/espresso/cubestr.c @@ -0,0 +1,152 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + Module: cubestr.c -- routines for managing the global cube structure +*/ + +#include "espresso.h" + +/* + 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; /* "" */ +} diff --git a/src/misc/espresso/cvrin.c b/src/misc/espresso/cvrin.c new file mode 100644 index 00000000..7790b38b --- /dev/null +++ b/src/misc/espresso/cvrin.c @@ -0,0 +1,810 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: cvrin.c + purpose: cube and cover input routines +*/ + +#include "espresso.h" + +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; +} + + +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; +} diff --git a/src/misc/espresso/cvrm.c b/src/misc/espresso/cvrm.c new file mode 100644 index 00000000..7d42d6e3 --- /dev/null +++ b/src/misc/espresso/cvrm.c @@ -0,0 +1,539 @@ +/* + * 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" + + +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 + */ +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; +} diff --git a/src/misc/espresso/cvrmisc.c b/src/misc/espresso/cvrmisc.c new file mode 100644 index 00000000..0f3de195 --- /dev/null +++ b/src/misc/espresso/cvrmisc.c @@ -0,0 +1,142 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + + +/* 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); +} diff --git a/src/misc/espresso/cvrout.c b/src/misc/espresso/cvrout.c new file mode 100644 index 00000000..4bd1c53b --- /dev/null +++ b/src/misc/espresso/cvrout.c @@ -0,0 +1,609 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: cvrout.c + purpose: cube and cover output routines +*/ + +#include "espresso.h" + +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)); +} + + +int 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); + } + } +} + + +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"); + } +} + + +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); +} + +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 contraints */ + 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); + } + } +} diff --git a/src/misc/espresso/dominate.c b/src/misc/espresso/dominate.c new file mode 100644 index 00000000..a930d453 --- /dev/null +++ b/src/misc/espresso/dominate.c @@ -0,0 +1,98 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + + +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; +} diff --git a/src/misc/espresso/equiv.c b/src/misc/espresso/equiv.c new file mode 100644 index 00000000..ba898a70 --- /dev/null +++ b/src/misc/espresso/equiv.c @@ -0,0 +1,94 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + + +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; +} diff --git a/src/misc/espresso/espresso.c b/src/misc/espresso/espresso.c new file mode 100644 index 00000000..8f05d43f --- /dev/null +++ b/src/misc/espresso/espresso.c @@ -0,0 +1,139 @@ +/* + * 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" + +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; +} diff --git a/src/misc/espresso/espresso.h b/src/misc/espresso/espresso.h new file mode 100644 index 00000000..1c7a8646 --- /dev/null +++ b/src/misc/espresso/espresso.h @@ -0,0 +1,782 @@ +/* + * 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 ptime() util_cpu_time() +#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 BPI +#define BPI 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;p<last;p+=R->wsize) +#define foreach_remaining_set(R, last, pfirst, p)\ + for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;p<last;p+=R->wsize) +#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;i<R->count;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 +#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 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 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 int makeup_labels(); +/* cvrout.c */ extern kiss_output(); +/* cvrout.c */ extern kiss_print_cube(); +/* cvrout.c */ extern 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 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 find_dc_inputs(); +/* hack.c */ extern find_inputs(); +/* hack.c */ extern form_bitvector(); +/* hack.c */ extern map_dcset(); +/* hack.c */ extern map_output_symbolic(); +/* hack.c */ extern map_symbolic(); +/* hack.c */ extern pcover map_symbolic_cover(); +/* hack.c */ extern 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 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 generate_all_pairs(); +/* pair.c */ extern int **find_pairing_cost(); +/* pair.c */ extern int find_best_cost(); +/* pair.c */ extern int greedy_best_cost(); +/* pair.c */ extern int minimize_pair(); +/* pair.c */ extern int pair_free(); +/* pair.c */ extern 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 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(); +#if !defined(__osf__) && !defined(__STDC__) && !defined(__hpux) +/* ucbqsort.c */ extern qsort(); +#endif +/* ucbqsort.c */ extern qst(); +/* 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 PLA_permute(); +/* verify.c */ extern bool PLA_verify(); +/* verify.c */ extern bool check_consistency(); +/* verify.c */ extern bool verify(); diff --git a/src/misc/espresso/essen.c b/src/misc/espresso/essen.c new file mode 100644 index 00000000..6a46295d --- /dev/null +++ b/src/misc/espresso/essen.c @@ -0,0 +1,179 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: essen.c + purpose: Find essential primes in a multiple-valued function +*/ + +#include "espresso.h" + +/* + 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; +} diff --git a/src/misc/espresso/exact.c b/src/misc/espresso/exact.c new file mode 100644 index 00000000..b1943636 --- /dev/null +++ b/src/misc/espresso/exact.c @@ -0,0 +1,181 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + + +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); + } +} diff --git a/src/misc/espresso/expand.c b/src/misc/espresso/expand.c new file mode 100644 index 00000000..2765d71c --- /dev/null +++ b/src/misc/espresso/expand.c @@ -0,0 +1,693 @@ +/* + * 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" + +/* + 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<last;w++){x=p[w]&r[w];if(x=~(x|x>>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;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(p[w]&r[ +w]&mask[w])goto nextvar;if(++dist>1)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<lastw;w++){x=p[w] +&r[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register +pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube. +var_mask[var];lastw=cube.last_word[var];for(w=cube.first_word[var];w<=lastw;w++) +if(p[w]&r[w]&mask[w])goto nextvar;goto false;nextvar:;}}continue;false: +#endif + BB->active_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, bestfeas, *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<last;w++){x=p[w]&r[w];if(x=~(x|x>>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;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(p[w]&r[ +w]&mask[w])goto nextvar;if(++dist>1)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; +} diff --git a/src/misc/espresso/gasp.c b/src/misc/espresso/gasp.c new file mode 100644 index 00000000..aa3254d3 --- /dev/null +++ b/src/misc/espresso/gasp.c @@ -0,0 +1,228 @@ +/* + * 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" + + +/* + * 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; +} diff --git a/src/misc/espresso/gimpel.c b/src/misc/espresso/gimpel.c new file mode 100644 index 00000000..648bb64a --- /dev/null +++ b/src/misc/espresso/gimpel.c @@ -0,0 +1,106 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + + +/* + * 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, *c2; + register sm_element *p, *p1; + int c1_col_num, c2_col_num, primary_row_num, secondary_row_num; + 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; + } +} diff --git a/src/misc/espresso/globals.c b/src/misc/espresso/globals.c new file mode 100644 index 00000000..d04771e9 --- /dev/null +++ b/src/misc/espresso/globals.c @@ -0,0 +1,76 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +/* + * 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 +}; diff --git a/src/misc/espresso/hack.c b/src/misc/espresso/hack.c new file mode 100644 index 00000000..927f5341 --- /dev/null +++ b/src/misc/espresso/hack.c @@ -0,0 +1,641 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +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); +} + +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); +} + + +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 + +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; +} + + +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"); + } + } +} + + +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; +} + + +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"); + } +} diff --git a/src/misc/espresso/indep.c b/src/misc/espresso/indep.c new file mode 100644 index 00000000..10b363a0 --- /dev/null +++ b/src/misc/espresso/indep.c @@ -0,0 +1,134 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + +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; +} diff --git a/src/misc/espresso/irred.c b/src/misc/espresso/irred.c new file mode 100644 index 00000000..384e698f --- /dev/null +++ b/src/misc/espresso/irred.c @@ -0,0 +1,440 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +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", + cdata.vars_unate, 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", + cdata.vars_unate, CUBELISTSIZE(T)); + } + goto start; + } + + /* Not much we can do about it */ + return MAYBE; +} diff --git a/src/misc/espresso/main.c b/src/misc/espresso/main.c new file mode 100644 index 00000000..0a511c0e --- /dev/null +++ b/src/misc/espresso/main.c @@ -0,0 +1,746 @@ +/* + * 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 "main.h" /* 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; +} diff --git a/src/misc/espresso/main.h b/src/misc/espresso/main.h new file mode 100644 index 00000000..00657f39 --- /dev/null +++ b/src/misc/espresso/main.h @@ -0,0 +1,122 @@ +/* + * 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, +}; diff --git a/src/misc/espresso/map.c b/src/misc/espresso/map.c new file mode 100644 index 00000000..5ccf264c --- /dev/null +++ b/src/misc/espresso/map.c @@ -0,0 +1,115 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +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); +} diff --git a/src/misc/espresso/matrix.c b/src/misc/espresso/matrix.c new file mode 100644 index 00000000..747fe54f --- /dev/null +++ b/src/misc/espresso/matrix.c @@ -0,0 +1,574 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +//#include "port.h" +#include "sparse_int.h" + +/* + * 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 +} diff --git a/src/misc/espresso/mincov.c b/src/misc/espresso/mincov.c new file mode 100644 index 00000000..ee18a3f1 --- /dev/null +++ b/src/misc/espresso/mincov.c @@ -0,0 +1,378 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + +/* + * 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; +} diff --git a/src/misc/espresso/mincov.h b/src/misc/espresso/mincov.h new file mode 100644 index 00000000..95310774 --- /dev/null +++ b/src/misc/espresso/mincov.h @@ -0,0 +1,11 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* exported */ +extern sm_row *sm_minimum_cover(); diff --git a/src/misc/espresso/mincov_int.h b/src/misc/espresso/mincov_int.h new file mode 100644 index 00000000..e81850f2 --- /dev/null +++ b/src/misc/espresso/mincov_int.h @@ -0,0 +1,55 @@ +/* + * 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 WEIGHT(weight, col) (weight == NIL(int) ? 1 : weight[col]) diff --git a/src/misc/espresso/module.make b/src/misc/espresso/module.make new file mode 100644 index 00000000..53ce982a --- /dev/null +++ b/src/misc/espresso/module.make @@ -0,0 +1,39 @@ +SRC += 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 diff --git a/src/misc/espresso/opo.c b/src/misc/espresso/opo.c new file mode 100644 index 00000000..8daa0771 --- /dev/null +++ b/src/misc/espresso/opo.c @@ -0,0 +1,624 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +/* + * 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 + */ + +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); + } +} diff --git a/src/misc/espresso/pair.c b/src/misc/espresso/pair.c new file mode 100644 index 00000000..a8077176 --- /dev/null +++ b/src/misc/espresso/pair.c @@ -0,0 +1,675 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +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, 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, xnum_binary_vars, xnum_vars, *xpart_size, cost; + pcover T, Fsave, Dsave, Rsave; + 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; + + +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, besti, bestj, 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; +} + + +int 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 +*/ + +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 + */ +int 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; +} + +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; +} + + +int pair_free(pair) +register ppair pair; +{ + FREE(pair->var1); + FREE(pair->var2); + FREE(pair); +} diff --git a/src/misc/espresso/part.c b/src/misc/espresso/part.c new file mode 100644 index 00000000..42843aeb --- /dev/null +++ b/src/misc/espresso/part.c @@ -0,0 +1,122 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + +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; + } +} diff --git a/src/misc/espresso/primes.c b/src/misc/espresso/primes.c new file mode 100644 index 00000000..3e40da27 --- /dev/null +++ b/src/misc/espresso/primes.c @@ -0,0 +1,170 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +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); +} diff --git a/src/misc/espresso/reduce.c b/src/misc/espresso/reduce.c new file mode 100644 index 00000000..00e4507f --- /dev/null +++ b/src/misc/espresso/reduce.c @@ -0,0 +1,258 @@ +/* + * 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" + +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; +} diff --git a/src/misc/espresso/rows.c b/src/misc/espresso/rows.c new file mode 100644 index 00000000..bf0c0baa --- /dev/null +++ b/src/misc/espresso/rows.c @@ -0,0 +1,314 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +//#include "port.h" +#include "sparse_int.h" + + +/* + * 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); + } +} diff --git a/src/misc/espresso/set.c b/src/misc/espresso/set.c new file mode 100644 index 00000000..fce88288 --- /dev/null +++ b/src/misc/espresso/set.c @@ -0,0 +1,820 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + * set.c -- routines for maniuplating sets and set families + */ + +/* LINTLIBRARY */ + +#include "espresso.h" +static pset_family set_family_garbage = NULL; + +static int 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<<LOGBPI; val!=0; base++, val >>= 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; +} diff --git a/src/misc/espresso/setc.c b/src/misc/espresso/setc.c new file mode 100644 index 00000000..a6112ebc --- /dev/null +++ b/src/misc/espresso/setc.c @@ -0,0 +1,483 @@ +/* + * 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" + +/* 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; +} diff --git a/src/misc/espresso/sharp.c b/src/misc/espresso/sharp.c new file mode 100644 index 00000000..53435078 --- /dev/null +++ b/src/misc/espresso/sharp.c @@ -0,0 +1,247 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + sharp.c -- perform sharp, disjoint sharp, and intersection +*/ + +#include "espresso.h" + +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; +} diff --git a/src/misc/espresso/sminterf.c b/src/misc/espresso/sminterf.c new file mode 100644 index 00000000..50a6db4e --- /dev/null +++ b/src/misc/espresso/sminterf.c @@ -0,0 +1,44 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + + +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; +} diff --git a/src/misc/espresso/solution.c b/src/misc/espresso/solution.c new file mode 100644 index 00000000..26119185 --- /dev/null +++ b/src/misc/espresso/solution.c @@ -0,0 +1,114 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + + +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); + } + } +} diff --git a/src/misc/espresso/sparse.c b/src/misc/espresso/sparse.c new file mode 100644 index 00000000..137ce7c1 --- /dev/null +++ b/src/misc/espresso/sparse.c @@ -0,0 +1,146 @@ +/* + * 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" + +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; +} diff --git a/src/misc/espresso/sparse.h b/src/misc/espresso/sparse.h new file mode 100644 index 00000000..212a32ed --- /dev/null +++ b/src/misc/espresso/sparse.h @@ -0,0 +1,135 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#ifndef SPARSE_H +#define SPARSE_H + +/* + * 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(); + +#endif diff --git a/src/misc/espresso/sparse_int.h b/src/misc/espresso/sparse_int.h new file mode 100644 index 00000000..49b2509a --- /dev/null +++ b/src/misc/espresso/sparse_int.h @@ -0,0 +1,121 @@ +/* + * 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 sorted_insert(type, first, last, count, next, prev, value, newval, e) \ + 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 */ diff --git a/src/misc/espresso/unate.c b/src/misc/espresso/unate.c new file mode 100644 index 00000000..bd71207f --- /dev/null +++ b/src/misc/espresso/unate.c @@ -0,0 +1,441 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + * unate.c -- routines for dealing with unate functions + */ + +#include "espresso.h" + +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; +} diff --git a/src/misc/espresso/util_old.h b/src/misc/espresso/util_old.h new file mode 100644 index 00000000..5451cbe9 --- /dev/null +++ b/src/misc/espresso/util_old.h @@ -0,0 +1,301 @@ +/* + * 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 UTIL_H +#define UTIL_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 <unistd.h> +#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 <stdio.h> +#include <ctype.h> + + +/* 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 <sys/types.h> +#include <signal.h> +#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 <stdlib.h> +#if defined(__hpux) +#include <errno.h> /* 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 <string.h> +#else +#if defined(ultrix4) || defined(__hpux) +#include <strings.h> +#else +#if defined(_IBMR2) || defined(__osf__) +#include<string.h> +#include<strings.h> +#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 <assert.h> +#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 <math.h> +#ifndef HUGE_VAL +#ifndef HUGE +#define HUGE 8.9884656743115790e+307 +#endif +#define HUGE_VAL HUGE +#endif +#ifndef MAXINT +#define MAXINT (1 << 30) +#endif + +#include <varargs.h> +#endif diff --git a/src/misc/espresso/verify.c b/src/misc/espresso/verify.c new file mode 100644 index 00000000..64342787 --- /dev/null +++ b/src/misc/espresso/verify.c @@ -0,0 +1,193 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + */ + +#include "espresso.h" + +/* + * 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. + */ +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; +} diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index 0d0c93a8..666d7388 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -37,9 +37,11 @@ /* Nested includes */ /*---------------------------------------------------------------------------*/ +#include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <assert.h> #include <time.h> -#include "util.h" #include "st.h" #include "cuddInt.h" @@ -155,6 +157,7 @@ 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 ); /*=== extraBddKmap.c ================================================================*/ @@ -408,6 +411,27 @@ extern void Extra_IntVecPush( Extra_IntVec_t * p, int Entry ); extern int Extra_IntVecPop( Extra_IntVec_t * p ); extern void Extra_IntVecSort( Extra_IntVec_t * p ); +/*=== extraUtilUtil.c ================================================================*/ + +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define REALLOC(type, obj, num) \ + (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num))) + +extern long Extra_CpuTime(); +extern int Extra_GetSoftDataLimit(); +extern void Extra_UtilGetoptReset(); +extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring ); +extern char * Extra_UtilPrintTime( long t ); +extern char * Extra_UtilStrsav( char *s ); +extern char * Extra_UtilTildeExpand( char *fname ); +extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); +extern void (*Extra_UtilMMoutOfMemory)(); + +extern char * globalUtilOptarg; +extern int globalUtilOptind; + /**AutomaticEnd***************************************************************/ #endif /* __EXTRA_H__ */ diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c index 7d806ec7..00e2ac94 100644 --- a/src/misc/extra/extraBddMisc.c +++ b/src/misc/extra/extraBddMisc.c @@ -52,8 +52,8 @@ static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdN static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ); // file "cuddUtils.c" -static void ddSupportStep ARGS((DdNode *f, int *support)); -static void ddClearFlag ARGS((DdNode *f)); +static void ddSupportStep(DdNode *f, int *support); +static void ddClearFlag(DdNode *f); /**AutomaticEnd***************************************************************/ @@ -796,6 +796,25 @@ DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ) } /* end of Extra_SupportNeg */ +/**Function******************************************************************** + + Synopsis [Returns 1 if the BDD is the BDD of elementary variable.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_VectorSupport Cudd_Support] + +******************************************************************************/ +int Extra_bddIsVar( DdNode * bFunc ) +{ + bFunc = Cudd_Regular( bFunc ); + if ( cuddIsConstant(bFunc) ) + return 0; + return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) ); +} + /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ diff --git a/src/misc/extra/extraUtil.h b/src/misc/extra/extraUtil.h new file mode 100644 index 00000000..d3f432c2 --- /dev/null +++ b/src/misc/extra/extraUtil.h @@ -0,0 +1,60 @@ +/**CFile**************************************************************** + + FileName [extraUtil.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Various reusable software utilities.] + + Description [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtil.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __EXTRA_UTIL_H__ +#define __EXTRA_UTIL_H__ + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include <string.h> +#include <time.h> + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/*===========================================================================*/ +/* Various Utilities */ +/*===========================================================================*/ + + +/**AutomaticEnd***************************************************************/ + +#endif /* __EXTRA_UTIL_H__ */ diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c index 03b31fea..b00125d1 100644 --- a/src/misc/extra/extraUtilFile.c +++ b/src/misc/extra/extraUtilFile.c @@ -172,7 +172,7 @@ char * Extra_FileNameGeneric( char * FileName ) char * pRes; // find the generic name of the file - pRes = util_strsav( FileName ); + pRes = Extra_UtilStrsav( FileName ); // find the pointer to the "." symbol in the file name // pUnd = strstr( FileName, "_" ); pUnd = NULL; @@ -391,7 +391,7 @@ char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ) free( pStrGiven ); } else - pTemp = util_strsav( pStrAdd ); + pTemp = Extra_UtilStrsav( pStrAdd ); return pTemp; } diff --git a/src/misc/extra/extraUtilUtil.c b/src/misc/extra/extraUtilUtil.c new file mode 100644 index 00000000..71d3f652 --- /dev/null +++ b/src/misc/extra/extraUtilUtil.c @@ -0,0 +1,330 @@ +/**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 "stdio.h" +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// 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. + */ + +char * globalUtilOptarg; // Global argument pointer (util_optarg) +int globalUtilOptind = 0; // Global argv index (util_optind) + +static char *pScanStr; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [util_cpu_time()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +long Extra_CpuTime() +{ + return clock(); +} + +/**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[], char *optstring ) +{ + register int c; + register 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( char *s ) +{ + if(s == NULL) { /* added 7/95, for robustness */ + return s; + } + else { + return strcpy(ALLOC(char, strlen(s)+1), s); + } +} + +/**Function************************************************************* + + Synopsis [util_tilde_expand()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_UtilTildeExpand( char *fname ) +{ + return Extra_UtilStrsav( fname ); +} + +/**Function************************************************************* + + Synopsis [check_file()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_UtilCheckFile(char *filename, 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 = ALLOC(char, strlen(path) + strlen(file) + 4); + (void) sprintf(buffer, "%s/%s", path, file); + } + filename = Extra_UtilTildeExpand(buffer); + FREE(buffer); + + /* see if we can access it */ + if (Extra_UtilCheckFile(filename, mode)) { + FREE(save_path); + return filename; + } + FREE(filename); + path = ++cp; + } while (! quit); + + 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)() = Extra_UtilMMout_Of_Memory; + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/misc/extra/module.make b/src/misc/extra/module.make index 8e7b1772..c4da05e4 100644 --- a/src/misc/extra/module.make +++ b/src/misc/extra/module.make @@ -2,10 +2,12 @@ SRC += src/misc/extra/extraBddAuto.c \ src/misc/extra/extraBddKmap.c \ src/misc/extra/extraBddMisc.c \ src/misc/extra/extraBddSymm.c \ + src/misc/extra/extraBddUnate.c \ src/misc/extra/extraUtilBitMatrix.c \ src/misc/extra/extraUtilCanon.c \ src/misc/extra/extraUtilFile.c \ src/misc/extra/extraUtilMemory.c \ src/misc/extra/extraUtilMisc.c \ src/misc/extra/extraUtilProgress.c \ - src/misc/extra/extraUtilReader.c + src/misc/extra/extraUtilReader.c \ + src/misc/extra/extraUtilUtil.c diff --git a/src/misc/mvc/mvc.h b/src/misc/mvc/mvc.h index b670dc97..363b1e57 100644 --- a/src/misc/mvc/mvc.h +++ b/src/misc/mvc/mvc.h @@ -24,9 +24,8 @@ //////////////////////////////////////////////////////////////////////// #include <stdio.h> -#include "util.h" #include "extra.h" -//#include "vm.h" +#include "extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/misc/st/st.c b/src/misc/st/st.c index 13e9bd6a..e1e5022a 100644 --- a/src/misc/st/st.c +++ b/src/misc/st/st.c @@ -8,9 +8,13 @@ * */ #include <stdio.h> -#include "util.h" +#include "extra.h" #include "st.h" +#ifndef ABS +# define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif + #define ST_NUMCMP(x,y) ((x) != (y)) #define ST_NUMHASH(x,size) (ABS((long)x)%(size)) #define ST_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) @@ -41,8 +45,8 @@ int reorder_flag; st_table *new; new = ALLOC(st_table, 1); - if (new == NIL(st_table)) { - return NIL(st_table); + if (new == NULL) { + return NULL; } new->compare = compare; new->hash = hash; @@ -55,9 +59,9 @@ int reorder_flag; } new->num_bins = size; new->bins = ALLOC(st_table_entry *, size); - if (new->bins == NIL(st_table_entry *)) { + if (new->bins == NULL) { FREE(new); - return NIL(st_table); + return NULL; } for(i = 0; i < size; i++) { new->bins[i] = 0; @@ -85,7 +89,7 @@ st_table *table; for(i = 0; i < table->num_bins ; i++) { ptr = table->bins[i]; - while (ptr != NIL(st_table_entry)) { + while (ptr != NULL) { next = ptr->next; FREE(ptr); ptr = next; @@ -96,7 +100,7 @@ st_table *table; } #define PTR_NOT_EQUAL(table, ptr, user_key)\ -(ptr != NIL(st_table_entry) && !EQUAL(table->compare, user_key, (ptr)->key)) +(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) #define FIND_ENTRY(table, hash_val, key, ptr, last) \ (last) = &(table)->bins[hash_val];\ @@ -104,7 +108,7 @@ st_table *table; while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ (last) = &(ptr)->next; (ptr) = *(last);\ }\ - if ((ptr) != NIL(st_table_entry) && (table)->reorder_flag) {\ + if ((ptr) != NULL && (table)->reorder_flag) {\ *(last) = (ptr)->next;\ (ptr)->next = (table)->bins[hash_val];\ (table)->bins[hash_val] = (ptr);\ @@ -123,10 +127,10 @@ char **value; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NIL(st_table_entry)) { + if (ptr == NULL) { return 0; } else { - if (value != NIL(char *)) { + if (value != NULL) { *value = ptr->record; } return 1; @@ -146,10 +150,10 @@ int *value; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NIL(st_table_entry)) { + if (ptr == NULL) { return 0; } else { - if (value != NIL(int)) { + if (value != 0) { *value = (long) ptr->record; } return 1; @@ -187,7 +191,7 @@ char *value; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NIL(st_table_entry)) { + 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; @@ -195,7 +199,7 @@ char *value; hash_val = do_hash(key, table); } new = ALLOC(st_table_entry, 1); - if (new == NIL(st_table_entry)) { + if (new == NULL) { return ST_OUT_OF_MEM; } new->key = key; @@ -227,7 +231,7 @@ char *value; } hash_val = do_hash(key, table); new = ALLOC(st_table_entry, 1); - if (new == NIL(st_table_entry)) { + if (new == NULL) { return ST_OUT_OF_MEM; } new->key = key; @@ -251,7 +255,7 @@ char ***slot; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NIL(st_table_entry)) { + 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; @@ -259,7 +263,7 @@ char ***slot; hash_val = do_hash(key, table); } new = ALLOC(st_table_entry, 1); - if (new == NIL(st_table_entry)) { + if (new == NULL) { return ST_OUT_OF_MEM; } new->key = key; @@ -267,10 +271,10 @@ char ***slot; new->next = table->bins[hash_val]; table->bins[hash_val] = new; table->num_entries++; - if (slot != NIL(char **)) *slot = &new->record; + if (slot != NULL) *slot = &new->record; return 0; } else { - if (slot != NIL(char **)) *slot = &ptr->record; + if (slot != NULL) *slot = &ptr->record; return 1; } } @@ -288,10 +292,10 @@ char ***slot; FIND_ENTRY(table, hash_val, key, ptr, last); - if (ptr == NIL(st_table_entry)) { + if (ptr == NULL) { return 0; } else { - if (slot != NIL(char **)) { + if (slot != NULL) { *slot = &ptr->record; } return 1; @@ -317,7 +321,7 @@ register st_table *table; } table->num_entries = 0; table->bins = ALLOC(st_table_entry *, table->num_bins); - if (table->bins == NIL(st_table_entry *)) { + if (table->bins == NULL) { table->bins = old_bins; table->num_bins = old_num_bins; table->num_entries = old_num_entries; @@ -331,7 +335,7 @@ register st_table *table; /* copy data over */ for (i = 0; i < old_num_bins; i++) { ptr = old_bins[i]; - while (ptr != NIL(st_table_entry)) { + while (ptr != NULL) { next = ptr->next; hash_val = do_hash(ptr->key, table); ptr->next = table->bins[hash_val]; @@ -354,25 +358,25 @@ st_table *old_table; int i, j, num_bins = old_table->num_bins; new_table = ALLOC(st_table, 1); - if (new_table == NIL(st_table)) { - return NIL(st_table); + if (new_table == NULL) { + return NULL; } *new_table = *old_table; new_table->bins = ALLOC(st_table_entry *, num_bins); - if (new_table->bins == NIL(st_table_entry *)) { + if (new_table->bins == NULL) { FREE(new_table); - return NIL(st_table); + return NULL; } for(i = 0; i < num_bins ; i++) { - new_table->bins[i] = NIL(st_table_entry); + new_table->bins[i] = NULL; ptr = old_table->bins[i]; - while (ptr != NIL(st_table_entry)) { + while (ptr != NULL) { new = ALLOC(st_table_entry, 1); - if (new == NIL(st_table_entry)) { + if (new == NULL) { for (j = 0; j <= i; j++) { newptr = new_table->bins[j]; - while (newptr != NIL(st_table_entry)) { + while (newptr != NULL) { next = newptr->next; FREE(newptr); newptr = next; @@ -380,7 +384,7 @@ st_table *old_table; } FREE(new_table->bins); FREE(new_table); - return NIL(st_table); + return NULL; } *new = *ptr; new->next = new_table->bins[i]; @@ -405,12 +409,12 @@ char **value; FIND_ENTRY(table, hash_val, key, ptr ,last); - if (ptr == NIL(st_table_entry)) { + if (ptr == NULL) { return 0; } *last = ptr->next; - if (value != NIL(char *)) *value = ptr->record; + if (value != NULL) *value = ptr->record; *keyp = ptr->key; FREE(ptr); table->num_entries--; @@ -431,12 +435,12 @@ char **value; FIND_ENTRY(table, hash_val, key, ptr ,last); - if (ptr == NIL(st_table_entry)) { + if (ptr == NULL) { return 0; } *last = ptr->next; - if (value != NIL(char *)) *value = ptr->record; + if (value != NULL) *value = ptr->record; *keyp = (long) ptr->key; FREE(ptr); table->num_entries--; @@ -455,7 +459,7 @@ char *arg; for(i = 0; i < table->num_bins; i++) { last = &table->bins[i]; ptr = *last; - while (ptr != NIL(st_table_entry)) { + while (ptr != NULL) { retval = (*func)(ptr->key, ptr->record, arg); switch (retval) { case ST_CONTINUE: @@ -528,11 +532,11 @@ st_table *table; st_generator *gen; gen = ALLOC(st_generator, 1); - if (gen == NIL(st_generator)) { - return NIL(st_generator); + if (gen == NULL) { + return NULL; } gen->table = table; - gen->entry = NIL(st_table_entry); + gen->entry = NULL; gen->index = 0; return gen; } @@ -546,16 +550,16 @@ char **value_p; { register int i; - if (gen->entry == NIL(st_table_entry)) { + if (gen->entry == NULL) { /* try to find next entry */ for(i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NIL(st_table_entry)) { + if (gen->table->bins[i] != NULL) { gen->index = i+1; gen->entry = gen->table->bins[i]; break; } } - if (gen->entry == NIL(st_table_entry)) { + if (gen->entry == NULL) { return 0; /* that's all folks ! */ } } @@ -576,21 +580,21 @@ long *value_p; { register int i; - if (gen->entry == NIL(st_table_entry)) { + if (gen->entry == NULL) { /* try to find next entry */ for(i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NIL(st_table_entry)) { + if (gen->table->bins[i] != NULL) { gen->index = i+1; gen->entry = gen->table->bins[i]; break; } } - if (gen->entry == NIL(st_table_entry)) { + if (gen->entry == NULL) { return 0; /* that's all folks ! */ } } *key_p = gen->entry->key; - if (value_p != NIL(long)) { + if (value_p != 0) { *value_p = (long) gen->entry->record; } gen->entry = gen->entry->next; diff --git a/src/misc/st/st.h b/src/misc/st/st.h index c51873e9..1802cf9b 100644 --- a/src/misc/st/st.h +++ b/src/misc/st/st.h @@ -48,28 +48,28 @@ enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE}; typedef enum st_retval (*ST_PFSR)(); typedef int (*ST_PFI)(); -EXTERN st_table *st_init_table_with_params ARGS((ST_PFI, ST_PFI, int, int, double, int)); -EXTERN st_table *st_init_table ARGS((ST_PFI, ST_PFI)); -EXTERN void st_free_table ARGS((st_table *)); -EXTERN int st_lookup ARGS((st_table *, char *, char **)); -EXTERN int st_lookup_int ARGS((st_table *, char *, int *)); -EXTERN int st_insert ARGS((st_table *, char *, char *)); -EXTERN int st_add_direct ARGS((st_table *, char *, char *)); -EXTERN int st_find_or_add ARGS((st_table *, char *, char ***)); -EXTERN int st_find ARGS((st_table *, char *, char ***)); -EXTERN st_table *st_copy ARGS((st_table *)); -EXTERN int st_delete ARGS((st_table *, char **, char **)); -EXTERN int st_delete_int ARGS((st_table *, long *, char **)); -EXTERN int st_foreach ARGS((st_table *, ST_PFSR, char *)); -EXTERN int st_strhash ARGS((char *, int)); -EXTERN int st_numhash ARGS((char *, int)); -EXTERN int st_ptrhash ARGS((char *, int)); -EXTERN int st_numcmp ARGS((char *, char *)); -EXTERN int st_ptrcmp ARGS((char *, char *)); -EXTERN st_generator *st_init_gen ARGS((st_table *)); -EXTERN int st_gen ARGS((st_generator *, char **, char **)); -EXTERN int st_gen_int ARGS((st_generator *, char **, long *)); -EXTERN void st_free_gen ARGS((st_generator *)); +extern st_table *st_init_table_with_params (ST_PFI, ST_PFI, int, int, double, int); +extern st_table *st_init_table (ST_PFI, ST_PFI); +extern void st_free_table (st_table *); +extern int st_lookup (st_table *, char *, char **); +extern int st_lookup_int (st_table *, char *, int *); +extern int st_insert (st_table *, 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 *, char **, char **); +extern int st_delete_int (st_table *, long *, char **); +extern int st_foreach (st_table *, ST_PFSR, char *); +extern int st_strhash (char *, int); +extern int st_numhash (char *, int); +extern int st_ptrhash (char *, int); +extern int st_numcmp (char *, char *); +extern int st_ptrcmp (char *, char *); +extern st_generator *st_init_gen (st_table *); +extern int st_gen (st_generator *, char **, char **); +extern int st_gen_int (st_generator *, char **, long *); +extern void st_free_gen (st_generator *); #define ST_DEFAULT_MAX_DENSITY 5 diff --git a/src/misc/st/stmm.c b/src/misc/st/stmm.c index b75b0134..c9b2320b 100644 --- a/src/misc/st/stmm.c +++ b/src/misc/st/stmm.c @@ -8,9 +8,13 @@ * */ #include <stdio.h> -#include "util.h" +#include "extra.h" #include "stmm.h" +#ifndef ABS +# define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif + #define STMM_NUMCMP(x,y) ((x) != (y)) #define STMM_NUMHASH(x,size) (ABS((long)x)%(size)) #define STMM_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) @@ -41,8 +45,8 @@ stmm_init_table_with_params (compare, hash, size, density, grow_factor, stmm_table *new; new = ALLOC (stmm_table, 1); - if (new == NIL (stmm_table)) { - return NIL (stmm_table); + if (new == NULL) { + return NULL; } new->compare = compare; new->hash = hash; @@ -55,9 +59,9 @@ stmm_init_table_with_params (compare, hash, size, density, grow_factor, } new->num_bins = size; new->bins = ALLOC (stmm_table_entry *, size); - if (new->bins == NIL (stmm_table_entry *)) { + if (new->bins == NULL) { FREE (new); - return NIL (stmm_table); + return NULL; } for (i = 0; i < size; i++) { new->bins[i] = 0; @@ -90,7 +94,7 @@ stmm_free_table (table) for ( i = 0; i < table->num_bins; i++ ) { ptr = table->bins[i]; - while ( ptr != NIL( stmm_table_entry ) ) + while ( ptr != NULL ) { next = ptr->next; FREE( ptr ); @@ -123,7 +127,7 @@ stmm_clean (table) #define PTR_NOT_EQUAL(table, ptr, user_key)\ -(ptr != NIL(stmm_table_entry) && !EQUAL(table->compare, user_key, (ptr)->key)) +(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) #define FIND_ENTRY(table, hash_val, key, ptr, last) \ (last) = &(table)->bins[hash_val];\ @@ -131,7 +135,7 @@ stmm_clean (table) while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ (last) = &(ptr)->next; (ptr) = *(last);\ }\ - if ((ptr) != NIL(stmm_table_entry) && (table)->reorder_flag) {\ + if ((ptr) != NULL && (table)->reorder_flag) {\ *(last) = (ptr)->next;\ (ptr)->next = (table)->bins[hash_val];\ (table)->bins[hash_val] = (ptr);\ @@ -150,11 +154,11 @@ stmm_lookup (table, key, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NIL (stmm_table_entry)) { + if (ptr == NULL) { return 0; } else { - if (value != NIL (char *)) + if (value != NULL) { *value = ptr->record; } @@ -175,11 +179,11 @@ stmm_lookup_int (table, key, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NIL (stmm_table_entry)) { + if (ptr == NULL) { return 0; } else { - if (value != NIL (int)) + if (value != 0) { *value = (long) ptr->record; } @@ -223,7 +227,7 @@ stmm_insert (table, key, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NIL (stmm_table_entry)) { + 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; @@ -233,7 +237,7 @@ stmm_insert (table, key, value) // new = ALLOC( stmm_table_entry, 1 ); new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NIL (stmm_table_entry)) { + if (new == NULL) { return STMM_OUT_OF_MEM; } @@ -269,7 +273,7 @@ stmm_add_direct (table, key, value) // new = ALLOC( stmm_table_entry, 1 ); new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NIL (stmm_table_entry)) { + if (new == NULL) { return STMM_OUT_OF_MEM; } @@ -294,7 +298,7 @@ stmm_find_or_add (table, key, slot) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NIL (stmm_table_entry)) { + 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; @@ -304,7 +308,7 @@ stmm_find_or_add (table, key, slot) // new = ALLOC( stmm_table_entry, 1 ); new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NIL (stmm_table_entry)) { + if (new == NULL) { return STMM_OUT_OF_MEM; } @@ -313,12 +317,12 @@ stmm_find_or_add (table, key, slot) new->next = table->bins[hash_val]; table->bins[hash_val] = new; table->num_entries++; - if (slot != NIL (char **)) + if (slot != NULL) *slot = &new->record; return 0; } else { - if (slot != NIL (char **)) + if (slot != NULL) *slot = &ptr->record; return 1; } @@ -337,11 +341,11 @@ stmm_find (table, key, slot) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NIL (stmm_table_entry)) { + if (ptr == NULL) { return 0; } else { - if (slot != NIL (char **)) + if (slot != NULL) { *slot = &ptr->record; } @@ -368,7 +372,7 @@ rehash (table) } table->num_entries = 0; table->bins = ALLOC (stmm_table_entry *, table->num_bins); - if (table->bins == NIL (stmm_table_entry *)) { + if (table->bins == NULL) { table->bins = old_bins; table->num_bins = old_num_bins; table->num_entries = old_num_entries; @@ -382,7 +386,7 @@ rehash (table) /* copy data over */ for (i = 0; i < old_num_bins; i++) { ptr = old_bins[i]; - while (ptr != NIL (stmm_table_entry)) { + while (ptr != NULL) { next = ptr->next; hash_val = do_hash (ptr->key, table); ptr->next = table->bins[hash_val]; @@ -405,15 +409,15 @@ stmm_copy (old_table) int i, /*j, */ num_bins = old_table->num_bins; new_table = ALLOC (stmm_table, 1); - if (new_table == NIL (stmm_table)) { - return NIL (stmm_table); + if (new_table == NULL) { + return NULL; } *new_table = *old_table; new_table->bins = ALLOC (stmm_table_entry *, num_bins); - if (new_table->bins == NIL (stmm_table_entry *)) { + if (new_table->bins == NULL) { FREE (new_table); - return NIL (stmm_table); + return NULL; } // allocate the memory manager for the new table @@ -421,20 +425,20 @@ stmm_copy (old_table) Extra_MmFixedStart (sizeof (stmm_table_entry)); for (i = 0; i < num_bins; i++) { - new_table->bins[i] = NIL (stmm_table_entry); + new_table->bins[i] = NULL; ptr = old_table->bins[i]; - while (ptr != NIL (stmm_table_entry)) { + while (ptr != NULL) { // new = ALLOC( stmm_table_entry, 1 ); new = (stmm_table_entry *) Extra_MmFixedEntryFetch (new_table-> pMemMan); - if (new == NIL (stmm_table_entry)) { + if (new == NULL) { /* for ( j = 0; j <= i; j++ ) { newptr = new_table->bins[j]; - while ( newptr != NIL( stmm_table_entry ) ) + while ( newptr != NULL ) { next = newptr->next; FREE( newptr ); @@ -446,7 +450,7 @@ stmm_copy (old_table) FREE (new_table->bins); FREE (new_table); - return NIL (stmm_table); + return NULL; } *new = *ptr; new->next = new_table->bins[i]; @@ -471,12 +475,12 @@ stmm_delete (table, keyp, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NIL (stmm_table_entry)) { + if (ptr == NULL) { return 0; } *last = ptr->next; - if (value != NIL (char *)) + if (value != NULL) *value = ptr->record; *keyp = ptr->key; // FREE( ptr ); @@ -500,12 +504,12 @@ stmm_delete_int (table, keyp, value) FIND_ENTRY (table, hash_val, key, ptr, last); - if (ptr == NIL (stmm_table_entry)) { + if (ptr == NULL) { return 0; } *last = ptr->next; - if (value != NIL (char *)) + if (value != NULL) *value = ptr->record; *keyp = (long) ptr->key; // FREE( ptr ); @@ -528,7 +532,7 @@ stmm_foreach (table, func, arg) for (i = 0; i < table->num_bins; i++) { last = &table->bins[i]; ptr = *last; - while (ptr != NIL (stmm_table_entry)) { + while (ptr != NULL) { retval = (*func) (ptr->key, ptr->record, arg); switch (retval) { case STMM_CONTINUE: @@ -604,11 +608,11 @@ stmm_init_gen (table) stmm_generator *gen; gen = ALLOC (stmm_generator, 1); - if (gen == NIL (stmm_generator)) { - return NIL (stmm_generator); + if (gen == NULL) { + return NULL; } gen->table = table; - gen->entry = NIL (stmm_table_entry); + gen->entry = NULL; gen->index = 0; return gen; } @@ -622,16 +626,16 @@ stmm_gen (gen, key_p, value_p) { register int i; - if (gen->entry == NIL (stmm_table_entry)) { + if (gen->entry == NULL) { /* try to find next entry */ for (i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NIL (stmm_table_entry)) { + if (gen->table->bins[i] != NULL) { gen->index = i + 1; gen->entry = gen->table->bins[i]; break; } } - if (gen->entry == NIL (stmm_table_entry)) { + if (gen->entry == NULL) { return 0; /* that's all folks ! */ } } @@ -652,21 +656,21 @@ stmm_gen_int (gen, key_p, value_p) { register int i; - if (gen->entry == NIL (stmm_table_entry)) { + if (gen->entry == NULL) { /* try to find next entry */ for (i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NIL (stmm_table_entry)) { + if (gen->table->bins[i] != NULL) { gen->index = i + 1; gen->entry = gen->table->bins[i]; break; } } - if (gen->entry == NIL (stmm_table_entry)) { + if (gen->entry == NULL) { return 0; /* that's all folks ! */ } } *key_p = gen->entry->key; - if (value_p != NIL (long)) + if (value_p != 0) { *value_p = (long) gen->entry->record; } diff --git a/src/misc/st/stmm.h b/src/misc/st/stmm.h index 1fe3dfd2..d7b8a3f3 100644 --- a/src/misc/st/stmm.h +++ b/src/misc/st/stmm.h @@ -93,7 +93,7 @@ EXTERN void stmm_clean ARGS ((stmm_table *)); // added by Zhihong: no need for memory allocation #define stmm_foreach_item2(tb, /* stmm_generator */gen, key, value) \ - for(gen.table=(tb), gen.entry=NIL(stmm_table_entry), gen.index=0; \ + for(gen.table=(tb), gen.entry=NULL, gen.index=0; \ stmm_gen(&(gen),key,value);) #define stmm_foreach_item(table, gen, key, value) \ diff --git a/src/misc/util/cpu_stats.c b/src/misc/util/cpu_stats.c deleted file mode 100644 index aa2d18ef..00000000 --- a/src/misc/util/cpu_stats.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/util/cpu_stats.c,v - * rajeev - * 1.4 - * 1995/08/08 22:41:17 - * - */ -/* LINTLIBRARY */ - -#include <stdio.h> -#include "util.h" - - -#include <sys/types.h> -//#include <sys/time.h> -#ifdef HAVE_SYS_RESOURCE_H -# include <sys/resource.h> -#endif - -#if defined(_IBMR2) -#define etext _etext -#define edata _edata -#define end _end -#endif - -#ifndef __CYGWIN32__ -extern int end, etext, edata; -#endif - -void -util_print_cpu_stats(fp) -FILE *fp; -{ - (void) fprintf(fp, "Usage statistics not available\n"); -} - -#if 0 - -void -util_print_cpu_stats(fp) -FILE *fp; -{ -#if HAVE_SYS_RESOURCE_H && !defined(__CYGWIN32__) - struct rusage rusage; -#ifdef RLIMIT_DATA - struct rlimit rlp; -#endif - int text, data, vm_limit, vm_soft_limit; - double user, system, scale; - char hostname[257]; - int vm_text, vm_init_data, vm_uninit_data, vm_sbrk_data; - - /* Get the hostname */ - (void) gethostname(hostname, 256); - hostname[256] = '\0'; /* just in case */ - - /* Get the virtual memory sizes */ - vm_text = ((int) (&etext)) / 1024.0 + 0.5; - vm_init_data = ((int) (&edata) - (int) (&etext)) / 1024.0 + 0.5; - vm_uninit_data = ((int) (&end) - (int) (&edata)) / 1024.0 + 0.5; - vm_sbrk_data = (sizeof(char) * ((char *) sbrk(0) - (char *) (&end))) / 1024.0 + 0.5; - - /* Get virtual memory limits */ -#ifdef RLIMIT_DATA /* In HP-UX, with cc, this constant does not exist */ - (void) getrlimit(RLIMIT_DATA, &rlp); - vm_limit = rlp.rlim_max / 1024.0 + 0.5; - vm_soft_limit = rlp.rlim_cur / 1024.0 + 0.5; -#else - vm_limit = -1; - vm_soft_limit = -1; -#endif - - /* Get usage stats */ - (void) getrusage(RUSAGE_SELF, &rusage); - user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec/1.0e6; - system = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec/1.0e6; - scale = (user + system)*100.0; - if (scale == 0.0) scale = 0.001; - - (void) fprintf(fp, "Runtime Statistics\n"); - (void) fprintf(fp, "------------------\n"); - (void) fprintf(fp, "Machine name: %s\n", hostname); - (void) fprintf(fp, "User time %6.1f seconds\n", user); - (void) fprintf(fp, "System time %6.1f seconds\n\n", system); - - text = rusage.ru_ixrss / scale + 0.5; - data = (rusage.ru_idrss + rusage.ru_isrss) / scale + 0.5; - (void) fprintf(fp, "Average resident text size = %5dK\n", text); - (void) fprintf(fp, "Average resident data+stack size = %5dK\n", data); - (void) fprintf(fp, "Maximum resident size = %5ldK\n\n", - rusage.ru_maxrss/2); - (void) fprintf(fp, "Virtual text size = %5dK\n", - vm_text); - (void) fprintf(fp, "Virtual data size = %5dK\n", - vm_init_data + vm_uninit_data + vm_sbrk_data); - (void) fprintf(fp, " data size initialized = %5dK\n", - vm_init_data); - (void) fprintf(fp, " data size uninitialized = %5dK\n", - vm_uninit_data); - (void) fprintf(fp, " data size sbrk = %5dK\n", - vm_sbrk_data); - /* In some platforms, this constant does not exist */ -#ifdef RLIMIT_DATA - (void) fprintf(fp, "Virtual memory limit = %5dK (%dK)\n\n", - vm_soft_limit, vm_limit); -#endif - (void) fprintf(fp, "Major page faults = %ld\n", rusage.ru_majflt); - (void) fprintf(fp, "Minor page faults = %ld\n", rusage.ru_minflt); - (void) fprintf(fp, "Swaps = %ld\n", rusage.ru_nswap); - (void) fprintf(fp, "Input blocks = %ld\n", rusage.ru_inblock); - (void) fprintf(fp, "Output blocks = %ld\n", rusage.ru_oublock); - (void) fprintf(fp, "Context switch (voluntary) = %ld\n", rusage.ru_nvcsw); - (void) fprintf(fp, "Context switch (involuntary) = %ld\n", rusage.ru_nivcsw); -#else /* Do not have sys/resource.h */ - (void) fprintf(fp, "Usage statistics not available\n"); -#endif -} - -#endif - diff --git a/src/misc/util/cpu_time.c b/src/misc/util/cpu_time.c deleted file mode 100644 index d264bdc9..00000000 --- a/src/misc/util/cpu_time.c +++ /dev/null @@ -1,128 +0,0 @@ -/**CFile*********************************************************************** - - FileName [ cpu_time.c ] - - PackageName [ util ] - - Synopsis [ System time calls ] - - Description [ The problem is that all unix systems have a different notion - of how fast time goes (i.e., the units returned by). This - returns a consistent result. ] - - Author [ Stephen Edwards <sedwards@eecs.berkeley.edu> and others ] - - Copyright [Copyright (c) 1994-1996 The Regents of the Univ. 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.] - -******************************************************************************/ - -#include "util.h" - -#if HAVE_SYS_TYPES_H -# include<sys/types.h> -#endif - -#if HAVE_SYS_TIMES_H -# include<sys/times.h> -#endif - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -/**Function******************************************************************** - - Synopsis [ Return elapsed time in milliseconds ] - - Description [ Return a long which represents the elapsed time in - milliseconds since some constant reference. <P> - - There are two possibilities: - <OL> - <LI> The system is non-POSIX compliant, so unistd.h - and hence sysconf() can't tell us the clock tick - speed. At this point, we have to resort to - using the user-settable CLOCK_RESOLUTION definition - to get the right speed - <LI> The system is POSIX-compliant. unistd.h gives - us sysconf(), which tells us the clock rate. - </OL> - ] - - SideEffects [ none ] - -******************************************************************************/ - -/* -long -util_cpu_time() -{ - long t = 0; - -#if HAVE_SYSCONF == 1 - - // Code for POSIX systems - - struct tms buffer; - long nticks; // number of clock ticks per second - - nticks = sysconf(_SC_CLK_TCK); - times(&buffer); - t = buffer.tms_utime * (1000.0/nticks); - -#else -# ifndef vms - - // Code for non-POSIX systems - - struct tms buffer; - - time(&buffer); - t = buffer.tms_utime * 1000.0 / CLOCK_RESOLUTION; - -# else - - // Code for VMS (?) - - struct {int p1, p2, p3, p4;} buffer; - static long ref_time; - times(&buffer); - t = buffer.p1 * 10; - if (ref_time == 0) - ref_time = t; - t = t - ref_time; - -# endif // vms -#endif // _POSIX_VERSION - - return t; -} -*/ - - -long -util_cpu_time() -{ - return clock(); -} diff --git a/src/misc/util/datalimit.c b/src/misc/util/datalimit.c deleted file mode 100644 index 96c2ce95..00000000 --- a/src/misc/util/datalimit.c +++ /dev/null @@ -1,95 +0,0 @@ -/**CFile************************************************************************ - - FileName [datalimit.c] - - PackageName [util] - - Synopsis [Routine to obtain the maximum data size available to a program. The - routine is based on "getrlimit". If the system does not have this function, - the default value RLIMIT_DATA_DEFAULT is assumed. This function provides an - informative value, it does not restrict the size of the program in any way.] - - Author [Fabio Somenzi <fabio@colorado.edu>] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util.h" - -static char rcsid[] UNUSED = "$Id: datalimit.c,v 1.1.1.1 2003/02/24 22:24:04 wjiang Exp $"; - -#if HAVE_SYS_RESOURCE_H -#if HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <sys/resource.h> -#endif - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef RLIMIT_DATA_DEFAULT -#define RLIMIT_DATA_DEFAULT 67108864 /* assume 64MB by default */ -#endif - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Function that computes the data limit of the process.] - - SideEffects [] - -******************************************************************************/ -int -getSoftDataLimit() -{ -#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && defined(RLIMIT_DATA) - struct rlimit rl; - int result; - - result = getrlimit(RLIMIT_DATA, &rl); - if (result != 0 || rl.rlim_cur == RLIM_INFINITY) - return(RLIMIT_DATA_DEFAULT); - else - return(rl.rlim_cur); -#else - return(RLIMIT_DATA_DEFAULT); -#endif - -} /* end of getSoftDataLimit */ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ diff --git a/src/misc/util/getopt.c b/src/misc/util/getopt.c deleted file mode 100644 index 778c34d6..00000000 --- a/src/misc/util/getopt.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/util/getopt.c,v - * rajeev - * 1.3 - * 1995/08/08 22:41:22 - * - */ -/* LINTLIBRARY */ - -#include <stdio.h> -#include "util.h" - - -/* 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. - */ - -char *util_optarg; /* Global argument pointer. */ -int util_optind = 0; /* Global argv index. */ -static char *scan; - - -void -util_getopt_reset() -{ - util_optarg = 0; - util_optind = 0; - scan = 0; -} - - - -int -util_getopt(argc, argv, optstring) -int argc; -char *argv[]; -char *optstring; -{ - register int c; - register char *place; - - util_optarg = NIL(char); - - if (scan == NIL(char) || *scan == '\0') { - if (util_optind == 0) util_optind++; - if (util_optind >= argc) return EOF; - place = argv[util_optind]; - if (place[0] != '-' || place[1] == '\0') return EOF; - util_optind++; - if (place[1] == '-' && place[2] == '\0') return EOF; - scan = place+1; - } - - c = *scan++; - place = strchr(optstring, c); - if (place == NIL(char) || c == ':') { - (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c); - return '?'; - } - if (*++place == ':') { - if (*scan != '\0') { - util_optarg = scan; - scan = NIL(char); - } else { - if (util_optind >= argc) { - (void) fprintf(stderr, "%s: %c requires an argument\n", - argv[0], c); - return '?'; - } - util_optarg = argv[util_optind]; - util_optind++; - } - } - return c; -} diff --git a/src/misc/util/leaks.h b/src/misc/util/leaks.h index daa628b1..1a32062a 100644 --- a/src/misc/util/leaks.h +++ b/src/misc/util/leaks.h @@ -1,8 +1,8 @@ -/////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // This file is used to detect memory leaks using Visual Studio 6.0 -// The idea comes from the following webpage: -// http://www.michaelmoser.org/memory.htm -////////////////////////////////////// +// The idea comes from this page: http://www.michaelmoser.org/memory.htm +// In addition to this file, it required the presence of "stdlib_hack.h" +////////////////////////////////////////////////////////////////////////// #ifndef __LEAKS_H__ #define __LEAKS_H__ diff --git a/src/misc/util/module.make b/src/misc/util/module.make index 06eba7e4..d6d908e7 100644 --- a/src/misc/util/module.make +++ b/src/misc/util/module.make @@ -1,8 +1 @@ -SRC += src/misc/util/cpu_stats.c \ - src/misc/util/cpu_time.c \ - src/misc/util/datalimit.c \ - src/misc/util/getopt.c \ - src/misc/util/pathsearch.c \ - src/misc/util/safe_mem.c \ - src/misc/util/strsav.c \ - src/misc/util/texpand.c +SRC += diff --git a/src/misc/util/pathsearch.c b/src/misc/util/pathsearch.c deleted file mode 100644 index d4d845eb..00000000 --- a/src/misc/util/pathsearch.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/util/pathsearch.c,v - * rajeev - * 1.3 - * 1995/08/08 22:41:24 - * - */ -/* LINTLIBRARY */ - -#if HAVE_SYS_FILE_H -# include <sys/file.h> -#endif - -#if HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif - -#include "util.h" - -/**Function******************************************************************** - - Synopsis [ Check that a given file is present and accessible ] - - SideEffects [none] -******************************************************************************/ -static int -check_file(filename, mode) -char *filename; -char *mode; -{ -#if defined(HAVE_SYS_STAT_H) - struct stat stat_rec; - int access_char = mode[0]; - int access_mode = R_OK; - - /* First check that the file is a regular file. */ - - if (stat(filename,&stat_rec) == 0 - && (stat_rec.st_mode&S_IFMT) == S_IFREG) { - if (access_char == 'w') { - access_mode = W_OK; - } else if (access_char == 'x') { - access_mode = X_OK; - } - return access(filename,access_mode) == 0; - } - return 0; - -#else - - 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; - -#endif -} - -/**Function******************************************************************** - - Synopsis [ Search for a program in all possible paths ] - - SideEffects [none] - -******************************************************************************/ -char * -util_path_search(prog) -char *prog; -{ -#ifdef HAVE_GETENV - return util_file_search(prog, getenv("PATH"), "x"); -#else - return util_file_search(prog, NIL(char), "x"); -#endif -} - -char * -util_file_search(file, path, 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 = util_strsav(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 = util_strsav(file); - } else { - buffer = ALLOC(char, strlen(path) + strlen(file) + 4); - (void) sprintf(buffer, "%s/%s", path, file); - } - filename = util_tilde_expand(buffer); - FREE(buffer); - - /* see if we can access it */ - if (check_file(filename, mode)) { - FREE(save_path); - return filename; - } - FREE(filename); - path = ++cp; - } while (! quit); - - FREE(save_path); - return 0; -} diff --git a/src/misc/util/safe_mem.c b/src/misc/util/safe_mem.c deleted file mode 100644 index 5a8a5de8..00000000 --- a/src/misc/util/safe_mem.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/util/safe_mem.c,v - * rajeev - * 1.3 - * 1995/08/08 22:41:29 - * - */ -/* LINTLIBRARY */ - -#include "util.h" - -/* - * These are interface routines to be placed between a program and the - * system memory allocator. - * - * It forces well-defined semantics for several 'borderline' cases: - * - * malloc() of a 0 size object is guaranteed to return something - * which is not 0, and can safely be freed (but not dereferenced) - * free() accepts (silently) an 0 pointer - * realloc of a 0 pointer is allowed, and is equiv. to malloc() - * For the IBM/PC it forces no object > 64K; note that the size argument - * to malloc/realloc is a 'long' to catch this condition - * - * The function pointer MMoutOfMemory() contains a vector to handle a - * 'out-of-memory' error (which, by default, points at a simple wrap-up - * and exit routine). - */ - -extern char *MMalloc(); -extern void MMout_of_memory(); -extern char *MMrealloc(); - - -void (*MMoutOfMemory)() = MMout_of_memory; - - -/* MMout_of_memory -- out of memory for lazy people, flush and exit */ -void -MMout_of_memory(size) -long size; -{ - (void) fflush(stdout); - (void) fprintf(stderr, "\nout of memory allocating %u bytes\n", - (unsigned) size); - assert( 0 ); - exit(1); -} - - -char * -MMalloc(size) -long size; -{ - char *p; - -#ifdef IBMPC - if (size > 65000L) { - if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size); - return NIL(char); - } -#endif - if (size == 0) size = sizeof(long); - if ((p = (char *) malloc((unsigned) size)) == NIL(char)) { - if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size); - return NIL(char); - } - return p; -} - - -char * -MMrealloc(obj, size) -char *obj; -long size; -{ - char *p; - -#ifdef IBMPC - if (size > 65000L) { - if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size); - return NIL(char); - } -#endif - if (obj == NIL(char)) return MMalloc(size); - if (size <= 0) size = sizeof(long); - if ((p = (char *) realloc(obj, (unsigned) size)) == NIL(char)) { - if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size); - return NIL(char); - } - return p; -} - - -void -MMfree(obj) -char *obj; -{ - if (obj != 0) { - free(obj); - } -} diff --git a/src/misc/util/strsav.c b/src/misc/util/strsav.c deleted file mode 100644 index 8da1f0c9..00000000 --- a/src/misc/util/strsav.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/util/strsav.c,v - * shiple - * 1.4 - * 1995/08/30 17:37:58 - * - */ -/* LINTLIBRARY */ - -#include <stdio.h> -#include "util.h" - - -/* - * util_strsav -- save a copy of a string - */ -char * -util_strsav(s) -char *s; -{ - if(s == NIL(char)) { /* added 7/95, for robustness */ - return s; - } - else { - return strcpy(ALLOC(char, strlen(s)+1), s); - } -} - -/* - * util_inttostr -- converts an integer into a string - */ -char * -util_inttostr(i) - int i; -{ - unsigned int mod, len; - char *s; - - if (i == 0) - len = 1; - else { - if (i < 0) { - len = 1; - mod = -i; - } - else { - len = 0; - mod = i; - } - len += (unsigned)floor(log10(mod)) + 1; - } - - s = ALLOC(char, len + 1); - sprintf(s, "%d", i); - - return s; -} - -/* - * util_strcat3 -- Creates a new string which is the concatenation of 3 - * strings. It is the responsibility of the caller to free this string - * using FREE. - */ -char * -util_strcat3( - char * str1, - char * str2, - char * str3) -{ - char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) + 1); - - (void) strcpy(str, str1); - (void) strcat(str, str2); - (void) strcat(str, str3); - - return (str); -} - -/* - * util_strcat4 -- Creates a new string which is the concatenation of 4 - * strings. It is the responsibility of the caller to free this string - * using FREE. - */ -char * -util_strcat4( - char * str1, - char * str2, - char * str3, - char * str4) -{ - char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) + - strlen(str4) + 1); - - (void) strcpy(str, str1); - (void) strcat(str, str2); - (void) strcat(str, str3); - (void) strcat(str, str4); - - return (str); -} - - -#if !HAVE_STRSTR -/**Function******************************************************************** - - Synopsis [required] - - Description [optional] - - SideEffects [required] - - SeeAlso [optional] - -******************************************************************************/ -char * -strstr( - const char * s, - const char * pat) -{ - int len; - - len = strlen(pat); - for (; *s != '\0'; ++s) - if (*s == *pat && memcmp(s, pat, len) == 0) { - return (char *)s; /* UGH */ - } - return NULL; -} -#endif /* !HAVE_STRSTR */ - -#if !HAVE_STRCHR -/**Function******************************************************************** - - Synopsis [required] - - Description [optional] - - SideEffects [required] - - SeeAlso [optional] - -******************************************************************************/ -char * -strchr(const char * s, - int c) -{ - for (; *s != '\0'; s++) { - if (*s == c) { - return (char *)s; - } - } - return NULL; - -} -#endif /* !HAVE_STRCHR */ diff --git a/src/misc/util/texpand.c b/src/misc/util/texpand.c deleted file mode 100644 index 37f71cbd..00000000 --- a/src/misc/util/texpand.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/util/texpand.c,v - * rajeev - * 1.3 - * 1995/08/08 22:41:36 - * - */ - -#include "util.h" - -#if HAVE_PWD_H -# include <pwd.h> -#endif - - -char * -util_tilde_expand(fname) -char *fname; -{ -#if HAVE_PWD_H - struct passwd *userRecord; - char username[256], *filename, *dir; - register int i, j; - - filename = ALLOC(char, strlen(fname) + 256); - - /* Clear the return string */ - i = 0; - filename[0] = '\0'; - - /* Tilde? */ - if (fname[0] == '~') { - j = 0; - i = 1; - while ((fname[i] != '\0') && (fname[i] != '/')) { - username[j++] = fname[i++]; - } - username[j] = '\0'; - dir = (char *)0; - if (username[0] == '\0') { - /* ~/ resolves to home directory of current user */ - userRecord = getpwuid(getuid()); - if (userRecord) dir = userRecord->pw_dir; - } else { - /* Special check for ~octtools */ - if (!strcmp(username,"octtools")) - dir = getenv("OCTTOOLS"); - /* ~user/ resolves to home directory of 'user' */ - if (!dir) { - userRecord = getpwnam(username); - if (userRecord) dir = userRecord->pw_dir; - } - } - if (dir) (void) strcat(filename, dir); - else i = 0; /* leave fname as-is */ - } /* if tilde */ - - /* Concantenate remaining portion of file name */ - (void) strcat(filename, fname + i); - return filename; -#else - return util_strsav(fname); -#endif -} diff --git a/src/misc/util/util.h b/src/misc/util/util.h deleted file mode 100644 index 0b147347..00000000 --- a/src/misc/util/util.h +++ /dev/null @@ -1,331 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [ util.h ] - - PackageName [ util ] - - Synopsis [ Very low-level utilities ] - - Description [ Includes file access, pipes, forks, time, and temporary file - access. ] - - Author [ Stephen Edwards <sedwards@eecs.berkeley.edu> and many others] - - Copyright [Copyright (c) 1994-1996 The Regents of the Univ. 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.] - - Revision [$Id: util.h,v 1.11 1998/05/04 02:05:08 hsv Exp $] - -******************************************************************************/ - -#ifndef _UTIL -#define _UTIL - -//////////////////////////////////////////// -#include "leaks.h" -//////////////////////////////////////////// - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -//////////////// added by alanmi, November 22, 2001 //////////////// -//#include <ctype.h> -#include <time.h> -#include <signal.h> - -#ifndef SIGALRM -#define SIGALRM SIGINT -#endif - -#ifndef SIGSTOP -#define SIGSTOP SIGINT -#endif - -#ifndef SIGXCPU -#define SIGXCPU SIGINT -#endif - -#ifndef SIGUSR1 -#define SIGUSR1 SIGINT -#endif - -#ifndef SIGKILL -#define SIGKILL SIGINT -#endif - -#ifndef HUGE -#define HUGE HUGE_VAL -#endif - -#if defined(__STDC__) -#define SIGNAL_FN void -#endif - -#define alarm(n) ((void)0) -#define kill(a,b) ((void)0) - -#define random rand -#define srandom srand -//////////////////////////////////////////////////////////////////// - - -#if HAVE_UNISTD_H -# include <unistd.h> -#endif - -#if HAVE_SYS_TYPES_H -# include <sys/types.h> -#endif - -#if HAVE_VARARGS_H -/////////////////////////////////////// -#undef __STDC__ -# include <varargs.h> -#define __STDC__ 1 -////////////////// alanmi Feb 03, 2001 -#endif - -#ifndef STDC_HEADERS -#define STDC_HEADERS 1 -#endif - -#ifndef HAVE_STRCHR -#define HAVE_STRCHR 1 -#endif - -#ifndef HAVE_GETENV -#define HAVE_GETENV 1 -#endif - -#if STDC_HEADERS -//# include <stdlib.h> -# include <string.h> -#else -# ifdef HAVE_STRCHR -char * strchr(); -int strcmp(); -# else -# define strchr index -# endif -# ifdef HAVE_GETENV -char * getenv(); -# endif -#endif /* STDC_HEADERS */ - -#if HAVE_ERRNO_H -# include <errno.h> -#endif - -/* - * Ensure we have reasonable assert() and fail() functions - */ - -#ifndef HAVE_ASSERT_H -#define HAVE_ASSERT_H 1 -#endif - -#if HAVE_ASSERT_H -# include <assert.h> -#else -# ifdef NDEBUG -# define assert(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 -#endif - -#define fail(why) {\ - (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ - __FILE__, __LINE__, why);\ - (void) fflush(stdout);\ - abort();\ -} - -/* - * Support for ANSI function prototypes in non-ANSI compilers - * - * Usage: - * extern int foo ARGS((char *, double)) - */ - -#ifndef ARGS -# ifdef __STDC__ -# define ARGS(args) args -# else -# define ARGS(args) () -# endif -#endif - -#ifndef NULLARGS -# ifdef __STDC__ -# define NULLARGS (void) -# else -# define NULLARGS () -# endif -#endif - -/* - * A little support for C++ compilers - */ - -#ifdef __cplusplus -# define EXTERN extern "C" -#else -# define EXTERN extern -#endif - -/* - * Support to define unused varibles - */ -#if (__GNUC__ >2 || __GNUC_MINOR__ >=7) && !defined(UNUSED) -#define UNUSED __attribute__ ((unused)) -#else -#define UNUSED -#endif - -/* - * A neater way to define zero pointers - * - * Usage: - * int * fred; - * fred = NIL(int); - */ - -#define NIL(type) ((type *) 0) - -/* - * Left over from SIS and Octtools: - */ - -//#define USE_MM -// uncommented this line, -// because to detect memory leaks, we need to work with malloc(), etc directly -#define USE_MM - - - -#ifdef USE_MM -/* - * assumes the memory manager is libmm.a (a deprecated (?) Octtools library) - * - 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 - */ -# 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) -EXTERN void MMout_of_memory ARGS((long)); -EXTERN char *MMalloc ARGS((long)); -EXTERN char *MMrealloc ARGS((char *, long)); -EXTERN void MMfree ARGS((char *)); -#endif - -#ifndef TRUE -# define TRUE 1 -#endif - -#ifndef FALSE -# define FALSE 0 -#endif - -#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 - -#define ptime() util_cpu_time() -#define print_time(t) util_print_time(t) - -#ifndef HUGE_VAL -# ifndef HUGE -# define HUGE 8.9884656743115790e+307 -# endif -# define HUGE_VAL HUGE -#endif - -#ifndef MAXINT -# define MAXINT (1 << 30) -#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 char *util_print_time ARGS((long)); -EXTERN int util_save_image ARGS((char *, char *)); -EXTERN char *util_strsav ARGS((char *)); -EXTERN char *util_inttostr ARGS((int)); -EXTERN char *util_strcat3 ARGS((char *, char *, char *)); -EXTERN char *util_strcat4 ARGS((char *, char *, char *, 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 void util_srandom ARGS((long)); -EXTERN long util_random ARGS(()); -EXTERN int getSoftDataLimit ARGS(()); - -/* - * Global variables for util_getopt() - */ - -extern int util_optind; -extern char *util_optarg; - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -#endif /* _UTIL */ diff --git a/src/misc/util/util_hack.h b/src/misc/util/util_hack.h new file mode 100644 index 00000000..57914c47 --- /dev/null +++ b/src/misc/util/util_hack.h @@ -0,0 +1,87 @@ +/**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 __UTIL_HACK_H__ +#define __UTIL_HACK_H__ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <time.h> +#include <math.h> + +#define EXTERN extern +#define NIL(type) ((type *) 0) +#define random rand +#define srandom srand + +#define util_cpu_time Extra_CpuTime +#define getSoftDataLimit Extra_GetSoftDataLimit +#define util_getopt_reset Extra_UtilGetoptReset +#define util_getopt Extra_UtilGetopt +#define util_print_time Extra_UtilPrintTime +#define util_strsav Extra_UtilStrsav +#define util_tilde_expand Extra_UtilTildeExpand +#define util_file_search Extra_UtilFileSearch +#define MMoutOfMemory Extra_UtilMMoutOfMemory + +#define util_optarg globalUtilOptarg +#define util_optind globalUtilOptind + +#ifndef ARGS +# ifdef __STDC__ +# define ARGS(args) args +# else +# define ARGS(args) () +# endif +#endif + +#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 + +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define REALLOC(type, obj, num) \ + (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num))) + +extern long Extra_CpuTime(); +extern int Extra_GetSoftDataLimit(); +extern void Extra_UtilGetoptReset(); +extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring ); +extern char * Extra_UtilPrintTime( long t ); +extern char * Extra_UtilStrsav( char *s ); +extern char * Extra_UtilTildeExpand( char *fname ); +extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); + +extern char * globalUtilOptarg; +extern int globalUtilOptind; + +#endif diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h index 7a96b0d7..06526332 100644 --- a/src/misc/vec/vecInt.h +++ b/src/misc/vec/vecInt.h @@ -25,7 +25,6 @@ /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include <stdio.h> #include "extra.h" //////////////////////////////////////////////////////////////////////// @@ -484,7 +483,7 @@ static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int /**Function************************************************************* - Synopsis [] + Synopsis [Inserts the entry while preserving the increasing order.] Description [] diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h index 5c9b2e8e..b724c976 100644 --- a/src/opt/cut/cut.h +++ b/src/opt/cut/cut.h @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////////////////// #define CUT_SIZE_MIN 3 // the min K of the K-feasible cut computation -#define CUT_SIZE_MAX 8 // the max 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 @@ -55,7 +55,7 @@ struct Cut_ParamsStruct_t_ int fFilter; // filter dominated cuts int fSeq; // compute sequential cuts int fDrop; // drop cuts on the fly - int fMulti; // compute cuts in multi-input AND gate graph + int fMulti; // compute factor-cuts int fRecord; // record the cut computation flow int fVerbose; // the verbosiness flag }; @@ -105,6 +105,7 @@ 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 ); diff --git a/src/opt/cut/cutInt.h b/src/opt/cut/cutInt.h index 51ff07f9..eca2fcd5 100644 --- a/src/opt/cut/cutInt.h +++ b/src/opt/cut/cutInt.h @@ -80,6 +80,7 @@ struct Cut_ManStruct_t_ int nCutsLimit; int nNodes; int nNodesMulti; + int nNodesMulti0; // runtime int timeMerge; int timeUnion; @@ -122,7 +123,6 @@ 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 int Cut_CutCountList( 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 ); diff --git a/src/opt/cut/cutMan.c b/src/opt/cut/cutMan.c index b2d62fce..8269da06 100644 --- a/src/opt/cut/cutMan.c +++ b/src/opt/cut/cutMan.c @@ -153,6 +153,15 @@ void Cut_ManPrintStats( Cut_Man_t * p ) 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) ); + if ( p->pParams->fMulti ) + { + printf( "Factor-cut computation statistics:\n" ); + printf( "Total nodes = %8d.\n", p->nNodes ); + printf( "Factor nodes = %8d.\n", p->nNodesMulti ); + printf( "Factor nodes 0 = %8d.\n", p->nNodesMulti0 ); + printf( "Factor cuts = %8d.\n", p->nCutsMulti ); + printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsMulti))/(p->nNodesMulti-p->nNodesMulti0) ); + } PRT( "Merge ", p->timeMerge ); PRT( "Union ", p->timeUnion ); PRT( "Filter", p->timeFilter ); diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c index 0268ba19..cace83bd 100644 --- a/src/opt/cut/cutNode.c +++ b/src/opt/cut/cutNode.c @@ -355,10 +355,19 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC { Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1; 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 ) return; - // start the new list + + // remember the old number of cuts nCutsOld = p->nCutsCur; Limit = p->pParams->nVarsMax; // get the simultation bit of the node @@ -373,15 +382,7 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC Cut_ListForEachCut( pList1, pStop1 ) if ( pStop1->nLeaves == (unsigned)Limit ) break; - // 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++; - nCutsOld++; - } + // small by small Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) @@ -424,6 +425,8 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC { p->nCutsMulti += p->nCutsCur - nCutsOld; p->nNodesMulti++; + if ( p->nCutsCur == nCutsOld ) + p->nNodesMulti0++; } } diff --git a/src/opt/dec/dec.h b/src/opt/dec/dec.h index b6b2524b..7b8b2e94 100644 --- a/src/opt/dec/dec.h +++ b/src/opt/dec/dec.h @@ -628,19 +628,75 @@ static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eE SeeAlso [] ***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) -{ - Dec_Edge_t eNode0, eNode1; - // derive the first AND - eEdge0.fCompl = !eEdge0.fCompl; - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - eEdge0.fCompl = !eEdge0.fCompl; - // derive the second AND - eEdge1.fCompl = !eEdge1.fCompl; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - eEdge1.fCompl = !eEdge1.fCompl; - // derive the final OR - return Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); +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; } //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/dec/decAbc.c b/src/opt/dec/decAbc.c index af76cd84..066b3bb2 100644 --- a/src/opt/dec/decAbc.c +++ b/src/opt/dec/decAbc.c @@ -18,7 +18,7 @@ #include "abc.h" #include "dec.h" -//#include "aig.h" +#include "aig.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -214,7 +214,6 @@ void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpda SeeAlso [] ***********************************************************************/ -/* Aig_Node_t * Dec_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph ) { Dec_Node_t * pNode; @@ -236,7 +235,7 @@ Aig_Node_t * Dec_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph ) // complement the result if necessary return Aig_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } -*/ + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/opt/fxu/fxuInt.h b/src/opt/fxu/fxuInt.h index 385cccef..d82a68db 100644 --- a/src/opt/fxu/fxuInt.h +++ b/src/opt/fxu/fxuInt.h @@ -23,7 +23,6 @@ /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -#include "util.h" #include "extra.h" #include "vec.h" diff --git a/src/opt/rwr/rwrDec.c b/src/opt/rwr/rwrDec.c index 45fcb02c..ef7af34f 100644 --- a/src/opt/rwr/rwrDec.c +++ b/src/opt/rwr/rwrDec.c @@ -135,7 +135,7 @@ Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * eNode1.fCompl = !eNode1.fCompl; // create the decomposition node(s) if ( pNode->fExor ) - eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1 ); + eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); else eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); // save the result diff --git a/src/opt/rwr/rwrEva.c b/src/opt/rwr/rwrEva.c index 3f3163f1..71d0b24d 100644 --- a/src/opt/rwr/rwrEva.c +++ b/src/opt/rwr/rwrEva.c @@ -66,7 +66,7 @@ int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int Required = fUpdateLevel? Abc_NodeReadRequiredLevel(pNode) : ABC_INFINITY; // get the node's cuts clk = clock(); - pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode ); + pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0 ); assert( pCut != NULL ); p->timeCut += clock() - clk; @@ -140,8 +140,9 @@ p->timeRes += clock() - clk; Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; p->nScores[p->pMap[uTruthBest]]++; - p->nNodesRewritten++; p->nNodesGained += GainBest; + if ( fUseZeros || GainBest > 0 ) + p->nNodesRewritten++; // report the progress if ( fVeryVerbose ) diff --git a/src/sat/aig/aig.h b/src/sat/aig/aig.h index ee029789..c83af527 100644 --- a/src/sat/aig/aig.h +++ b/src/sat/aig/aig.h @@ -300,8 +300,9 @@ extern void Aig_ManStop( Aig_Man_t * p ); /*=== aigNode.c =============================================================*/ extern Aig_Node_t * Aig_NodeCreateConst( Aig_Man_t * p ); extern Aig_Node_t * Aig_NodeCreatePi( Aig_Man_t * p ); -extern Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p, Aig_Node_t * pFanin ); +extern Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p ); extern Aig_Node_t * Aig_NodeCreateAnd( Aig_Man_t * p, Aig_Node_t * pFanin0, Aig_Node_t * pFanin1 ); +extern Aig_Node_t * Aig_NodeConnectPo( Aig_Man_t * p, Aig_Node_t * pNode, Aig_Node_t * pFanin ); extern void Aig_NodeConnectAnd( Aig_Node_t * pFanin0, Aig_Node_t * pFanin1, Aig_Node_t * pNode ); extern void Aig_NodeDisconnectAnd( Aig_Node_t * pNode ); extern void Aig_NodeDeleteAnd_rec( Aig_Man_t * pMan, Aig_Node_t * pRoot ); diff --git a/src/sat/aig/aigNode.c b/src/sat/aig/aigNode.c index 991cc7e5..ce458353 100644 --- a/src/sat/aig/aigNode.c +++ b/src/sat/aig/aigNode.c @@ -104,12 +104,30 @@ Aig_Node_t * Aig_NodeCreatePi( Aig_Man_t * p ) SeeAlso [] ***********************************************************************/ -Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p, Aig_Node_t * pFanin ) +Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p ) { Aig_Node_t * pNode; pNode = Aig_NodeCreate( p ); pNode->Type = AIG_PO; Vec_PtrPush( p->vPos, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates a primary output node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Node_t * Aig_NodeConnectPo( Aig_Man_t * p, Aig_Node_t * pNode, Aig_Node_t * pFanin ) +{ + assert( Aig_NodeIsPo(pNode) ); + assert( !Aig_IsComplement(pNode) ); // connect to the fanin pNode->Fans[0].fComp = Aig_IsComplement(pFanin); pNode->Fans[0].iNode = Aig_Regular(pFanin)->Id; @@ -224,13 +242,14 @@ void Aig_NodeDeleteAnd_rec( Aig_Man_t * pMan, Aig_Node_t * pRoot ) assert( !Aig_IsComplement(pRoot) ); assert( pRoot->nRefs == 0 ); assert( Aig_NodeIsAnd(pRoot) ); - // save the children + // remember the children pNode0 = Aig_NodeFanin0(pRoot); pNode1 = Aig_NodeFanin1(pRoot); // disconnect the node Aig_NodeDisconnectAnd( pRoot ); // recycle the node Vec_PtrWriteEntry( pMan->vNodes, pRoot->Id, NULL ); + memset( pRoot, 0, sizeof(Aig_Node_t) ); // this is a temporary hack to skip dead children below!!! Aig_MemFixedEntryRecycle( pMan->mmNodes, (char *)pRoot ); // call recursively if ( Aig_NodeIsAnd(pNode0) && pNode0->nRefs == 0 ) diff --git a/src/sat/aig/fraigCore.c b/src/sat/aig/fraigCore.c index decf05ee..525d4a14 100644 --- a/src/sat/aig/fraigCore.c +++ b/src/sat/aig/fraigCore.c @@ -92,7 +92,7 @@ Aig_ProofType_t Aig_FraigProveOutput( Aig_Man_t * pMan ) // solve the miter clk = clock(); pMan->pSat->verbosity = pMan->pParam->fSatVerbose; - status = solver_solve( pMan->pSat, NULL, NULL, pMan->pParam->nSeconds ); + status = solver_solve( pMan->pSat, NULL, NULL, 0, 0 );//pMan->pParam->nConfLimit, pMan->pParam->nImpLimit ); if ( status == l_Undef ) { // printf( "The problem timed out.\n" ); diff --git a/src/sat/aig/rwrMffc.c b/src/sat/aig/rwrMffc.c new file mode 100644 index 00000000..663534b3 --- /dev/null +++ b/src/sat/aig/rwrMffc.c @@ -0,0 +1,303 @@ +/**CFile**************************************************************** + + FileName [rwrMffc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Procedures working with Maximum Fanout-Free Cones.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrMffc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Aig_NodeDeref_rec( Aig_Node_t * pNode ); +extern int Aig_NodeRef_rec( Aig_Node_t * pNode ); +extern void Aig_NodeMffsConeSupp( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); +extern void Aig_NodeFactorConeSupp( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MffcTest( Aig_Man_t * pMan ) +{ + Aig_Node_t * pNode, * pNodeA, * pNodeB, * pNodeC, * pLeaf; + Vec_Ptr_t * vCone, * vSupp; + int i, k;//, nNodes1, nNodes2; + int nSizes = 0; + int nCones = 0; + int nMuxes = 0; + int nExors = 0; + + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + + // mark the multiple-fanout nodes + Aig_ManForEachAnd( pMan, pNode, i ) + if ( pNode->nRefs > 1 ) + pNode->fMarkA = 1; + // unmark the control inputs of MUXes and inputs of EXOR gates + Aig_ManForEachAnd( pMan, pNode, i ) + { + if ( !Aig_NodeIsMuxType(pNode) ) + continue; + + pNodeC = Aig_NodeRecognizeMux( pNode, &pNodeA, &pNodeB ); + // if real children are used, skip + if ( Aig_NodeFanin0(pNode)->nRefs > 1 || Aig_NodeFanin1(pNode)->nRefs > 1 ) + continue; +/* + + if ( pNodeC->nRefs == 2 ) + pNodeC->fMarkA = 0; + if ( Aig_Regular(pNodeA) == Aig_Regular(pNodeB) && Aig_Regular(pNodeA)->nRefs == 2 ) + Aig_Regular(pNodeA)->fMarkA = 0; +*/ + + if ( Aig_Regular(pNodeA) == Aig_Regular(pNodeB) ) + nExors++; + else + nMuxes++; + } + // mark the PO drivers + Aig_ManForEachPo( pMan, pNode, i ) + { + Aig_NodeFanin0(pNode)->fMarkA = 1; + Aig_NodeFanin0(pNode)->fMarkB = 1; + } + + + // print sizes of MFFCs + Aig_ManForEachAnd( pMan, pNode, i ) + { + if ( !pNode->fMarkA ) + continue; + +// nNodes1 = Aig_NodeDeref_rec( pNode ); +// Aig_NodeMffsConeSupp( pNode, vCone, vSupp ); +// nNodes2 = Aig_NodeRef_rec( pNode ); +// assert( nNodes1 == nNodes2 ); + + Aig_NodeFactorConeSupp( pNode, vCone, vSupp ); + + printf( "%6d : Fan = %4d. Co = %5d. Su = %5d. %s ", + pNode->Id, pNode->nRefs, Vec_PtrSize(vCone), Vec_PtrSize(vSupp), pNode->fMarkB? "po" : " " ); + + Vec_PtrForEachEntry( vSupp, pLeaf, k ) + printf( " %d", pLeaf->Id ); + + printf( "\n" ); + + nSizes += Vec_PtrSize(vCone); + nCones++; + } + printf( "Nodes = %6d. MFFC sizes = %6d. Cones = %6d. nExors = %6d. Muxes = %6d.\n", + Aig_ManAndNum(pMan), nSizes, nCones, nExors, nMuxes ); + + // unmark the nodes + Aig_ManForEachNode( pMan, pNode, i ) + { + pNode->fMarkA = 0; + pNode->fMarkB = 0; + pNode->fMarkC = 0; + } + + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeDeref_rec( Aig_Node_t * pNode ) +{ + Aig_Node_t * pNode0, * pNode1; + int Counter = 1; + if ( Aig_NodeIsPi(pNode) ) + return 0; + pNode0 = Aig_NodeFanin0(pNode); + pNode1 = Aig_NodeFanin1(pNode); + assert( pNode0->nRefs > 0 ); + assert( pNode1->nRefs > 0 ); + if ( --pNode0->nRefs == 0 ) + Counter += Aig_NodeDeref_rec( pNode0 ); + if ( --pNode1->nRefs == 0 ) + Counter += Aig_NodeDeref_rec( pNode1 ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeRef_rec( Aig_Node_t * pNode ) +{ + Aig_Node_t * pNode0, * pNode1; + int Counter = 1; + if ( Aig_NodeIsPi(pNode) ) + return 0; + pNode0 = Aig_NodeFanin0(pNode); + pNode1 = Aig_NodeFanin1(pNode); + if ( pNode0->nRefs++ == 0 ) + Counter += Aig_NodeRef_rec( pNode0 ); + if ( pNode1->nRefs++ == 0 ) + Counter += Aig_NodeRef_rec( pNode1 ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and leaf nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeMffsConeSupp_rec( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost ) +{ + // skip visited nodes + if ( Aig_NodeIsTravIdCurrent(pNode) ) + return; + Aig_NodeSetTravIdCurrent(pNode); + // add to the new support nodes + if ( !fTopmost && (Aig_NodeIsPi(pNode) || pNode->nRefs > 0) ) + { + Vec_PtrPush( vSupp, pNode ); + return; + } + // recur on the children + Aig_NodeMffsConeSupp_rec( Aig_NodeFanin0(pNode), vCone, vSupp, 0 ); + Aig_NodeMffsConeSupp_rec( Aig_NodeFanin1(pNode), vCone, vSupp, 0 ); + // collect the internal node + Vec_PtrPush( vCone, pNode ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeMffsConeSupp( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) +{ + assert( Aig_NodeIsAnd(pNode) ); + assert( !Aig_IsComplement(pNode) ); + Vec_PtrClear( vCone ); + Vec_PtrClear( vSupp ); + Aig_ManIncrementTravId( pNode->pMan ); + Aig_NodeMffsConeSupp_rec( pNode, vCone, vSupp, 1 ); +} + + + + + +/**Function************************************************************* + + Synopsis [Collects the internal and leaf nodes of the factor-cut of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeFactorConeSupp_rec( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost ) +{ + // skip visited nodes + if ( Aig_NodeIsTravIdCurrent(pNode) ) + return; + Aig_NodeSetTravIdCurrent(pNode); + // add to the new support nodes + if ( !fTopmost && (Aig_NodeIsPi(pNode) || pNode->fMarkA) ) + { + Vec_PtrPush( vSupp, pNode ); + return; + } + // recur on the children + Aig_NodeFactorConeSupp_rec( Aig_NodeFanin0(pNode), vCone, vSupp, 0 ); + Aig_NodeFactorConeSupp_rec( Aig_NodeFanin1(pNode), vCone, vSupp, 0 ); + // collect the internal node + assert( fTopmost || !pNode->fMarkA ); + Vec_PtrPush( vCone, pNode ); + + assert( pNode->fMarkC == 0 ); + pNode->fMarkC = 1; +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeFactorConeSupp( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) +{ + assert( Aig_NodeIsAnd(pNode) ); + assert( !Aig_IsComplement(pNode) ); + Vec_PtrClear( vCone ); + Vec_PtrClear( vSupp ); + Aig_ManIncrementTravId( pNode->pMan ); + Aig_NodeFactorConeSupp_rec( pNode, vCone, vSupp, 1 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/sat/aig/rwrTruth.c b/src/sat/aig/rwrTruth.c index 2c402184..63a437ce 100644 --- a/src/sat/aig/rwrTruth.c +++ b/src/sat/aig/rwrTruth.c @@ -444,6 +444,8 @@ Aig_Node_t * Aig_TruthDecompose( Aig_Truth_t * p ) assert( 0 ); } + + return NULL; } diff --git a/src/sat/aig/rwr_.c b/src/sat/aig/rwr_.c new file mode 100644 index 00000000..45e76f75 --- /dev/null +++ b/src/sat/aig/rwr_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [rwr_.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 - June 20, 2005.] + + Revision [$Id: rwr_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/sat/asat/asatmem.c b/src/sat/asat/asatmem.c new file mode 100644 index 00000000..24c1b1a8 --- /dev/null +++ b/src/sat/asat/asatmem.c @@ -0,0 +1,527 @@ +/**CFile**************************************************************** + + FileName [asatmem.c] + + PackageName [SAT solver.] + + Synopsis [Memory management.] + + Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: asatmem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "asatmem.h" +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Asat_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 Asat_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 Asat_MmStep_t_ +{ + int nMems; // the number of fixed memory managers employed + Asat_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Asat_MmFixed_t ** pMap; // maps the number of bytes into its memory manager +}; + +//////////////////////////////////////////////////////////////////////// +/// 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 [] + +***********************************************************************/ +Asat_MmFixed_t * Asat_MmFixedStart( int nEntrySize ) +{ + Asat_MmFixed_t * p; + + p = ALLOC( Asat_MmFixed_t, 1 ); + memset( p, 0, sizeof(Asat_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 = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_MmFixedStop( Asat_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++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Asat_MmFixedEntryFetch( Asat_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 = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = 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 Asat_MmFixedEntryRecycle( Asat_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 Asat_MmFixedRestart( Asat_MmFixed_t * p ) +{ + int i; + char * pTemp; + + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + 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 Asat_MmFixedReadMemUsage( Asat_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 [] + +***********************************************************************/ +Asat_MmFlex_t * Asat_MmFlexStart() +{ + Asat_MmFlex_t * p; + + p = ALLOC( Asat_MmFlex_t, 1 ); + memset( p, 0, sizeof(Asat_MmFlex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 12); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_MmFlexStop( Asat_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++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Asat_MmFlexEntryFetch( Asat_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 = 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 = 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 Asat_MmFlexReadMemUsage( Asat_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 free()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Asat_MmStep_t * Asat_MmStepStart( int nSteps ) +{ + Asat_MmStep_t * p; + int i, k; + p = ALLOC( Asat_MmStep_t, 1 ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ALLOC( Asat_MmFixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Asat_MmFixedStart( (8<<i) ); + // set up the mapping of the required memory size into the corresponding manager + p->nMapSize = (4<<p->nMems); + p->pMap = ALLOC( Asat_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<<i)+1; k <= (8<<i); k++ ) + p->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 Asat_MmStepStop( Asat_MmStep_t * p, int fVerbose ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Asat_MmFixedStop( p->pMems[i], fVerbose ); + free( p->pMems ); + free( p->pMap ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Asat_MmStepEntryFetch( Asat_MmStep_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; + if ( nBytes > p->nMapSize ) + { +// printf( "Allocating %d bytes.\n", nBytes ); + return ALLOC( char, nBytes ); + } + return Asat_MmFixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_MmStepEntryRecycle( Asat_MmStep_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; + if ( nBytes > p->nMapSize ) + { + free( pEntry ); + return; + } + Asat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Asat_MmStepReadMemUsage( Asat_MmStep_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} diff --git a/src/sat/asat/asatmem.h b/src/sat/asat/asatmem.h new file mode 100644 index 00000000..56115e7d --- /dev/null +++ b/src/sat/asat/asatmem.h @@ -0,0 +1,76 @@ +/**CFile**************************************************************** + + FileName [asatmem.h] + + PackageName [SAT solver.] + + Synopsis [Memory management.] + + Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: asatmem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __ASAT_MEM_H__ +#define __ASAT_MEM_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//#include "leaks.h" +#include <stdio.h> +#include <stdlib.h> + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Asat_MmFixed_t_ Asat_MmFixed_t; +typedef struct Asat_MmFlex_t_ Asat_MmFlex_t; +typedef struct Asat_MmStep_t_ Asat_MmStep_t; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// fixed-size-block memory manager +extern Asat_MmFixed_t * Asat_MmFixedStart( int nEntrySize ); +extern void Asat_MmFixedStop( Asat_MmFixed_t * p, int fVerbose ); +extern char * Asat_MmFixedEntryFetch( Asat_MmFixed_t * p ); +extern void Asat_MmFixedEntryRecycle( Asat_MmFixed_t * p, char * pEntry ); +extern void Asat_MmFixedRestart( Asat_MmFixed_t * p ); +extern int Asat_MmFixedReadMemUsage( Asat_MmFixed_t * p ); +// flexible-size-block memory manager +extern Asat_MmFlex_t * Asat_MmFlexStart(); +extern void Asat_MmFlexStop( Asat_MmFlex_t * p, int fVerbose ); +extern char * Asat_MmFlexEntryFetch( Asat_MmFlex_t * p, int nBytes ); +extern int Asat_MmFlexReadMemUsage( Asat_MmFlex_t * p ); +// hierarchical memory manager +extern Asat_MmStep_t * Asat_MmStepStart( int nSteps ); +extern void Asat_MmStepStop( Asat_MmStep_t * p, int fVerbose ); +extern char * Asat_MmStepEntryFetch( Asat_MmStep_t * p, int nBytes ); +extern void Asat_MmStepEntryRecycle( Asat_MmStep_t * p, char * pEntry, int nBytes ); +extern int Asat_MmStepReadMemUsage( Asat_MmStep_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/sat/asat/module.make b/src/sat/asat/module.make index 882176fa..d5cf69bf 100644 --- a/src/sat/asat/module.make +++ b/src/sat/asat/module.make @@ -1,2 +1,3 @@ SRC += src/sat/asat/added.c \ + src/sat/asat/asatmem.c \ src/sat/asat/solver.c diff --git a/src/sat/asat/solver.c b/src/sat/asat/solver.c index 3927fac3..1130d437 100644 --- a/src/sat/asat/solver.c +++ b/src/sat/asat/solver.c @@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "solver.h" +//#define ASAT_USE_SYSTEM_MEMORY_MANAGEMENT + //================================================================================================= // Simple (var/literal) helpers: @@ -275,7 +277,14 @@ static clause* clause_new(solver* s, lit* begin, lit* end, int learnt) assert(end - begin > 1); assert(learnt >= 0 && learnt < 2); size = end - begin; - c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float)); + +// c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float)); +#ifdef ASAT_USE_SYSTEM_MEMORY_MANAGEMENT + c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float)); +#else + c = (clause*)Asat_MmStepEntryFetch( s->pMem, sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float) ); +#endif + c->size_learnt = (size << 1) | learnt; assert(((unsigned int)c & 1) == 0); @@ -324,7 +333,12 @@ static void clause_remove(solver* s, clause* c) s->solver_stats.clauses_literals -= clause_size(c); } +#ifdef ASAT_USE_SYSTEM_MEMORY_MANAGEMENT free(c); +#else + Asat_MmStepEntryRecycle( s->pMem, (char *)c, sizeof(clause) + sizeof(lit) * clause_size(c) + clause_learnt(c) * sizeof(float) ); +#endif + } @@ -829,12 +843,24 @@ static lbool solver_search(solver* s, int nof_conflicts, int nof_learnts) // NO CONFLICT int next; - if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ + if (nof_conflicts >= 0 && conflictC >= nof_conflicts) + { // Reached bound on number of conflicts: s->progress_estimate = solver_progress(s); solver_canceluntil(s,s->root_level); vec_delete(&learnt_clause); - return l_Undef; } + return l_Undef; + } + + if ( s->nConfLimit && s->solver_stats.conflicts > s->nConfLimit || + s->nImpLimit && s->solver_stats.propagations > s->nImpLimit ) + { + // Reached bound on number of conflicts: + s->progress_estimate = solver_progress(s); + solver_canceluntil(s,s->root_level); + vec_delete(&learnt_clause); + return l_Undef; + } if (solver_dlevel(s) == 0) // Simplify the set of problem clauses: @@ -922,18 +948,28 @@ solver* solver_new(void) s->solver_stats.max_literals = 0; s->solver_stats.tot_literals = 0; +#ifdef ASAT_USE_SYSTEM_MEMORY_MANAGEMENT + s->pMem = NULL; +#else + s->pMem = Asat_MmStepStart( 10 ); +#endif + return s; } void solver_delete(solver* s) { + +#ifdef ASAT_USE_SYSTEM_MEMORY_MANAGEMENT int i; for (i = 0; i < vec_size(&s->clauses); i++) free(vec_begin(&s->clauses)[i]); - for (i = 0; i < vec_size(&s->learnts); i++) free(vec_begin(&s->learnts)[i]); +#else + Asat_MmStepStop( s->pMem, 0 ); +#endif // delete vectors vec_delete(&s->clauses); @@ -1056,14 +1092,18 @@ bool solver_simplify(solver* s) } -bool solver_solve(solver* s, lit* begin, lit* end, int nSeconds) +bool solver_solve(solver* s, lit* begin, lit* end, int nConfLimit, int nImpLimit ) { double nof_conflicts = 100; double nof_learnts = solver_nclauses(s) / 3; lbool status = l_Undef; lbool* values = s->assigns; lit* i; - int timeStart = clock(); + + // set the external limits + s->nConfLimit = nConfLimit; // external limit on the number of conflicts + s->nImpLimit = nImpLimit; // external limit on the number of implications + for (i = begin; i < end; i++) if ((lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]) == l_False || (assume(s,*i), solver_propagate(s) != 0)){ @@ -1098,9 +1138,18 @@ bool solver_solve(solver* s, lit* begin, lit* end, int nSeconds) status = solver_search(s,(int)nof_conflicts, (int)nof_learnts); nof_conflicts *= 1.5; nof_learnts *= 1.1; - // if the runtime limit is exceeded, quit the restart loop - if ( (nSeconds >= 0) && (clock() - timeStart >= nSeconds * CLOCKS_PER_SEC) ) + + // quit the loop if reached an external limit + if ( s->nConfLimit && s->solver_stats.conflicts > s->nConfLimit ) + { +// printf( "Reached the limit on the number of conflicts (%d).\n", s->nConfLimit ); break; + } + if ( s->nImpLimit && s->solver_stats.propagations > s->nImpLimit ) + { +// printf( "Reached the limit on the number of implications (%d).\n", s->nImpLimit ); + break; + } } if (s->verbosity >= 1) printf("==============================================================================\n"); diff --git a/src/sat/asat/solver.h b/src/sat/asat/solver.h index 9618603c..d798a7a9 100644 --- a/src/sat/asat/solver.h +++ b/src/sat/asat/solver.h @@ -27,6 +27,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #endif #include "solver_vec.h" +#include "asatmem.h" //================================================================================================= // Simple types: @@ -67,7 +68,7 @@ extern void solver_delete(solver* s); extern bool solver_addclause(solver* s, lit* begin, lit* end); extern bool solver_simplify(solver* s); -extern int solver_solve(solver* s, lit* begin, lit* end, int nSeconds); +extern int solver_solve(solver* s, lit* begin, lit* end, int nConfLimit, int nImpLimit ); extern int * solver_get_model( solver * p, int * pVars, int nVars ); extern int solver_nvars(solver* s); @@ -132,6 +133,12 @@ struct solver_t double progress_estimate; int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything + int nConfLimit; // external limit on the number of conflicts + int nImpLimit; // external limit on the number of implications + + // the memory manager + Asat_MmStep_t * pMem; + stats solver_stats; }; diff --git a/src/sat/csat/csat_apis.c b/src/sat/csat/csat_apis.c index d25e42db..d286ea9c 100644 --- a/src/sat/csat/csat_apis.c +++ b/src/sat/csat/csat_apis.c @@ -17,14 +17,15 @@ ***********************************************************************/ #include "abc.h" -#include "fraig.h" #include "csat_apis.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -#define ABC_DEFAULT_TIMEOUT 60 // 60 seconds +#define ABC_DEFAULT_CONF_LIMIT 0 // limit on conflicts +#define ABC_DEFAULT_IMP_LIMIT 0 // limit on implications + struct ABC_ManagerStruct_t { @@ -37,19 +38,24 @@ struct ABC_ManagerStruct_t Extra_MmFlex_t * pMmNames; // memory manager for signal names // solving parameters int mode; // 0 = brute-force SAT; 1 = resource-aware FRAIG - int nSeconds; // time limit for pure SAT solving - Fraig_Params_t Params; // the set of parameters to call FRAIG package + int nConfLimit; // time limit for pure SAT solving + int nImpLimit; // time limit for pure SAT solving +// Fraig_Params_t Params; // the set of parameters to call FRAIG package // information about the target int nog; // the numbers of gates in the target Vec_Ptr_t * vNodes; // the gates in the target Vec_Int_t * vValues; // the values of gate's outputs in the target // solution - ABC_Target_ResultT * pResult; // the result of solving the target + CSAT_Target_ResultT * pResult; // the result of solving the target }; -static ABC_Target_ResultT * ABC_TargetResAlloc( int nVars ); +static CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars ); static char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode ); +// procedures to start and stop the ABC framework +extern void Abc_Start(); +extern void Abc_Stop(); + // some external procedures extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); @@ -71,16 +77,18 @@ extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); ABC_Manager ABC_InitManager() { ABC_Manager_t * mng; + Abc_Start(); mng = ALLOC( ABC_Manager_t, 1 ); memset( mng, 0, sizeof(ABC_Manager_t) ); mng->pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP ); - mng->pNtk->pName = util_strsav("csat_network"); + mng->pNtk->pName = Extra_UtilStrsav("csat_network"); mng->tName2Node = stmm_init_table(strcmp, stmm_strhash); mng->tNode2Name = stmm_init_table(stmm_ptrcmp, stmm_ptrhash); mng->pMmNames = Extra_MmFlexStart(); mng->vNodes = Vec_PtrAlloc( 100 ); mng->vValues = Vec_IntAlloc( 100 ); - mng->nSeconds = ABC_DEFAULT_TIMEOUT; + mng->nConfLimit = ABC_DEFAULT_CONF_LIMIT; + mng->nImpLimit = ABC_DEFAULT_IMP_LIMIT; return mng; } @@ -95,7 +103,7 @@ ABC_Manager ABC_InitManager() SeeAlso [] ***********************************************************************/ -void ABC_QuitManager( ABC_Manager mng ) +void ABC_ReleaseManager( ABC_Manager mng ) { if ( mng->tNode2Name ) stmm_free_table( mng->tNode2Name ); if ( mng->tName2Node ) stmm_free_table( mng->tName2Node ); @@ -106,6 +114,7 @@ void ABC_QuitManager( ABC_Manager mng ) if ( mng->vValues ) Vec_IntFree( mng->vValues ); FREE( mng->pDumpFileName ); free( mng ); + Abc_Stop(); } /**Function************************************************************* @@ -119,7 +128,7 @@ void ABC_QuitManager( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -void ABC_SetSolveOption( ABC_Manager mng, enum ABC_OptionT option ) +void ABC_SetSolveOption( ABC_Manager mng, enum CSAT_OptionT option ) { mng->mode = option; if ( option == 0 ) @@ -160,23 +169,23 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha // consider different cases, create the node, and map the node into the name switch( type ) { - case ABC_BPI: - case ABC_BPPI: + case CSAT_BPI: + case CSAT_BPPI: if ( nofi != 0 ) { printf( "ABC_AddGate: The PI/PPI gate \"%s\" has fanins.\n", name ); return 0; } // create the PI pObj = Abc_NtkCreatePi( mng->pNtk ); stmm_insert( mng->tNode2Name, (char *)pObj, name ); break; - case ABC_CONST: - case ABC_BAND: - case ABC_BNAND: - case ABC_BOR: - case ABC_BNOR: - case ABC_BXOR: - case ABC_BXNOR: - case ABC_BINV: - case ABC_BBUF: + case CSAT_CONST: + case CSAT_BAND: + case CSAT_BNAND: + case CSAT_BOR: + case CSAT_BNOR: + case CSAT_BXOR: + case CSAT_BXNOR: + case CSAT_BINV: + case CSAT_BBUF: // create the node pObj = Abc_NtkCreateNode( mng->pNtk ); // create the fanins @@ -189,51 +198,51 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha // create the node function switch( type ) { - case ABC_CONST: + case CSAT_CONST: if ( nofi != 0 ) { printf( "ABC_AddGate: The constant gate \"%s\" has fanins.\n", name ); return 0; } pSop = Abc_SopCreateConst1( mng->pNtk->pManFunc ); break; - case ABC_BAND: + case CSAT_BAND: if ( nofi < 1 ) { printf( "ABC_AddGate: The AND gate \"%s\" no fanins.\n", name ); return 0; } pSop = Abc_SopCreateAnd( mng->pNtk->pManFunc, nofi, NULL ); break; - case ABC_BNAND: + case CSAT_BNAND: if ( nofi < 1 ) { printf( "ABC_AddGate: The NAND gate \"%s\" no fanins.\n", name ); return 0; } pSop = Abc_SopCreateNand( mng->pNtk->pManFunc, nofi ); break; - case ABC_BOR: + case CSAT_BOR: if ( nofi < 1 ) { printf( "ABC_AddGate: The OR gate \"%s\" no fanins.\n", name ); return 0; } pSop = Abc_SopCreateOr( mng->pNtk->pManFunc, nofi, NULL ); break; - case ABC_BNOR: + case CSAT_BNOR: if ( nofi < 1 ) { printf( "ABC_AddGate: The NOR gate \"%s\" no fanins.\n", name ); return 0; } pSop = Abc_SopCreateNor( mng->pNtk->pManFunc, nofi ); break; - case ABC_BXOR: + case CSAT_BXOR: if ( nofi < 1 ) { printf( "ABC_AddGate: The XOR gate \"%s\" no fanins.\n", name ); return 0; } if ( nofi > 2 ) { printf( "ABC_AddGate: The XOR gate \"%s\" has more than two fanins.\n", name ); return 0; } pSop = Abc_SopCreateXor( mng->pNtk->pManFunc, nofi ); break; - case ABC_BXNOR: + case CSAT_BXNOR: if ( nofi < 1 ) { printf( "ABC_AddGate: The XNOR gate \"%s\" no fanins.\n", name ); return 0; } if ( nofi > 2 ) { printf( "ABC_AddGate: The XNOR gate \"%s\" has more than two fanins.\n", name ); return 0; } pSop = Abc_SopCreateNxor( mng->pNtk->pManFunc, nofi ); break; - case ABC_BINV: + case CSAT_BINV: if ( nofi != 1 ) { printf( "ABC_AddGate: The inverter gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } pSop = Abc_SopCreateInv( mng->pNtk->pManFunc ); break; - case ABC_BBUF: + case CSAT_BBUF: if ( nofi != 1 ) { printf( "ABC_AddGate: The buffer gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } pSop = Abc_SopCreateBuf( mng->pNtk->pManFunc ); @@ -243,8 +252,8 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha } Abc_ObjSetData( pObj, pSop ); break; - case ABC_BPPO: - case ABC_BPO: + case CSAT_BPPO: + case CSAT_BPO: if ( nofi != 1 ) { printf( "ABC_AddGate: The PO/PPO gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } // create the PO @@ -268,38 +277,46 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha /**Function************************************************************* - Synopsis [Checks integraty of the manager.] + Synopsis [This procedure also finalizes construction of the ABC network.] - Description [Checks if there are gates that are not used by any primary output. - If no such gates exist, return 1 else return 0.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -int ABC_Check_Integrity( ABC_Manager mng ) +void ABC_Network_Finalize( ABC_Manager mng ) { Abc_Ntk_t * pNtk = mng->pNtk; Abc_Obj_t * pObj; int i; - - // this procedure also finalizes construction of the ABC network - Abc_NtkFixNonDrivenNets( pNtk ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkLogicStoreName( pObj, ABC_GetNodeName(mng, pObj) ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkLogicStoreName( pObj, ABC_GetNodeName(mng, pObj) ); assert( Abc_NtkLatchNum(pNtk) == 0 ); +} - // make sure everything is okay with the network structure - if ( !Abc_NtkDoCheck( pNtk ) ) - { - printf( "ABC_Check_Integrity: The internal network check has failed.\n" ); - return 0; - } +/**Function************************************************************* + + Synopsis [Checks integraty of the manager.] + + Description [Checks if there are gates that are not used by any primary output. + If no such gates exist, return 1 else return 0.] + + SideEffects [] + + SeeAlso [] - // check that there is no dangling nodes +***********************************************************************/ +int ABC_Check_Integrity( ABC_Manager mng ) +{ + Abc_Ntk_t * pNtk = mng->pNtk; + Abc_Obj_t * pObj; + int i; + + // check that there are no dangling nodes Abc_NtkForEachNode( pNtk, pObj, i ) { if ( i == 0 ) @@ -310,6 +327,13 @@ int ABC_Check_Integrity( ABC_Manager mng ) return 0; } } + + // make sure everything is okay with the network structure + if ( !Abc_NtkDoCheck( pNtk ) ) + { + printf( "ABC_Check_Integrity: The internal network check has failed.\n" ); + return 0; + } return 1; } @@ -326,7 +350,7 @@ int ABC_Check_Integrity( ABC_Manager mng ) ***********************************************************************/ void ABC_SetTimeLimit( ABC_Manager mng, int runtime ) { - mng->nSeconds = runtime; + printf( "ABC_SetTimeLimit: The resource limit is not implemented (warning).\n" ); } /**Function************************************************************* @@ -356,9 +380,25 @@ void ABC_SetLearnLimit( ABC_Manager mng, int num ) SeeAlso [] ***********************************************************************/ +void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num ) +{ + printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num ) { - printf( "ABC_SetSolveBacktrackLimit: The resource limit is not implemented (warning).\n" ); + mng->nConfLimit = num; } /**Function************************************************************* @@ -372,9 +412,9 @@ void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num ) SeeAlso [] ***********************************************************************/ -void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num ) +void ABC_SetSolveImplicationLimit( ABC_Manager mng, int num ) { - printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" ); + mng->nImpLimit = num; } /**Function************************************************************* @@ -391,7 +431,7 @@ void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num ) void ABC_EnableDump( ABC_Manager mng, char * dump_file ) { FREE( mng->pDumpFileName ); - mng->pDumpFileName = util_strsav( dump_file ); + mng->pDumpFileName = Extra_UtilStrsav( dump_file ); } /**Function************************************************************* @@ -447,9 +487,6 @@ int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values ) ***********************************************************************/ void ABC_SolveInit( ABC_Manager mng ) { - Fraig_Params_t * pParams = &mng->Params; - int nWords1, nWords2, nWordsMin; - // check if the target is available assert( mng->nog == Vec_PtrSize(mng->vNodes) ); if ( mng->nog == 0 ) @@ -459,30 +496,8 @@ void ABC_SolveInit( ABC_Manager mng ) if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget ); // set the new target network - mng->pTarget = Abc_NtkCreateCone( mng->pNtk, mng->vNodes, mng->vValues ); - - // 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(mng->pTarget) + Abc_NtkCiNum(mng->pTarget)); - nWordsMin = ABC_MIN( nWords1, nWords2 ); - - // set parameters for fraiging - memset( pParams, 0, sizeof(Fraig_Params_t) ); - 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 = 10; // the max number of backtracks to perform at a node - pParams->nSeconds = mng->nSeconds; // the time out for the final proof - pParams->fFuncRed = mng->mode; // 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 verbosiness flag for proof reporting + mng->pTarget = Abc_NtkCreateTarget( mng->pNtk, mng->vNodes, mng->vValues ); + } /**Function************************************************************* @@ -511,78 +526,35 @@ void ABC_AnalyzeTargets( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -enum ABC_StatusT ABC_Solve( ABC_Manager mng ) +enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) { - Fraig_Man_t * pMan; - Abc_Ntk_t * pCnf; - int * pModel; int RetValue, i; // check if the target network is available if ( mng->pTarget == NULL ) { printf( "ABC_Solve: Target network is not derived by ABC_SolveInit().\n" ); return UNDETERMINED; } - // optimizations of the target go here - // for example, to enable one pass of rewriting, uncomment this line -// Abc_NtkRewrite( mng->pTarget, 0, 1, 0 ); + // try to prove the miter using a number of techniques + RetValue = Abc_NtkMiterProve( &mng->pTarget, mng->nConfLimit, mng->nImpLimit, 1, 1, 0 ); - if ( mng->mode == 0 ) // brute-force SAT - { - // transform the AIG into a logic network for efficient CNF construction - pCnf = Abc_NtkRenode( mng->pTarget, 0, 100, 1, 0, 0 ); - RetValue = Abc_NtkMiterSat( pCnf, mng->nSeconds, 0 ); - - // analyze the result - mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); - if ( RetValue == -1 ) - mng->pResult->status = UNDETERMINED; - else if ( RetValue == 1 ) - mng->pResult->status = UNSATISFIABLE; - else if ( RetValue == 0 ) - { - mng->pResult->status = SATISFIABLE; - // create the array of PI names and values - for ( i = 0; i < mng->pResult->no_sig; i++ ) - { - mng->pResult->names[i] = ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)); // returns the same string that was given - mng->pResult->values[i] = pCnf->pModel[i]; - } - FREE( mng->pTarget->pModel ); - } - else assert( 0 ); - Abc_NtkDelete( pCnf ); - } - else if ( mng->mode == 1 ) // resource-aware fraiging + // analyze the result + mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); + if ( RetValue == -1 ) + mng->pResult->status = UNDETERMINED; + else if ( RetValue == 1 ) + mng->pResult->status = UNSATISFIABLE; + else if ( RetValue == 0 ) { - // transform the target into a fraig - pMan = Abc_NtkToFraig( mng->pTarget, &mng->Params, 0, 0 ); - Fraig_ManProveMiter( pMan ); - RetValue = Fraig_ManCheckMiter( pMan ); - - // analyze the result - mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); - if ( RetValue == -1 ) - mng->pResult->status = UNDETERMINED; - else if ( RetValue == 1 ) - mng->pResult->status = UNSATISFIABLE; - else if ( RetValue == 0 ) + mng->pResult->status = SATISFIABLE; + // create the array of PI names and values + for ( i = 0; i < mng->pResult->no_sig; i++ ) { - mng->pResult->status = SATISFIABLE; - pModel = Fraig_ManReadModel( pMan ); - assert( pModel != NULL ); - // create the array of PI names and values - for ( i = 0; i < mng->pResult->no_sig; i++ ) - { - mng->pResult->names[i] = ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)); // returns the same string that was given - mng->pResult->values[i] = pModel[i]; - } + mng->pResult->names[i] = Extra_UtilStrsav( ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)) ); + mng->pResult->values[i] = mng->pTarget->pModel[i]; } - else assert( 0 ); - // delete the fraig manager - Fraig_ManFree( pMan ); + FREE( mng->pTarget->pModel ); } - else - assert( 0 ); + else assert( 0 ); // delete the target Abc_NtkDelete( mng->pTarget ); @@ -602,7 +574,7 @@ enum ABC_StatusT ABC_Solve( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -ABC_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID ) +CSAT_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID ) { return mng->pResult; } @@ -615,7 +587,7 @@ ABC_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID ) SideEffects [] - SeeAlso [] + SeeAlso [] ***********************************************************************/ void ABC_Dump_Bench_File( ABC_Manager mng ) @@ -647,11 +619,11 @@ void ABC_Dump_Bench_File( ABC_Manager mng ) SeeAlso [] ***********************************************************************/ -ABC_Target_ResultT * ABC_TargetResAlloc( int nVars ) +CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars ) { - ABC_Target_ResultT * p; - p = ALLOC( ABC_Target_ResultT, 1 ); - memset( p, 0, sizeof(ABC_Target_ResultT) ); + CSAT_Target_ResultT * p; + p = ALLOC( CSAT_Target_ResultT, 1 ); + memset( p, 0, sizeof(CSAT_Target_ResultT) ); p->no_sig = nVars; p->names = ALLOC( char *, nVars ); p->values = ALLOC( int, nVars ); @@ -671,7 +643,7 @@ ABC_Target_ResultT * ABC_TargetResAlloc( int nVars ) SeeAlso [] ***********************************************************************/ -void ABC_TargetResFree( ABC_Target_ResultT * p ) +void ABC_TargetResFree( CSAT_Target_ResultT * p ) { if ( p == NULL ) return; @@ -702,100 +674,6 @@ char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode ) } - -/**Function************************************************************* - - Synopsis [This procedure applies a rewriting script to the network.] - - Description [Rewriting is performed without regard for the number of - logic levels. This corresponds to "circuit compression for formal - verification" (Per Bjesse et al, ICCAD 2004) but implemented in a more - exhaustive way than in the above paper.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_PerformRewriting( ABC_Manager mng ) -{ - void * pAbc; - char Command[1000]; - int clkBalan, clkResyn, clk; - int fPrintStats = 1; - int fUseResyn = 1; - - // procedures to get the ABC framework and execute commands in it - extern void * Abc_FrameGetGlobalFrame(); - extern void Abc_FrameReplaceCurrentNetwork( void * p, Abc_Ntk_t * pNtk ); - extern int Cmd_CommandExecute( void * p, char * sCommand ); - extern Abc_Ntk_t * Abc_FrameReadNtk( void * p ); - - - // get the pointer to the ABC framework - pAbc = Abc_FrameGetGlobalFrame(); - assert( pAbc != NULL ); - - // replace the current network by the target network - Abc_FrameReplaceCurrentNetwork( pAbc, mng->pTarget ); - -clk = clock(); - ////////////////////////////////////////////////////////////////////////// - // balance - sprintf( Command, "balance" ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return; - } -clkBalan = clock() - clk; - - ////////////////////////////////////////////////////////////////////////// - // print stats - if ( fPrintStats ) - { - sprintf( Command, "print_stats" ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return; - } - } - -clk = clock(); - ////////////////////////////////////////////////////////////////////////// - // synthesize - if ( fUseResyn ) - { - 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; - } - } -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; - } - } - printf( "Balancing = %6.2f sec ", (float)(clkBalan)/(float)(CLOCKS_PER_SEC) ); - printf( "Rewriting = %6.2f sec ", (float)(clkResyn)/(float)(CLOCKS_PER_SEC) ); - printf( "\n" ); - - // read the target network from the current network - mng->pTarget = Abc_NtkDup( Abc_FrameReadNtk(pAbc) ); -} - - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/csat/csat_apis.h b/src/sat/csat/csat_apis.h index a6179710..faba9ee4 100644 --- a/src/sat/csat/csat_apis.h +++ b/src/sat/csat/csat_apis.h @@ -12,13 +12,17 @@ Date [Ver. 1.0. Started - August 28, 2005] - Revision [$Id: csat_apis.h,v 1.00 2005/08/28 00:00:00 alanmi Exp $] + Revision [$Id: csat_apis.h,v 1.5 2005/12/30 10:54:40 rmukherj Exp $] ***********************************************************************/ #ifndef __ABC_APIS_H__ #define __ABC_APIS_H__ +#ifdef __cplusplus +extern "C" { +#endif + //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// @@ -42,27 +46,35 @@ typedef struct ABC_ManagerStruct_t * ABC_Manager; #define _ABC_GATE_TYPE_ enum GateType { - ABC_CONST = 0, // constant gate - ABC_BPI, // boolean PI - ABC_BPPI, // bit level PSEUDO PRIMARY INPUT - ABC_BAND, // bit level AND - ABC_BNAND, // bit level NAND - ABC_BOR, // bit level OR - ABC_BNOR, // bit level NOR - ABC_BXOR, // bit level XOR - ABC_BXNOR, // bit level XNOR - ABC_BINV, // bit level INVERTER - ABC_BBUF, // bit level BUFFER - ABC_BPPO, // bit level PSEUDO PRIMARY OUTPUT - ABC_BPO // boolean PO + CSAT_CONST = 0, // constant gate + CSAT_BPI, // boolean PI + CSAT_BPPI, // bit level PSEUDO PRIMARY INPUT + CSAT_BAND, // bit level AND + CSAT_BNAND, // bit level NAND + CSAT_BOR, // bit level OR + CSAT_BNOR, // bit level NOR + CSAT_BXOR, // bit level XOR + CSAT_BXNOR, // bit level XNOR + CSAT_BINV, // bit level INVERTER + CSAT_BBUF, // bit level BUFFER + CSAT_BMUX, // bit level MUX --not supported + CSAT_BDFF, // bit level D-type FF + CSAT_BSDFF, // bit level scan FF --not supported + CSAT_BTRIH, // bit level TRISTATE gate with active high control --not supported + CSAT_BTRIL, // bit level TRISTATE gate with active low control --not supported + CSAT_BBUS, // bit level BUS --not supported + CSAT_BPPO, // bit level PSEUDO PRIMARY OUTPUT + CSAT_BPO, // boolean PO + CSAT_BCNF, // boolean constraint + CSAT_BDC, // boolean don't care gate (2 input) }; #endif -//ABC_StatusT defines the return value by ABC_Solve(); +//CSAT_StatusT defines the return value by ABC_Solve(); #ifndef _ABC_STATUS_ #define _ABC_STATUS_ -enum ABC_StatusT +enum CSAT_StatusT { UNDETERMINED = 0, UNSATISFIABLE, @@ -76,11 +88,23 @@ enum ABC_StatusT #endif -// ABC_OptionT defines the solver option about learning +// to identify who called the CSAT solver +#ifndef _ABC_CALLER_ +#define _ABC_CALLER_ +enum CSAT_CallerT +{ + BLS = 0, + SATORI, + NONE +}; +#endif + + +// CSAT_OptionT defines the solver option about learning // which is used by ABC_SetSolveOption(); #ifndef _ABC_OPTION_ #define _ABC_OPTION_ -enum ABC_OptionT +enum CSAT_OptionT { BASE_LINE = 0, IMPLICT_LEARNING, //default @@ -91,10 +115,10 @@ enum ABC_OptionT #ifndef _ABC_Target_Result #define _ABC_Target_Result -typedef struct _ABC_Target_ResultT ABC_Target_ResultT; -struct _ABC_Target_ResultT +typedef struct _CSAT_Target_ResultT CSAT_Target_ResultT; +struct _CSAT_Target_ResultT { - enum ABC_StatusT status; // solve status of the target + enum CSAT_StatusT status; // solve status of the target int num_dec; // num of decisions to solve the target int num_imp; // num of implications to solve the target int num_cftg; // num of conflict gates learned @@ -118,10 +142,13 @@ struct _ABC_Target_ResultT //////////////////////////////////////////////////////////////////////// // create a new manager -extern ABC_Manager ABC_InitManager(void); +extern ABC_Manager ABC_InitManager(void); + +// release a manager +extern void ABC_ReleaseManager(ABC_Manager mng); // set solver options for learning -extern void ABC_SetSolveOption(ABC_Manager mng, enum ABC_OptionT option); +extern void ABC_SetSolveOption(ABC_Manager mng, enum CSAT_OptionT option); // add a gate to the circuit // the meaning of the parameters are: @@ -130,16 +157,19 @@ extern void ABC_SetSolveOption(ABC_Manager mng, enum ABC_Option // nofi: number of fanins of the gate to be added; // fanins: the name array of fanins of the gate to be added extern int ABC_AddGate(ABC_Manager mng, - enum GateType type, - char* name, - int nofi, - char** fanins, - int dc_attr); + enum GateType type, + char* name, + int nofi, + char** fanins, + int dc_attr); // check if there are gates that are not used by any primary ouput. // if no such gates exist, return 1 else return 0; extern int ABC_Check_Integrity(ABC_Manager mng); +// THIS PROCEDURE SHOULD BE CALLED AFTER THE NETWORK IS CONSTRUCTED!!! +extern void ABC_Network_Finalize( ABC_Manager mng ); + // set time limit for solving a target. // runtime: time limit (in second). extern void ABC_SetTimeLimit(ABC_Manager mng, int runtime); @@ -160,21 +190,24 @@ extern void ABC_SolveInit(ABC_Manager mng); extern void ABC_AnalyzeTargets(ABC_Manager mng); // solve the targets added by ABC_AddTarget() -extern enum ABC_StatusT ABC_Solve(ABC_Manager mng); +extern enum CSAT_StatusT ABC_Solve(ABC_Manager mng); // get the solve status of a target // TargetID: the target id returned by ABC_AddTarget(). -extern ABC_Target_ResultT * ABC_Get_Target_Result(ABC_Manager mng, int TargetID); +extern CSAT_Target_ResultT * ABC_Get_Target_Result(ABC_Manager mng, int TargetID); extern void ABC_Dump_Bench_File(ABC_Manager mng); // ADDED PROCEDURES: -extern void ABC_QuitManager( ABC_Manager mng ); -extern void ABC_TargetResFree( ABC_Target_ResultT * p ); +extern void ABC_TargetResFree( CSAT_Target_ResultT * p ); -extern void ABC_PerformRewriting( ABC_Manager mng ); +extern void CSAT_SetCaller(ABC_Manager mng, enum CSAT_CallerT caller); //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/sat/fraig/fraig.h b/src/sat/fraig/fraig.h index 237030af..4637c030 100644 --- a/src/sat/fraig/fraig.h +++ b/src/sat/fraig/fraig.h @@ -44,6 +44,8 @@ struct Fraig_ParamsStruct_t_ 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 nConfLimit; + int nImpLimit; int fFuncRed; // performs only one level hashing int fFeedBack; // enables solver feedback int fDist1Pats; // enables distance-1 patterns diff --git a/src/sat/fraig/fraigCanon.c b/src/sat/fraig/fraigCanon.c index fab01368..4ebb9a9f 100644 --- a/src/sat/fraig/fraigCanon.c +++ b/src/sat/fraig/fraigCanon.c @@ -49,7 +49,7 @@ Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ) { Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr; - int RetValue; +// int RetValue; // check for trivial cases if ( p1 == p2 ) @@ -9,8 +9,6 @@ Minor things: - QR's compilation problems -- add storage for internal memory for node names in the ABC_ package - - prevent node name clash between PO and internal names (i.e. [484]) - add the output of ABC version/platform in the output files |