From f936cc0680c98ffe51b3a1716c996072d5dbf76c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 18 Jan 2009 08:01:00 -0800 Subject: Version abc90118 --- Makefile | 7 +- abc.dsp | 262 +++-- abc.rc | 6 +- src/aig/aig/aig.h | 15 +- src/aig/aig/aigCanon.c | 694 +++++++++++++ src/aig/aig/aigDup.c | 1 + src/aig/aig/aigMan.c | 24 +- src/aig/aig/aigMffc.c | 28 +- src/aig/aig/aigObj.c | 9 + src/aig/aig/aigScl.c | 57 ++ src/aig/aig/aigTsim.c | 6 +- src/aig/aig/module.make | 1 + src/aig/bbr/bbrImage.c | 8 +- src/aig/bdc/bdcCore.c | 3 +- src/aig/bdc/bdcInt.h | 2 +- src/aig/cec/cec.h | 100 ++ src/aig/cec/cecAig.c | 151 +++ src/aig/cec/cecClass.c | 569 +++++++++++ src/aig/cec/cecCnf.c | 328 +++++++ src/aig/cec/cecCore.c | 233 +++++ src/aig/cec/cecInt.h | 220 +++++ src/aig/cec/cecMan.c | 59 ++ src/aig/cec/cecSat.c | 322 +++---- src/aig/cec/cecSim.c | 459 +++++++++ src/aig/cec/cecStatus.c | 187 ++++ src/aig/cec/module.make | 8 + src/aig/cgt/cgt.h | 3 +- src/aig/cgt/cgtAig.c | 381 +++++++- src/aig/cgt/cgtCore.c | 112 ++- src/aig/cgt/cgtDecide.c | 220 ++++- src/aig/cgt/cgtInt.h | 21 +- src/aig/cgt/cgtMan.c | 50 +- src/aig/cnf/cnfWrite.c | 2 +- src/aig/dar/dar.h | 5 +- src/aig/dar/darCore.c | 9 + src/aig/dar/darLib.c | 36 +- src/aig/dar/darRefact.c | 2 +- src/aig/dar/darScript.c | 17 +- src/aig/dch/dch.h | 1 + src/aig/dch/dchCore.c | 1 + src/aig/fra/fraSec.c | 2 +- src/aig/fsim/fsim.h | 97 ++ src/aig/fsim/fsimCore.c | 83 ++ src/aig/fsim/fsimFront.c | 364 +++++++ src/aig/fsim/fsimInt.h | 134 +++ src/aig/fsim/fsimMan.c | 207 ++++ src/aig/fsim/fsimSim.c | 560 +++++++++++ src/aig/fsim/fsimSwitch.c | 588 +++++++++++ src/aig/fsim/fsimTsim.c | 410 ++++++++ src/aig/fsim/module.make | 6 + src/aig/hop/hop.h | 5 +- src/aig/hop/hopObj.c | 1 + src/aig/hop/hopTruth.c | 12 +- src/aig/ioa/ioaWriteAig.c | 6 + src/aig/kit/kit.h | 15 +- src/aig/kit/kitDsd.c | 128 ++- src/aig/kit/kitTruth.c | 124 ++- src/aig/mfx/mfx.h | 1 + src/aig/mfx/mfxCore.c | 65 +- src/aig/mfx/mfxInt.h | 3 + src/aig/mfx/mfxMan.c | 2 + src/aig/mfx/mfxResub.c | 36 + src/aig/ntl/ntl.h | 31 +- src/aig/ntl/ntlCheck.c | 2 + src/aig/ntl/ntlCore.c | 4 +- src/aig/ntl/ntlExtract.c | 4 +- src/aig/ntl/ntlFraig.c | 51 +- src/aig/ntl/ntlInsert.c | 51 +- src/aig/ntl/ntlMan.c | 82 +- src/aig/ntl/ntlReadBlif.c | 3 + src/aig/ntl/ntlSweep.c | 9 +- src/aig/ntl/ntlTable.c | 37 +- src/aig/ntl/ntlUtil.c | 2 +- src/aig/ntl/ntlWriteBlif.c | 12 +- src/aig/nwk/nwk.h | 13 +- src/aig/nwk/nwkBidec.c | 53 +- src/aig/nwk/nwkMan.c | 42 +- src/aig/nwk/nwkMap.c | 26 +- src/aig/nwk/nwkMerge.c | 6 +- src/aig/nwk/nwkStrash.c | 1 + src/aig/nwk2/nwk.h | 2 +- src/aig/nwk2/nwkMan.c | 2 +- src/aig/saig/module.make | 10 +- src/aig/saig/saig.h | 32 +- src/aig/saig/saigAbs.c | 259 ++++- src/aig/saig/saigBmc.c | 82 +- src/aig/saig/saigDup.c | 6 +- src/aig/saig/saigLoc.c | 48 - src/aig/saig/saigMiter.c | 210 +++- src/aig/saig/saigPhase.c | 10 +- src/aig/saig/saigSimExt.c | 325 +++++++ src/aig/saig/saigSimFast.c | 443 +++++++++ src/aig/saig/saigSimMv.c | 726 ++++++++++++++ src/aig/saig/saigSimSeq.c | 513 ++++++++++ src/aig/saig/saigStrSim.c | 971 +++++++++++++++++++ src/aig/saig/saigSwitch.c | 582 +++++++++++ src/aig/saig/saigWnd.c | 809 ++++++++++++++++ src/aig/ssw/ssw.h | 20 +- src/aig/ssw/sswAig.c | 1 + src/aig/ssw/sswClass.c | 6 +- src/aig/ssw/sswCore.c | 10 +- src/aig/ssw/sswDyn.c | 106 +- src/aig/ssw/sswInt.h | 18 +- src/aig/ssw/sswIslands.c | 543 +++++++---- src/aig/ssw/sswMan.c | 5 + src/aig/ssw/sswPart.c | 2 +- src/aig/ssw/sswSim.c | 229 ++++- src/base/abc/abc.h | 18 +- src/base/abc/abcHie.c | 3 - src/base/abci/abc.c | 1984 +++++++++++++++++++++++++++++++------- src/base/abci/abc.zip | Bin 62408 -> 0 bytes src/base/abci/abcBidec.c | 33 +- src/base/abci/abcCut.c | 75 +- src/base/abci/abcDar.c | 726 +++++++++++++- src/base/abci/abcDelay.c | 297 ++++++ src/base/abci/abcIf.c | 58 +- src/base/abci/abcMap.c | 6 +- src/base/abci/abcMerge.c | 352 +++++++ src/base/abci/abcPrint.c | 82 +- src/base/abci/abcStrash.c | 8 +- src/base/abci/module.make | 1 + src/base/cmd/cmd.c | 1 + src/base/cmd/cmd.h | 8 +- src/base/io/io.c | 45 + src/base/io/ioAbc.h | 3 + src/base/io/ioReadAiger.c | 2 +- src/base/io/ioReadBlifMv.c | 3 +- src/base/io/ioUtil.c | 2 + src/base/io/ioWriteBook.c | 985 +++++++++++++++++++ src/base/io/io_.c | 48 - src/base/io/module.make | 1 + src/base/main/main.c | 6 +- src/base/main/main.h | 11 +- src/base/main/mainFrame.c | 2 + src/base/main/mainInt.h | 10 +- src/map/amap/amap.h | 83 ++ src/map/amap/amapCore.c | 103 ++ src/map/amap/amapGraph.c | 389 ++++++++ src/map/amap/amapInt.h | 380 ++++++++ src/map/amap/amapLib.c | 361 +++++++ src/map/amap/amapMan.c | 99 ++ src/map/amap/amapMatch.c | 538 +++++++++++ src/map/amap/amapMerge.c | 521 ++++++++++ src/map/amap/amapOutput.c | 181 ++++ src/map/amap/amapParse.c | 457 +++++++++ src/map/amap/amapPerm.c | 344 +++++++ src/map/amap/amapRead.c | 412 ++++++++ src/map/amap/amapRule.c | 368 +++++++ src/map/amap/amapUniq.c | 312 ++++++ src/map/amap/module.make | 12 + src/map/if/if.h | 9 + src/map/if/ifCut.c | 295 +++++- src/map/if/ifMan.c | 2 + src/map/if/ifMap.c | 10 +- src/map/if/ifReduce.c | 4 +- src/map/if/ifUtil.c | 5 + src/map/mapper/mapperTime.c | 2 +- src/map/mio/mio.c | 193 +++- src/map/mio/mio.h | 3 + src/map/mio/mio81214.zip | Bin 0 -> 16939 bytes src/map/mio/mioApi.c | 25 +- src/map/mio/mioGENERIC.c | 46 - src/map/mio/mioInt.h | 5 +- src/map/mio/mioRead.c | 81 ++ src/map/mio/mioUtils.c | 13 +- src/map/super/superGate.c | 7 +- src/misc/avl/avl.c | 616 ++++++++++++ src/misc/avl/avl.doc | 166 ++++ src/misc/avl/avl.h | 80 ++ src/misc/extra/extra.h | 21 +- src/misc/extra/extraUtilMemory.c | 4 +- src/misc/extra/extraUtilUtil.c | 16 + src/misc/util/leaks.h | 30 - src/misc/util/stdlib_hack.h | 4 - src/misc/vec/vec.h | 8 +- src/opt/cut/cut.h | 2 + src/opt/cut/cutNode.c | 7 + src/opt/lpk/lpkAbcDsd.c | 7 +- src/opt/lpk/lpkCore.c | 4 + src/opt/mfs/mfs.h | 1 + src/opt/mfs/mfsCore.c | 248 ++++- src/opt/mfs/mfsCore_.c | 388 ++++++++ src/opt/mfs/mfsInt.h | 5 + src/opt/mfs/mfsMan.c | 25 + src/opt/mfs/mfsResub.c | 67 +- src/opt/mfs/mfsResub_.c | 560 +++++++++++ src/opt/sim/simSwitch.c | 2 +- src/sat/bsat/satInterP.c | 150 ++- src/sat/bsat/satStore.h | 2 +- todo.txt | 5 + 190 files changed, 24755 insertions(+), 1560 deletions(-) create mode 100644 src/aig/aig/aigCanon.c create mode 100644 src/aig/cec/cec.h create mode 100644 src/aig/cec/cecAig.c create mode 100644 src/aig/cec/cecClass.c create mode 100644 src/aig/cec/cecCnf.c create mode 100644 src/aig/cec/cecCore.c create mode 100644 src/aig/cec/cecInt.h create mode 100644 src/aig/cec/cecMan.c create mode 100644 src/aig/cec/cecSim.c create mode 100644 src/aig/cec/cecStatus.c create mode 100644 src/aig/cec/module.make create mode 100644 src/aig/fsim/fsim.h create mode 100644 src/aig/fsim/fsimCore.c create mode 100644 src/aig/fsim/fsimFront.c create mode 100644 src/aig/fsim/fsimInt.h create mode 100644 src/aig/fsim/fsimMan.c create mode 100644 src/aig/fsim/fsimSim.c create mode 100644 src/aig/fsim/fsimSwitch.c create mode 100644 src/aig/fsim/fsimTsim.c create mode 100644 src/aig/fsim/module.make delete mode 100644 src/aig/saig/saigLoc.c create mode 100644 src/aig/saig/saigSimExt.c create mode 100644 src/aig/saig/saigSimFast.c create mode 100644 src/aig/saig/saigSimMv.c create mode 100644 src/aig/saig/saigSimSeq.c create mode 100644 src/aig/saig/saigStrSim.c create mode 100644 src/aig/saig/saigSwitch.c create mode 100644 src/aig/saig/saigWnd.c delete mode 100644 src/base/abci/abc.zip create mode 100644 src/base/abci/abcMerge.c create mode 100644 src/base/io/ioWriteBook.c delete mode 100644 src/base/io/io_.c create mode 100644 src/map/amap/amap.h create mode 100644 src/map/amap/amapCore.c create mode 100644 src/map/amap/amapGraph.c create mode 100644 src/map/amap/amapInt.h create mode 100644 src/map/amap/amapLib.c create mode 100644 src/map/amap/amapMan.c create mode 100644 src/map/amap/amapMatch.c create mode 100644 src/map/amap/amapMerge.c create mode 100644 src/map/amap/amapOutput.c create mode 100644 src/map/amap/amapParse.c create mode 100644 src/map/amap/amapPerm.c create mode 100644 src/map/amap/amapRead.c create mode 100644 src/map/amap/amapRule.c create mode 100644 src/map/amap/amapUniq.c create mode 100644 src/map/amap/module.make create mode 100644 src/map/mio/mio81214.zip delete mode 100644 src/map/mio/mioGENERIC.c create mode 100644 src/misc/avl/avl.c create mode 100644 src/misc/avl/avl.doc create mode 100644 src/misc/avl/avl.h delete mode 100644 src/misc/util/leaks.h delete mode 100644 src/misc/util/stdlib_hack.h create mode 100644 src/opt/mfs/mfsCore_.c create mode 100644 src/opt/mfs/mfsResub_.c diff --git a/Makefile b/Makefile index cfa819f4..e17a5d08 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,12 @@ MODULES := \ src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr \ src/bdd/parse src/bdd/reo src/bdd/cas \ src/map/fpga src/map/mapper src/map/mio src/map/super \ - src/map/if \ + src/map/if src/map/amap \ src/misc/extra src/misc/mvc src/misc/st src/misc/util \ src/misc/nm src/misc/vec src/misc/hash \ src/misc/bzlib src/misc/zlib \ src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr src/opt/mfs \ - src/opt/sim src/opt/ret src/opt/res src/opt/lpk src/opt/fret \ + src/opt/sim src/opt/ret src/opt/res src/opt/lpk \ src/sat/bsat src/sat/csat src/sat/msat src/sat/fraig \ src/sat/psat \ src/aig/ivy src/aig/hop src/aig/rwt src/aig/deco \ @@ -25,7 +25,8 @@ MODULES := \ src/aig/csw src/aig/ioa src/aig/aig src/aig/kit \ src/aig/bdc src/aig/bar src/aig/ntl src/aig/nwk \ src/aig/mfx src/aig/tim src/aig/saig src/aig/bbr \ - src/aig/int src/aig/dch src/aig/ssw src/aig/cgt + src/aig/int src/aig/dch src/aig/ssw src/aig/cgt \ + src/aig/cec src/aig/fsim default: $(PROG) diff --git a/abc.dsp b/abc.dsp index 9c87c7ee..f0bad559 100644 --- a/abc.dsp +++ b/abc.dsp @@ -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/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/misc/bzlib" /I "src/misc/zlib" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/sat/nsat" /I "src/sat/psat" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /I "src/aig/cgt" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D ABC_DLL=DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_LIBRARIES" /FR /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/misc/bzlib" /I "src/misc/zlib" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/sat/nsat" /I "src/sat/psat" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /I "src/aig/cgt" /I "src/aig/sec" /I "src/map/amap" /I "src/aig/fsim" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -50,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib m114pr.lib /nologo /subsystem:console /profile /machine:I386 /out:"_TEST/abc.exe" /libpath:"lib" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib m114pr.lib /nologo /subsystem:console /profile /machine:I386 /nodefaultlib:"libcp.lib libc.lib" /out:"_TEST/abc.exe" /libpath:"lib" !ELSEIF "$(CFG)" == "abc - Win32 Debug" @@ -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/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/misc/bzlib" /I "src/misc/zlib" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/sat/nsat" /I "src/sat/psat" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /I "src/aig/cgt" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D ABC_DLL=DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_LIBRARIES" /FR /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/misc/bzlib" /I "src/misc/zlib" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/sat/nsat" /I "src/sat/psat" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /I "src/aig/cgt" /I "src/aig/sec" /I "src/map/amap" /I "src/aig/fsim" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /GZ /c # SUBTRACT CPP /X # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -75,7 +75,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib m114pd.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abc.exe" /pdbtype:sept /libpath:"lib" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib m114pd.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcpd.lib libcd.lib" /out:"_TEST/abc.exe" /pdbtype:sept /libpath:"lib" !ENDIF @@ -290,6 +290,10 @@ SOURCE=.\src\base\abci\abcMeasure.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcMerge.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcMini.c # End Source File # Begin Source File @@ -538,6 +542,10 @@ SOURCE=.\src\base\io\ioWriteBlifMv.c # End Source File # Begin Source File +SOURCE=.\src\base\io\ioWriteBook.c +# End Source File +# Begin Source File + SOURCE=.\src\base\io\ioWriteCnf.c # End Source File # Begin Source File @@ -1640,26 +1648,6 @@ SOURCE=.\src\opt\lpk\lpkSets.c # Begin Group "fret" # PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\fret\fretFlow.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fret\fretime.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fret\fretInit.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fret\fretMain.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fret\fretTime.c -# End Source File # End Group # Begin Group "mfs" @@ -1961,96 +1949,72 @@ SOURCE=.\src\map\if\ifTruth.c SOURCE=.\src\map\if\ifUtil.c # End Source File # End Group -# Begin Group "pcm" +# Begin Group "ply" # PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\pcm\pcmCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmMap.c -# End Source File -# Begin Source File +# End Group +# Begin Group "pcm" -SOURCE=.\src\map\pcm\pcmReduce.c -# End Source File -# Begin Source File +# PROP Default_Filter "" +# End Group +# Begin Group "amap" -SOURCE=.\src\map\pcm\pcmTime.c -# End Source File +# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\map\pcm\pcmTruth.c +SOURCE=.\src\map\amap\amap.h # End Source File # Begin Source File -SOURCE=.\src\map\pcm\pcmUtil.c +SOURCE=.\src\map\amap\amapCore.c # End Source File -# End Group -# Begin Group "ply" - -# PROP Default_Filter "" # Begin Source File -SOURCE=.\src\map\ply\ply.h +SOURCE=.\src\map\amap\amapGraph.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyAbc.c +SOURCE=.\src\map\amap\amapInt.h # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyAig.c +SOURCE=.\src\map\amap\amapLib.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyFake.c +SOURCE=.\src\map\amap\amapMan.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyInt.h +SOURCE=.\src\map\amap\amapMatch.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyIter.c +SOURCE=.\src\map\amap\amapMerge.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyLib.c +SOURCE=.\src\map\amap\amapOutput.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyMan.c +SOURCE=.\src\map\amap\amapParse.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyMap.c +SOURCE=.\src\map\amap\amapPerm.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyNtk.c +SOURCE=.\src\map\amap\amapRead.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyPair.c +SOURCE=.\src\map\amap\amapRule.c # End Source File # Begin Source File -SOURCE=.\src\map\ply\plyPar.c +SOURCE=.\src\map\amap\amapUniq.c # End Source File # End Group # End Group @@ -2934,6 +2898,10 @@ SOURCE=.\src\aig\aig\aig.h # End Source File # Begin Source File +SOURCE=.\src\aig\aig\aigCanon.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\aig\aigCheck.c # End Source File # Begin Source File @@ -3310,10 +3278,6 @@ SOURCE=.\src\aig\saig\saigIoa.c # End Source File # Begin Source File -SOURCE=.\src\aig\saig\saigLoc.c -# End Source File -# Begin Source File - SOURCE=.\src\aig\saig\saigMiter.c # End Source File # Begin Source File @@ -3338,12 +3302,40 @@ SOURCE=.\src\aig\saig\saigScl.c # End Source File # Begin Source File +SOURCE=.\src\aig\saig\saigSimExt.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSimFast.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSimMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSimSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigStrSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSwitch.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\saig\saigSynch.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigTrans.c # End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigWnd.c +# End Source File # End Group # Begin Group "int" @@ -3532,6 +3524,46 @@ SOURCE=.\src\aig\ssw\sswUnique.c # Begin Group "cec" # PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\cec\cec.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cec\cecStatus.c +# End Source File # End Group # Begin Group "cgt" @@ -3565,6 +3597,90 @@ SOURCE=.\src\aig\cgt\cgtMan.c SOURCE=.\src\aig\cgt\cgtSat.c # End Source File # End Group +# Begin Group "sec" + +# PROP Default_Filter "" +# End Group +# Begin Group "nal" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\nal\nal.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalFlop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalFunc.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalModels.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\nal\nalWrite.c +# End Source File +# End Group +# Begin Group "fsim" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\fsim\fsim.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fsim\fsimCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fsim\fsimFront.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fsim\fsimInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fsim\fsimMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fsim\fsimSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fsim\fsimSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fsim\fsimTsim.c +# End Source File +# End Group # End Group # End Group # Begin Group "Header Files" diff --git a/abc.rc b/abc.rc index 1a2638e3..6deeeb51 100644 --- a/abc.rc +++ b/abc.rc @@ -22,10 +22,10 @@ set gnuplotunix gnuplot # standard aliases alias b balance +alias cg clockgate alias cl cleanup alias clp collapse alias cs care_set -alias dc2 dcompress2 alias esd ext_seq_dcs alias f fraig alias fs fraig_sweep @@ -40,6 +40,7 @@ alias pd print_dsd alias pex print_exdc -d alias pf print_factor alias pfan print_fanio +alias pg print_gates alias pl print_level alias plat print_latch alias pio print_io @@ -139,3 +140,6 @@ alias t2 "r i/intel_001.aig; ps; indcut -v" alias t "r c\s\0\000.aig; int" #alias t "r test/interpol.blif; st; int" +#read_library at\syn\brdcm.genlib + + diff --git a/src/aig/aig/aig.h b/src/aig/aig/aig.h index 0cdd5b1a..3db9b845 100644 --- a/src/aig/aig/aig.h +++ b/src/aig/aig/aig.h @@ -144,6 +144,7 @@ struct Aig_Man_t_ void * pImpData; // implication checking data void * pManTime; // the timing manager void * pManCuts; + int * pFastSim; Vec_Ptr_t * vMapped; Vec_Int_t * vFlopNums; Vec_Int_t * vFlopReprs; @@ -154,6 +155,7 @@ struct Aig_Man_t_ int fCreatePios; Vec_Int_t * vEquPairs; Vec_Vec_t * vClockDoms; + Vec_Int_t * vProbs; // probability of node being 1 // timing statistics int time1; int time2; @@ -195,14 +197,14 @@ struct Aig_ManCut_t_ }; #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif static inline Aig_Cut_t * Aig_ObjCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } @@ -338,6 +340,7 @@ static inline int Aig_ObjSetLevel( Aig_Obj_t * pObj, int i ) { assert( static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); } static inline Aig_Obj_t * Aig_ObjFanout0( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(p->pFanData && pObj->Id < p->nFansAlloc); return Aig_ManObj(p, p->pFanData[5*pObj->Id] >> 1); } static inline Aig_Obj_t * Aig_ObjEquiv( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs? p->pEquivs[pObj->Id] : NULL; } +static inline void Aig_ObjSetEquiv( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEqu ) { assert(p->pEquivs); p->pEquivs[pObj->Id] = pEqu; } static inline Aig_Obj_t * Aig_ObjRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pReprs? p->pReprs[pObj->Id] : NULL; } static inline void Aig_ObjSetRepr( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) { assert(p->pReprs); p->pReprs[pObj->Id] = pRepr; } static inline Aig_Obj_t * Aig_ObjHaig( Aig_Obj_t * pObj ) { assert( Aig_Regular(pObj)->pHaig ); return Aig_NotCond( Aig_Regular(pObj)->pHaig, Aig_IsComplement(pObj) ); } @@ -529,9 +532,9 @@ extern void Aig_ManStartMemory( Aig_Man_t * p ); extern void Aig_ManStopMemory( Aig_Man_t * p ); /*=== aigMffc.c ==========================================================*/ extern int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ); -extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin ); +extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs ); extern int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ); -extern int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode ); +extern int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower ); extern int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ); extern int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ); /*=== aigObj.c ==========================================================*/ diff --git a/src/aig/aig/aigCanon.c b/src/aig/aig/aigCanon.c new file mode 100644 index 00000000..febad8ae --- /dev/null +++ b/src/aig/aig/aigCanon.c @@ -0,0 +1,694 @@ +/**CFile**************************************************************** + + FileName [aigCanon.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Processing the library of semi-canonical AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigCanon.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "kit.h" +#include "bdc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define RMAN_MAXVARS 12 +#define RMAX_MAXWORD (RMAN_MAXVARS <= 5 ? 1 : (1 << (RMAN_MAXVARS - 5))) + +typedef struct Aig_VSig_t_ Aig_VSig_t; +struct Aig_VSig_t_ +{ + int nOnes; + short nCofOnes[RMAN_MAXVARS]; +}; + +typedef struct Aig_Tru_t_ Aig_Tru_t; +struct Aig_Tru_t_ +{ + Aig_Tru_t * pNext; + int Id; + unsigned nVisits : 27; + unsigned nVars : 5; + unsigned pTruth[0]; +}; + +typedef struct Aig_RMan_t_ Aig_RMan_t; +struct Aig_RMan_t_ +{ + int nVars; // the largest variable number + Aig_Man_t * pAig; // recorded subgraphs + // hash table + int nBins; + Aig_Tru_t ** pBins; + int nEntries; + Aig_MmFlex_t* pMemTrus; + // bidecomposion + Bdc_Man_t * pBidec; + // temporaries + unsigned pTruthInit[RMAX_MAXWORD]; // canonical truth table + unsigned pTruth[RMAX_MAXWORD]; // current truth table + unsigned pTruthC[RMAX_MAXWORD]; // canonical truth table + unsigned pTruthTemp[RMAX_MAXWORD]; // temporary truth table + Aig_VSig_t pMints[2*RMAN_MAXVARS]; // minterm count + char pPerm[RMAN_MAXVARS]; // permutation + char pPermR[RMAN_MAXVARS]; // reverse permutation + // statistics + int nVarFuncs[RMAN_MAXVARS+1]; + int nTotal; + int nTtDsd; + int nTtDsdPart; + int nTtDsdNot; + int nUniqueVars; +}; + +static Aig_RMan_t * s_pRMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates recording manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_RMan_t * Aig_RManStart() +{ + static Bdc_Par_t Pars = {0}, * pPars = &Pars; + Aig_RMan_t * p; + p = ALLOC( Aig_RMan_t, 1 ); + memset( p, 0, sizeof(Aig_RMan_t) ); + p->nVars = RMAN_MAXVARS; + p->pAig = Aig_ManStart( 1000000 ); + Aig_IthVar( p->pAig, p->nVars-1 ); + // create hash table + p->nBins = Aig_PrimeCudd(5000); + p->pBins = CALLOC( Aig_Tru_t *, p->nBins ); + p->pMemTrus = Aig_MmFlexStart(); + // bi-decomposition manager + pPars->nVarsMax = p->nVars; + pPars->fVerbose = 0; + p->pBidec = Bdc_ManAlloc( pPars ); + return p; +} + +/**Function************************************************************* + + Synopsis [Returns the hash key.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_RManTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes ) +{ + int i, nWords = Kit_TruthWordNum( nVars ); + unsigned uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pTruth[i] * pPrimes[i & 0xf]; + return (int)(uHash % nBins); +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Tru_t ** Aig_RManTableLookup( Aig_RMan_t * p, unsigned * pTruth, int nVars ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; + Aig_Tru_t ** ppSpot, * pEntry; + ppSpot = p->pBins + Aig_RManTableHash( pTruth, nVars, p->nBins, s_Primes ); + for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pNext, pEntry = pEntry->pNext ) + if ( Kit_TruthIsEqual( pEntry->pTruth, pTruth, nVars ) ) + return ppSpot; + return ppSpot; +} + +/**Function************************************************************* + + Synopsis [Find or add new entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManTableResize( Aig_RMan_t * p ) +{ + Aig_Tru_t * pEntry, * pNext; + Aig_Tru_t ** pBinsOld, ** ppPlace; + int nBinsOld, Counter, i, clk; + assert( p->pBins != NULL ); +clk = clock(); + // save the old Bins + pBinsOld = p->pBins; + nBinsOld = p->nBins; + // get the new Bins + p->nBins = Aig_PrimeCudd( 3 * nBinsOld ); + p->pBins = CALLOC( Aig_Tru_t *, p->nBins ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < nBinsOld; i++ ) + for ( pEntry = pBinsOld[i], pNext = pEntry? pEntry->pNext : NULL; + pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) + { + // get the place where this entry goes in the Bins + ppPlace = Aig_RManTableLookup( p, pEntry->pTruth, pEntry->nVars ); + assert( *ppPlace == NULL ); // should not be there + // add the entry to the list + *ppPlace = pEntry; + pEntry->pNext = NULL; + Counter++; + } + assert( Counter == p->nEntries ); +// PRT( "Time", clock() - clk ); + free( pBinsOld ); +} + +/**Function************************************************************* + + Synopsis [Find or add new entry.] + + Description [Returns 1 if this is a new entry.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_RManTableFindOrAdd( Aig_RMan_t * p, unsigned * pTruth, int nVars ) +{ + Aig_Tru_t ** ppSpot, * pEntry; + int nBytes; + ppSpot = Aig_RManTableLookup( p, pTruth, nVars ); + if ( *ppSpot ) + { + (*ppSpot)->nVisits++; + return 0; + } + nBytes = sizeof(Aig_Tru_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars); + if ( p->nEntries == 3*p->nBins ) + Aig_RManTableResize( p ); + pEntry = (Aig_Tru_t *)Aig_MmFlexEntryFetch( p->pMemTrus, nBytes ); + pEntry->Id = p->nEntries++; + pEntry->nVars = nVars; + pEntry->nVisits = 1; + pEntry->pNext = NULL; + memcpy( pEntry->pTruth, pTruth, sizeof(unsigned) * Kit_TruthWordNum(nVars) ); + *ppSpot = pEntry; + return 1; +} + +/**Function************************************************************* + + Synopsis [Deallocates recording manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManStop( Aig_RMan_t * p ) +{ + int i; + printf( "Total funcs = %10d\n", p->nTotal ); + printf( "Full DSD funcs = %10d\n", p->nTtDsd ); + printf( "Part DSD funcs = %10d\n", p->nTtDsdPart ); + printf( "Non- DSD funcs = %10d\n", p->nTtDsdNot ); + printf( "Uniq-var funcs = %10d\n", p->nUniqueVars ); + printf( "Unique funcs = %10d\n", p->nEntries ); + printf( "Distribution of functions:\n" ); + for ( i = 5; i <= p->nVars; i++ ) + printf( "%2d = %8d\n", i, p->nVarFuncs[i] ); + Aig_MmFlexStop( p->pMemTrus, 0 ); + Aig_ManStop( p->pAig ); + Bdc_ManFree( p->pBidec ); + free( p->pBins ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Stops recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManQuit() +{ + extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); + char Buffer[20]; + if ( s_pRMan == NULL ) + return; + // dump the library file + sprintf( Buffer, "aiglib%02d.aig", s_pRMan->nVars ); + Ioa_WriteAiger( s_pRMan->pAig, Buffer, 0, 1 ); + // quit the manager + Aig_RManStop( s_pRMan ); + s_pRMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if all variables are unique.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManPrintVarProfile( unsigned * pTruth, int nVars, unsigned * pTruthAux ) +{ + short pStore2[32]; + int i; + Kit_TruthCountOnesInCofsSlow( pTruth, nVars, pStore2, pTruthAux ); + for ( i = 0; i < nVars; i++ ) + printf( "%2d/%2d ", pStore2[2*i], pStore2[2*i+1] ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Sorts numbers in the increasing order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManSortNums( short * pArray, int nVars ) +{ + int i, j, best_i, tmp; + for ( i = 0; i < nVars-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nVars; j++ ) + if ( pArray[j] > pArray[best_i] ) + best_i = j; + tmp = pArray[i]; pArray[i] = pArray[best_i]; pArray[best_i] = tmp; + } +} + +/**Function************************************************************* + + Synopsis [Prints signatures for all variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManPrintSigs( Aig_VSig_t * pSigs, int nVars ) +{ + int v, i, k; + for ( v = 0; v < nVars; v++ ) + { + printf( "%2d : ", v ); + for ( k = 0; k < 2; k++ ) + { + printf( "%5d ", pSigs[2*v+k].nOnes ); + printf( "(" ); + for ( i = 0; i < nVars; i++ ) + printf( "%4d ", pSigs[2*v+k].nCofOnes[i] ); + printf( ") " ); + } + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Computes signatures for all variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManComputeVSigs( unsigned * pTruth, int nVars, Aig_VSig_t * pSigs, unsigned * pAux ) +{ + int v; + for ( v = 0; v < nVars; v++ ) + { + Kit_TruthCofactor0New( pAux, pTruth, nVars, v ); + pSigs[2*v+0].nOnes = Kit_TruthCountOnes( pAux, nVars ); + Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+0].nCofOnes ); + Aig_RManSortNums( pSigs[2*v+0].nCofOnes, nVars ); + + Kit_TruthCofactor1New( pAux, pTruth, nVars, v ); + pSigs[2*v+1].nOnes = Kit_TruthCountOnes( pAux, nVars ); + Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+1].nCofOnes ); + Aig_RManSortNums( pSigs[2*v+1].nCofOnes, nVars ); + } +} + +/**Function************************************************************* + + Synopsis [Computs signatures for all variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_RManCompareSigs( Aig_VSig_t * p0, Aig_VSig_t * p1, int nVars ) +{ +// return memcmp( p0, p1, sizeof(int) + sizeof(short) * nVars ); + return memcmp( p0, p1, sizeof(int) ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if all variables are unique.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_RManVarsAreUnique( Aig_VSig_t * pMints, int nVars ) +{ + int i; + for ( i = 0; i < nVars - 1; i++ ) + if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*(i+1)], nVars ) == 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if all variables are unique.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManPrintUniqueVars( Aig_VSig_t * pMints, int nVars ) +{ + int i; + for ( i = 0; i < nVars; i++ ) + if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*i+1], nVars ) == 0 ) + printf( "=" ); + else + printf( "x" ); + printf( "\n" ); + + printf( "0" ); + for ( i = 1; i < nVars; i++ ) + if ( Aig_RManCompareSigs( &pMints[2*(i-1)], &pMints[2*i], nVars ) == 0 ) + printf( "-" ); + else if ( i < 10 ) + printf( "%c", '0' + i ); + else + printf( "%c", 'A' + i-10 ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Canonicize the truth table.] + + Description [Returns the phase. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Aig_RManSemiCanonicize( unsigned * pOut, unsigned * pIn, int nVars, char * pCanonPerm, Aig_VSig_t * pSigs, int fReturnIn ) +{ + Aig_VSig_t TempSig; + int i, Temp, fChange, Counter; + unsigned * pTemp, uCanonPhase = 0; + // collect signatures + Aig_RManComputeVSigs( pIn, nVars, pSigs, pOut ); + // canonicize phase + for ( i = 0; i < nVars; i++ ) + { +// if ( pStore[2*i+0] <= pStore[2*i+1] ) + if ( Aig_RManCompareSigs( &pSigs[2*i+0], &pSigs[2*i+1], nVars ) <= 0 ) + continue; + uCanonPhase |= (1 << i); + TempSig = pSigs[2*i+0]; + pSigs[2*i+0] = pSigs[2*i+1]; + pSigs[2*i+1] = TempSig; + Kit_TruthChangePhase( pIn, nVars, i ); + } + // permute + Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { +// if ( pStore[2*i] <= pStore[2*(i+1)] ) + if ( Aig_RManCompareSigs( &pSigs[2*i], &pSigs[2*(i+1)], nVars ) <= 0 ) + continue; + Counter++; + fChange = 1; + + Temp = pCanonPerm[i]; + pCanonPerm[i] = pCanonPerm[i+1]; + pCanonPerm[i+1] = Temp; + + TempSig = pSigs[2*i]; + pSigs[2*i] = pSigs[2*(i+1)]; + pSigs[2*(i+1)] = TempSig; + + TempSig = pSigs[2*i+1]; + pSigs[2*i+1] = pSigs[2*(i+1)+1]; + pSigs[2*(i+1)+1] = TempSig; + + Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + + // swap if it was moved an even number of times + if ( fReturnIn ^ !(Counter & 1) ) + Kit_TruthCopy( pOut, pIn, nVars ); + return uCanonPhase; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) +{ return Aig_NotCond( Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } + +/**Function************************************************************* + + Synopsis [Records one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManSaveOne( Aig_RMan_t * p, unsigned * pTruth, int nVars ) +{ + int i, nNodes, RetValue; + Bdc_Fun_t * pFunc; + Aig_Obj_t * pTerm; + // perform decomposition + RetValue = Bdc_ManDecompose( p->pBidec, pTruth, NULL, nVars, NULL, 1000 ); + if ( RetValue < 0 ) + { + printf( "Decomposition failed.\n" ); + return; + } + // convert back into HOP + Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, 0 ), Aig_ManConst1(p->pAig) ); + for ( i = 0; i < nVars; i++ ) + Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, i+1 ), Aig_IthVar(p->pAig, i) ); + nNodes = Bdc_ManNodeNum(p->pBidec); + for ( i = nVars + 1; i < nNodes; i++ ) + { + pFunc = Bdc_ManFunc( p->pBidec, i ); + Bdc_FuncSetCopy( pFunc, Aig_And( p->pAig, + Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), + Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) ); + } + pTerm = Bdc_FunCopyHop( Bdc_ManRoot(p->pBidec) ); + pTerm = Aig_ObjCreatePo( p->pAig, pTerm ); +// assert( pTerm->fPhase == 0 ); +} + +/**Function************************************************************* + + Synopsis [Records one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManRecord( unsigned * pTruth, int nVarsInit ) +{ + int fVerify = 1; + Kit_DsdNtk_t * pNtk; + Kit_DsdObj_t * pObj; + unsigned uPhaseC; + int i, nVars, nWords; + int fUniqueVars; + + if ( nVarsInit > RMAN_MAXVARS ) + { + printf( "The number of variables in too large.\n" ); + return; + } + + if ( s_pRMan == NULL ) + s_pRMan = Aig_RManStart(); + s_pRMan->nTotal++; + // canonicize the function + pNtk = Kit_DsdDecompose( pTruth, nVarsInit ); + pObj = Kit_DsdNonDsdPrimeMax( pNtk ); + if ( pObj == NULL || pObj->nFans == 3 ) + { + s_pRMan->nTtDsd++; + Kit_DsdNtkFree( pNtk ); + return; + } + nVars = pObj->nFans; + s_pRMan->nVarFuncs[nVars]++; + if ( nVars < nVarsInit ) + s_pRMan->nTtDsdPart++; + else + s_pRMan->nTtDsdNot++; + // compute the number of words + nWords = Aig_TruthWordNum( nVars ); + // copy the function + memcpy( s_pRMan->pTruthInit, Kit_DsdObjTruth(pObj), 4*nWords ); + Kit_DsdNtkFree( pNtk ); + // canonicize the output + if ( s_pRMan->pTruthInit[0] & 1 ) + Kit_TruthNot( s_pRMan->pTruthInit, s_pRMan->pTruthInit, nVars ); + memcpy( s_pRMan->pTruth, s_pRMan->pTruthInit, 4*nWords ); + + // canonize the function + for ( i = 0; i < nVars; i++ ) + s_pRMan->pPerm[i] = i; + uPhaseC = Aig_RManSemiCanonicize( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPerm, s_pRMan->pMints, 1 ); + // check unique variables + fUniqueVars = Aig_RManVarsAreUnique( s_pRMan->pMints, nVars ); + s_pRMan->nUniqueVars += fUniqueVars; + +/* + printf( "%4d : ", s_pRMan->nTotal ); + printf( "%2d %2d ", nVarsInit, nVars ); + Extra_PrintBinary( stdout, &uPhaseC, nVars ); + printf( " " ); + for ( i = 0; i < nVars; i++ ) + printf( "%2d/%2d ", s_pRMan->pMints[2*i], s_pRMan->pMints[2*i+1] ); + printf( "\n" ); + Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars ); +Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<nTotal ); + printf( "%2d %2d ", nVarsInit, nVars ); + printf( " " ); + printf( "\n" ); + Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars ); +// Aig_RManPrintSigs( s_pRMan->pMints, nVars ); +*/ + +//Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<pTruth, nVars ) ) + Aig_RManSaveOne( s_pRMan, s_pRMan->pTruth, nVars ); + + if ( fVerify ) + { + // derive reverse permutation + for ( i = 0; i < nVars; i++ ) + s_pRMan->pPermR[i] = s_pRMan->pPerm[i]; + // implement permutation + Kit_TruthPermute( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPermR, 1 ); + // implement polarity + for ( i = 0; i < nVars; i++ ) + if ( uPhaseC & (1 << i) ) + Kit_TruthChangePhase( s_pRMan->pTruth, nVars, i ); + + // perform verification + if ( fUniqueVars && !Kit_TruthIsEqual( s_pRMan->pTruth, s_pRMan->pTruthInit, nVars ) ) + printf( "Verification failed.\n" ); + } +//Aig_RManPrintVarProfile( s_pRMan->pTruth, nVars, s_pRMan->pTruthTemp ); +//Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<fMarkA && !pObj->fMarkB ); // Aig_TableProfile( p ); Aig_MmFixedStop( p->pMemObjs, 0 ); - if ( p->vPis ) Vec_PtrFree( p->vPis ); - if ( p->vPos ) Vec_PtrFree( p->vPos ); - if ( p->vObjs ) Vec_PtrFree( p->vObjs ); - if ( p->vBufs ) Vec_PtrFree( p->vBufs ); - if ( p->vLevelR ) Vec_IntFree( p->vLevelR ); - if ( p->vLevels ) Vec_VecFree( p->vLevels ); - if ( p->vFlopNums) Vec_IntFree( p->vFlopNums ); - if ( p->vFlopReprs)Vec_IntFree( p->vFlopReprs ); - if ( p->pManExdc ) Aig_ManStop( p->pManExdc ); - if ( p->vOnehots ) Vec_VecFree( (Vec_Vec_t *)p->vOnehots ); - if ( p->vClockDoms)Vec_VecFree( p->vClockDoms ); + if ( p->vPis ) Vec_PtrFree( p->vPis ); + if ( p->vPos ) Vec_PtrFree( p->vPos ); + if ( p->vObjs ) Vec_PtrFree( p->vObjs ); + if ( p->vBufs ) Vec_PtrFree( p->vBufs ); + if ( p->vLevelR ) Vec_IntFree( p->vLevelR ); + if ( p->vLevels ) Vec_VecFree( p->vLevels ); + if ( p->vFlopNums) Vec_IntFree( p->vFlopNums ); + if ( p->vFlopReprs) Vec_IntFree( p->vFlopReprs ); + if ( p->pManExdc ) Aig_ManStop( p->pManExdc ); + if ( p->vOnehots ) Vec_VecFree( (Vec_Vec_t *)p->vOnehots ); + if ( p->vClockDoms) Vec_VecFree( p->vClockDoms ); + if ( p->vProbs ) Vec_IntFree( p->vProbs ); + FREE( p->pFastSim ); FREE( p->pData ); FREE( p->pSeqModel ); FREE( p->pName ); diff --git a/src/aig/aig/aigMffc.c b/src/aig/aig/aigMffc.c index 47ce896d..10887712 100644 --- a/src/aig/aig/aigMffc.c +++ b/src/aig/aig/aigMffc.c @@ -39,17 +39,22 @@ SeeAlso [] ***********************************************************************/ -int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin ) +int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs ) { + float Power0 = 0.0, Power1 = 0.0; Aig_Obj_t * pFanin; int Counter = 0; + if ( pProbs ) + *pPower = 0.0; if ( Aig_ObjIsPi(pNode) ) return 0; // consider the first fanin pFanin = Aig_ObjFanin0(pNode); assert( pFanin->nRefs > 0 ); if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) - Counter += Aig_NodeDeref_rec( pFanin, LevelMin ); + Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power0, pProbs ); + if ( pProbs ) + *pPower += Power0 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]); // skip the buffer if ( Aig_ObjIsBuf(pNode) ) return Counter; @@ -58,7 +63,9 @@ int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin ) pFanin = Aig_ObjFanin1(pNode); assert( pFanin->nRefs > 0 ); if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) - Counter += Aig_NodeDeref_rec( pFanin, LevelMin ); + Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power1, pProbs ); + if ( pProbs ) + *pPower += Power1 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]); return Counter + 1; } @@ -173,7 +180,7 @@ int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t assert( Aig_ObjIsNode(pNode) ); if ( vSupp ) Vec_PtrClear( vSupp ); Aig_ManIncrementTravId( p ); - ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin ); + ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin, NULL, NULL ); Aig_NodeMffsSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL ); ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin ); assert( ConeSize1 == ConeSize2 ); @@ -192,13 +199,14 @@ int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t SeeAlso [] ***********************************************************************/ -int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode ) +int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower ) { int ConeSize1, ConeSize2; + assert( (pPower != NULL) == (p->vProbs != NULL) ); assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); Aig_ManIncrementTravId( p ); - ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); + ConeSize1 = Aig_NodeDeref_rec( pNode, 0, pPower, p->vProbs? (float *)p->vProbs->pArray : NULL ); ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); @@ -225,7 +233,7 @@ int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( vLeaves, pObj, i ) pObj->nRefs++; - ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); + ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL ); ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); Vec_PtrForEachEntry( vLeaves, pObj, i ) pObj->nRefs--; @@ -256,7 +264,7 @@ int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves if ( LevelMax == 0 ) return 0; // dereference the cut - ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); + ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL ); // try expanding each node in the boundary ConeBest = AIG_INFINITY; pLeafBest = NULL; @@ -264,7 +272,7 @@ int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves { if ( (int)pObj->Level != LevelMax ) continue; - ConeCur1 = Aig_NodeDeref_rec( pObj, 0 ); + ConeCur1 = Aig_NodeDeref_rec( pObj, 0, NULL, NULL ); if ( ConeBest > ConeCur1 ) { ConeBest = ConeCur1; @@ -276,7 +284,7 @@ int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves assert( pLeafBest != NULL ); assert( Aig_ObjIsNode(pLeafBest) ); // deref the best leaf - ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0 ); + ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0, NULL, NULL ); // collect the cut nodes Vec_PtrClear( vResult ); Aig_ManIncrementTravId( p ); diff --git a/src/aig/aig/aigObj.c b/src/aig/aig/aigObj.c index 3ceed094..2c373ee1 100644 --- a/src/aig/aig/aigObj.c +++ b/src/aig/aig/aigObj.c @@ -116,6 +116,15 @@ Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ) assert( !Aig_IsComplement(pObj->pHaig) ); // printf( "Creating HAIG node %d equivalent to node %d.\n", pObj->pHaig->Id, pObj->Id ); } + // create the power counter + if ( p->vProbs ) + { + float Prob0 = Aig_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId0(pObj) ) ); + float Prob1 = Aig_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId1(pObj) ) ); + Prob0 = Aig_ObjFaninC0(pObj)? 1.0 - Prob0 : Prob0; + Prob1 = Aig_ObjFaninC1(pObj)? 1.0 - Prob1 : Prob1; + Vec_IntSetEntry( p->vProbs, pObj->Id, Aig_Float2Int(Prob0 * Prob1) ); + } return pObj; } diff --git a/src/aig/aig/aigScl.c b/src/aig/aig/aigScl.c index 153ac421..57b7b989 100644 --- a/src/aig/aig/aigScl.c +++ b/src/aig/aig/aigScl.c @@ -232,6 +232,7 @@ int Aig_ManSeqCleanup( Aig_Man_t * p ) Vec_PtrFree( vNodes ); p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p); p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p); + Aig_ManSetPioNumbers( p ); // remove dangling nodes return Aig_ManCleanup( p ); } @@ -577,6 +578,58 @@ void Aig_ManComputeSccs( Aig_Man_t * p ) Vec_VecFree( (Vec_Vec_t *)vSupports ); } +/**Function************************************************************* + + Synopsis [Performs partitioned register sweep.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManSclPart( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fVerbose ) +{ + Vec_Ptr_t * vResult; + Vec_Int_t * vPart; + int i, nCountPis, nCountRegs; + int * pMapBack; + Aig_Man_t * pTemp, * pNew; + int nClasses; + + if ( pAig->vClockDoms ) + { + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) + Vec_PtrPush( vResult, Vec_IntDup(vPart) ); + } + else + vResult = Aig_ManRegPartitionSimple( pAig, 0, 0 ); + + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + Vec_PtrForEachEntry( vResult, vPart, i ) + { + pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack ); + Aig_ManSetRegNum( pTemp, pTemp->nRegs ); + if (nCountPis>0) + { + pNew = Aig_ManScl( pTemp, fLatchConst, fLatchEqual, fVerbose ); + nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack ); + if ( fVerbose ) + printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d\n", + i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), 0, nClasses ); + Aig_ManStop( pNew ); + } + Aig_ManStop( pTemp ); + free( pMapBack ); + } + pNew = Aig_ManDupRepr( pAig, 0 ); + Aig_ManSeqCleanup( pNew ); + Vec_VecFree( (Vec_Vec_t*)vResult ); + return pNew; +} + /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] @@ -596,6 +649,10 @@ Aig_Man_t * Aig_ManScl( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int Aig_Man_t * pAigInit, * pAigNew; Aig_Obj_t * pFlop1, * pFlop2; int i, Entry1, Entry2, nTruePis;//, nRegs; + + if ( pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0 ) + return Aig_ManSclPart( pAig, fLatchConst, fLatchEqual, fVerbose); + // store the original AIG assert( pAig->vFlopNums == NULL ); pAigInit = pAig; diff --git a/src/aig/aig/aigTsim.c b/src/aig/aig/aigTsim.c index 7b48a73d..c411100b 100644 --- a/src/aig/aig/aigTsim.c +++ b/src/aig/aig/aigTsim.c @@ -44,10 +44,10 @@ static inline int Aig_XsimInv( int Value ) } static inline int Aig_XsimAnd( int Value0, int Value1 ) { - if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 ) - return AIG_XVS0; if ( Value0 == AIG_XVSX || Value1 == AIG_XVSX ) return AIG_XVSX; + if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 ) + return AIG_XVS0; assert( Value0 == AIG_XVS1 && Value1 == AIG_XVS1 ); return AIG_XVS1; } @@ -371,7 +371,7 @@ Vec_Ptr_t * Aig_ManTernarySimulate( Aig_Man_t * p, int fVerbose ) } // printf( "%d ", Aig_TsiStateCount(pTsi, pState) ); -// Aig_TsiStatePrint( pTsi, pState ); +//Aig_TsiStatePrint( pTsi, pState ); // check if this state exists if ( Aig_TsiStateLookup( pTsi, pState, pTsi->nWords ) ) break; diff --git a/src/aig/aig/module.make b/src/aig/aig/module.make index b1b8c5c2..5fea4341 100644 --- a/src/aig/aig/module.make +++ b/src/aig/aig/module.make @@ -1,4 +1,5 @@ SRC += src/aig/aig/aigCheck.c \ + src/aig/aig/aigCanon.c \ src/aig/aig/aigCuts.c \ src/aig/aig/aigDfs.c \ src/aig/aig/aigDup.c \ diff --git a/src/aig/bbr/bbrImage.c b/src/aig/bbr/bbrImage.c index f362162c..afc8dc39 100644 --- a/src/aig/bbr/bbrImage.c +++ b/src/aig/bbr/bbrImage.c @@ -19,7 +19,7 @@ ***********************************************************************/ #include "bbr.h" -#include "mtr.h" +#include "mtr.h" /* The ideas implemented in this file are inspired by the paper: @@ -721,7 +721,7 @@ int Bbr_BuildTreeNode( DdManager * dd, Bbr_ImageNode_t * pNode1, * pNode2; Bbr_ImageVar_t * pVar; Bbr_ImageNode_t * pNode; - DdNode * bCube, * bTemp, * bSuppTemp, * bParts; + DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts; int iNode1, iNode2; int iVarBest, nSupp, v; @@ -773,7 +773,7 @@ int Bbr_BuildTreeNode( DdManager * dd, Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); pNode1 = pNodes[iNode1]; pNode2 = pNodes[iNode2]; - +/* // it is not possible that a var appears only in these two // otherwise, it would have a different cost bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); @@ -781,7 +781,7 @@ int Bbr_BuildTreeNode( DdManager * dd, if ( pVars[v] && pVars[v]->bParts == bParts ) assert( 0 ); Cudd_RecursiveDeref( dd, bParts ); - +*/ // combines two nodes pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 ); } diff --git a/src/aig/bdc/bdcCore.c b/src/aig/bdc/bdcCore.c index e812da3d..9067d315 100644 --- a/src/aig/bdc/bdcCore.c +++ b/src/aig/bdc/bdcCore.c @@ -72,7 +72,8 @@ Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ) p->nNodesAlloc = 512; p->pNodes = ALLOC( Bdc_Fun_t, p->nNodesAlloc ); // memory - p->vMemory = Vec_IntStart( 4 * p->nWords * p->nNodesAlloc ); + p->vMemory = Vec_IntStart( 8 * p->nWords * p->nNodesAlloc ); + Vec_IntClear(p->vMemory); // set up hash table p->nTableSize = (1 << p->pPars->nVarsMax); p->pTable = ALLOC( Bdc_Fun_t *, p->nTableSize ); diff --git a/src/aig/bdc/bdcInt.h b/src/aig/bdc/bdcInt.h index ab800269..a35663ef 100644 --- a/src/aig/bdc/bdcInt.h +++ b/src/aig/bdc/bdcInt.h @@ -124,7 +124,7 @@ struct Bdc_Man_t_ static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes >= p->nNodesAlloc || p->nNodesNew >= p->nNodesMax ) return NULL; pRes = p->pNodes + p->nNodes++; p->nNodesNew++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); return pRes; } static inline Bdc_Fun_t * Bdc_FunWithId( Bdc_Man_t * p, int Id ) { assert( Id < p->nNodes ); return p->pNodes + Id; } static inline int Bdc_FunId( Bdc_Man_t * p, Bdc_Fun_t * pFun ) { return pFun - p->pNodes; } -static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); } +static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); assert( pF->puOff && pF->puOn ); } static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->uUniq = 0; } static inline void Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q ) { Bdc_Isf_t T = *p; *p = *q; *q = T; } static inline void Bdc_IsfNot( Bdc_Isf_t * p ) { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT; } diff --git a/src/aig/cec/cec.h b/src/aig/cec/cec.h new file mode 100644 index 00000000..fb0bb830 --- /dev/null +++ b/src/aig/cec/cec.h @@ -0,0 +1,100 @@ +/**CFile**************************************************************** + + FileName [cec.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CEC_H__ +#define __CEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// dynamic SAT parameters +typedef struct Cec_ParSat_t_ Cec_ParSat_t; +struct Cec_ParSat_t_ +{ + int nBTLimit; // conflict limit at a node + int nSatVarMax; // the max number of SAT variables + int nCallsRecycle; // calls to perform before recycling SAT solver + int fFirstStop; // stop on the first sat output + int fPolarFlip; // uses polarity adjustment + int fVerbose; // verbose stats +}; + +// combinational SAT sweeping parameters +typedef struct Cec_ParCsw_t_ Cec_ParCsw_t; +struct Cec_ParCsw_t_ +{ + int nWords; // the number of simulation words + int nRounds; // the number of simulation rounds + int nBTlimit; // conflict limit at a node + int fRewriting; // enables AIG rewriting + int fVerbose; // verbose stats +}; + +// combinational equivalence checking parameters +typedef struct Cec_ParCec_t_ Cec_ParCec_t; +struct Cec_ParCec_t_ +{ + int nIters; // iterations of SAT solving/sweeping + int nBTLimitBeg; // starting backtrack limit + int nBTlimitMulti; // multiple of backtrack limit + int fUseSmartCnf; // use smart CNF computation + int fRewriting; // enables AIG rewriting + int fSatSweeping; // enables SAT sweeping + int fFirstStop; // stop on the first sat output + int fVerbose; // verbose stats +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cecCore.c ==========================================================*/ +extern void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ); +extern void Cec_ManCswSetDefaultParams( Cec_ParCsw_t * p ); +extern void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ); +extern int Cec_Solve( Aig_Man_t * pAig0, Aig_Man_t * pAig1, Cec_ParCec_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/cec/cecAig.c b/src/aig/cec/cecAig.c new file mode 100644 index 00000000..2a6f5683 --- /dev/null +++ b/src/aig/cec/cecAig.c @@ -0,0 +1,151 @@ +/**CFile**************************************************************** + + FileName [cecAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [AIG manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives combinational miter of the two AIGs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Cec_DeriveMiter_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj ) +{ + if ( pObj->pData ) + return pObj->pData; + Cec_DeriveMiter_rec( pNew, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsBuf(pObj) ) + return pObj->pData = Aig_ObjChild0Copy(pObj); + Cec_DeriveMiter_rec( pNew, Aig_ObjFanin1(pObj) ); + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_Regular(pObj->pData)->pHaig = pObj->pHaig; + return pObj->pData; +} + +/**Function************************************************************* + + Synopsis [Derives combinational miter of the two AIGs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cec_DeriveMiter( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Bar_Progress_t * pProgress = NULL; + Aig_Man_t * pNew; + Aig_Obj_t * pObj0, * pObj1, * pObjNew; + int i; + assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) ); + assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) ); + // create the new manager + pNew = Aig_ManStart( Aig_ManNodeNum(p0) + Aig_ManNodeNum(p1) ); + pNew->pName = Aig_UtilStrsav( p0->pName ); + // create the PIs + Aig_ManCleanData( p0 ); + Aig_ManCleanData( p1 ); + Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew); + Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p0, pObj0, i ) + { + pObjNew = Aig_ObjCreatePi( pNew ); + pObj0->pData = pObjNew; + Aig_ManPi(p1, i)->pData = pObjNew; + } + // add logic for the POs + pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p0) ); + Aig_ManForEachPo( p0, pObj0, i ) + { + Bar_ProgressUpdate( pProgress, i, "Miter..." ); + pObj1 = Aig_ManPo( p1, i ); + Cec_DeriveMiter_rec( pNew, Aig_ObjFanin0(pObj0) ); + Cec_DeriveMiter_rec( pNew, Aig_ObjFanin0(pObj1) ); + pObjNew = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj0), Aig_ObjChild0Copy(pObj1) ); + Aig_ObjCreatePo( pNew, pObjNew ); + } + Bar_ProgressStop( pProgress ); + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, 0 ); + // check the resulting network +// if ( !Aig_ManCheck(pNew) ) +// printf( "Cec_DeriveMiter(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Cec_Duplicate( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManNodeNum(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); + // add logic for the POs + Aig_ManForEachPo( p, pObj, i ) + { + Cec_DeriveMiter_rec( pNew, Aig_ObjFanin0(pObj) ); + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, 0 ); + assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + // check the resulting network +// if ( !Aig_ManCheck(pNew) ) +// printf( "Cec_DeriveMiter(): The check has failed.\n" ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/cec/cecClass.c b/src/aig/cec/cecClass.c new file mode 100644 index 00000000..f3f6bf11 --- /dev/null +++ b/src/aig/cec/cecClass.c @@ -0,0 +1,569 @@ +/**CFile**************************************************************** + + FileName [cecClass.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [Equivalence class representation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecClass.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Caig_ManSpecReduce( Caig_Man_t * p ) +{ + Aig_Man_t * pAig; + Aig_Obj_t ** pCopy; + Aig_Obj_t * pMiter, * pRes0, * pRes1, * pRepr; + int i; + pCopy = ALLOC( Aig_Obj_t *, p->nObjs ); + pCopy[0] = NULL; + pAig = Aig_ManStart( p->nNodes ); + for ( i = 1; i < p->nObjs; i++ ) + { + if ( p->pFans0[i] == 0 ) // pi always has zero first fanin + { + pCopy[i] = Aig_ObjCreatePi( pAig ); + continue; + } + if ( p->pFans1[i] == 0 ) // po always has non-zero 1st fanin and zero 2nd fanin + continue; + pRes0 = pCopy[ Cec_Lit2Var(p->pFans0[i]) ]; + pRes0 = Aig_NotCond( pRes0, Cec_LitIsCompl(p->pFans0[i]) ); + pRes1 = pCopy[ Cec_Lit2Var(p->pFans1[i]) ]; + pRes1 = Aig_NotCond( pRes1, Cec_LitIsCompl(p->pFans1[i]) ); + pCopy[i] = Aig_And( pAig, pRes0, pRes1 ); + if ( p->pReprs[i] < 0 ) + continue; + assert( p->pReprs[i] < i ); + pRepr = p->pReprs[i]? pCopy[ p->pReprs[i] ] : Aig_ManConst1(pAig); + if ( Aig_Regular(pCopy[i]) == Aig_Regular(pRepr) ) + continue; + pMiter = Aig_Exor( pAig, pCopy[i], pRepr ); + Aig_ObjCreatePo( pAig, Aig_NotCond(pMiter, Aig_ObjPhaseReal(pMiter)) ); + } + free( pCopy ); + Aig_ManSetRegNum( pAig, 0 ); + Aig_ManCleanup( pAig ); + return pAig; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManCountOne( Caig_Man_t * p, int i ) +{ + int Ent, nLits = 0; + assert( p->pReprs[i] < 0 && p->pNexts[i] > 0 ); + for ( Ent = p->pNexts[i]; Ent; Ent = p->pNexts[Ent] ) + { + assert( p->pReprs[Ent] == i ); + nLits++; + } + return 1 + nLits; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManCountLiterals( Caig_Man_t * p ) +{ + int i, nLits = 0; + for ( i = 1; i < p->nObjs; i++ ) + if ( p->pReprs[i] < 0 && p->pNexts[i] > 0 ) + nLits += Caig_ManCountOne(p, i) - 1; + return nLits; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManPrintOne( Caig_Man_t * p, int i, int Counter ) +{ + int Ent; + printf( "Class %4d : Num = %2d {", Counter, Caig_ManCountOne(p, i) ); + for ( Ent = i; Ent; Ent = p->pNexts[Ent] ) + printf(" %d", Ent ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManPrintClasses( Caig_Man_t * p, int fVerbose ) +{ + int i, Counter = 0, Counter1 = 0, CounterX = 0, nLits; + for ( i = 1; i < p->nObjs; i++ ) + { + if ( p->pReprs[i] < 0 && p->pNexts[i] > 0 ) + Counter++; + if ( p->pReprs[i] == 0 ) + Counter1++; + if ( p->pReprs[i] < 0 && p->pNexts[i] == 0 ) + CounterX++; + } + nLits = Caig_ManCountLiterals( p ); + printf( "Class = %6d. Const1 = %6d. Other = %6d. Lits = %7d. Total = %7d.\n", + Counter, Counter1, CounterX, nLits, nLits+Counter1 ); + if ( fVerbose ) + for ( i = 1; i < p->nObjs; i++ ) + if ( p->pReprs[i] < 0 && p->pNexts[i] > 0 ) + Caig_ManPrintOne( p, i, ++Counter ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManCollectSimsSimple( Caig_Man_t * p, int i ) +{ + int Ent; + Vec_PtrClear( p->vSims ); + for ( Ent = i; Ent; Ent = p->pNexts[Ent] ) + Vec_PtrPush( p->vSims, p->pSims + Ent ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManCollectSimsNormal( Caig_Man_t * p, int i ) +{ + unsigned * pSim; + int Ent; + Vec_PtrClear( p->vSims ); + for ( Ent = i; Ent; Ent = p->pNexts[Ent] ) + { + pSim = Caig_ManSimDeref( p, Ent ); + Vec_PtrPush( p->vSims, pSim + 1 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManCompareEqual( unsigned * p0, unsigned * p1, int nWords ) +{ + int w; + if ( (p0[0] & 1) == (p1[0] & 1) ) + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != p1[w] ) + return 0; + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != ~p1[w] ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManCompareConst( unsigned * p, int nWords ) +{ + int w; + if ( p[0] & 1 ) + { + for ( w = 0; w < nWords; w++ ) + if ( p[w] != ~0 ) + return 0; + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p[w] != 0 ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManClassCreate( Caig_Man_t * p, Vec_Int_t * vClass ) +{ + int * pNext, Repr, Ent, i; + assert( Vec_IntSize(vClass) > 0 ); + Vec_IntForEachEntry( vClass, Ent, i ) + { + if ( i == 0 ) + { + Repr = Ent; + p->pReprs[Ent] = -1; + pNext = p->pNexts + Ent; + } + else + { + p->pReprs[Ent] = Repr; + *pNext = Ent; + pNext = p->pNexts + Ent; + } + } + *pNext = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManClassRefineOne( Caig_Man_t * p, int i, Vec_Ptr_t * vSims ) +{ + unsigned * pSim0, * pSim1; + int Ent, c = 0, d = 0; + Vec_IntClear( p->vClassOld ); + Vec_IntClear( p->vClassNew ); + pSim0 = Vec_PtrEntry( vSims, c++ ); + Vec_IntPush( p->vClassOld, i ); + for ( Ent = p->pNexts[i]; Ent; Ent = p->pNexts[Ent] ) + { + pSim1 = Vec_PtrEntry( vSims, c++ ); + if ( Caig_ManCompareEqual( pSim0, pSim1, p->nWords ) ) + Vec_IntPush( p->vClassOld, Ent ); + else + { + Vec_IntPush( p->vClassNew, Ent ); + Vec_PtrWriteEntry( vSims, d++, pSim1 ); + } + } + Vec_PtrShrink( vSims, d ); + if ( Vec_IntSize(p->vClassNew) == 0 ) + return 0; + Caig_ManClassCreate( p, p->vClassOld ); + Caig_ManClassCreate( p, p->vClassNew ); + if ( Vec_IntSize(p->vClassNew) > 1 ) + return 1 + Caig_ManClassRefineOne( p, Vec_IntEntry(p->vClassNew,0), vSims ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManHashKey( unsigned * pSim, int nWords, int nTableSize ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; + unsigned uHash = 0; + int i; + if ( pSim[0] & 1 ) + for ( i = 0; i < nWords; i++ ) + uHash ^= ~pSim[i] * s_Primes[i & 0xf]; + else + for ( i = 0; i < nWords; i++ ) + uHash ^= pSim[i] * s_Primes[i & 0xf]; + return (int)(uHash % nTableSize); + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManClassesCreate( Caig_Man_t * p ) +{ + int * pTable, nTableSize, i, Key; + nTableSize = Aig_PrimeCudd( 100 + p->nObjs / 10 ); + pTable = CALLOC( int, nTableSize ); + p->pReprs = ALLOC( int, p->nObjs ); + p->pNexts = CALLOC( int, p->nObjs ); + for ( i = 1; i < p->nObjs; i++ ) + { + if ( Caig_ManCompareConst( p->pSims + i, 1 ) ) + { + p->pReprs[i] = 0; + continue; + } + Key = Caig_ManHashKey( p->pSims + i, 1, nTableSize ); + if ( pTable[Key] == 0 ) + p->pReprs[i] = -1; + else + { + p->pNexts[ pTable[Key] ] = i; + p->pReprs[i] = p->pReprs[ pTable[Key] ]; + if ( p->pReprs[i] == -1 ) + p->pReprs[i] = pTable[Key]; + } + pTable[Key] = i; + } + FREE( pTable ); +Caig_ManPrintClasses( p, 0 ); + // refine classes + p->vSims = Vec_PtrAlloc( 100 ); + p->vClassOld = Vec_IntAlloc( 100 ); + p->vClassNew = Vec_IntAlloc( 100 ); + for ( i = 1; i < p->nObjs; i++ ) + if ( p->pReprs[i] < 0 && p->pNexts[i] > 0 ) + { + Caig_ManCollectSimsSimple( p, i ); + Caig_ManClassRefineOne( p, i, p->vSims ); + } + // clean memory + memset( p->pSims, 0, sizeof(unsigned) * p->nObjs ); +Caig_ManPrintClasses( p, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManSimulateSimple( Caig_Man_t * p ) +{ + unsigned Res0, Res1; + int i; + for ( i = 1; i < p->nObjs; i++ ) + { + if ( p->pFans0[i] == 0 ) // pi + { + p->pSims[i] = Aig_ManRandom( 0 ); + continue; + } + Res0 = p->pSims[Cec_Lit2Var(p->pFans0[i])]; + Res1 = p->pSims[Cec_Lit2Var(p->pFans1[i])]; + p->pSims[i] = (Cec_LitIsCompl(p->pFans0[i]) ? ~Res0: Res0) & + (Cec_LitIsCompl(p->pFans1[i]) ? ~Res1: Res1); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManProcessClass( Caig_Man_t * p, int i ) +{ + Caig_ManCollectSimsNormal( p, i ); + Caig_ManClassRefineOne( p, i, p->vSims ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManProcessRefined( Caig_Man_t * p, Vec_Int_t * vRefined ) +{ + Vec_Int_t * vClasses; + int * pTable, nTableSize, i, Key, iNode; + unsigned * pSim; + if ( Vec_IntSize(vRefined) == 0 ) + return; + nTableSize = Aig_PrimeCudd( 100 + Vec_IntSize(vRefined) / 5 ); + pTable = CALLOC( int, nTableSize ); + vClasses = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vRefined, iNode, i ) + { + pSim = Caig_ManSimRead( p, iNode ); + assert( !Caig_ManCompareConst( pSim + 1, p->nWords ) ); + Key = Caig_ManHashKey( pSim + 1, p->nWords, nTableSize ); + if ( pTable[Key] == 0 ) + { + assert( p->pReprs[iNode] == 0 ); + assert( p->pNexts[iNode] == 0 ); + p->pReprs[iNode] = -1; + Vec_IntPush( vClasses, iNode ); + } + else + { + p->pNexts[ pTable[Key] ] = iNode; + p->pReprs[iNode] = p->pReprs[ pTable[Key] ]; + if ( p->pReprs[iNode] == -1 ) + p->pReprs[iNode] = pTable[Key]; + assert( p->pReprs[iNode] > 0 ); + } + pTable[Key] = iNode; + } + FREE( pTable ); + // refine classes + Vec_IntForEachEntry( vClasses, iNode, i ) + { + if ( p->pNexts[iNode] == 0 ) + { + Caig_ManSimDeref( p, iNode ); + continue; + } + Caig_ManCollectSimsNormal( p, iNode ); + Caig_ManClassRefineOne( p, iNode, p->vSims ); + } + Vec_IntFree( vClasses ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Caig_Man_t * Caig_ManClassesPrepare( Aig_Man_t * pAig, int nWords, int nIters ) +{ + Caig_Man_t * p; + int i; + Aig_ManRandom( 1 ); + p = Caig_ManCreate( pAig ); + p->nWords = 1; + Caig_ManSimulateSimple( p ); + Caig_ManClassesCreate( p ); + p->nWords = nWords; + for ( i = 0; i < nIters; i++ ) + { + Caig_ManSimulateRound( p, 0 ); +Caig_ManPrintClasses( p, 0 ); + } + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/cec/cecCnf.c b/src/aig/cec/cecCnf.c new file mode 100644 index 00000000..8b8c011d --- /dev/null +++ b/src/aig/cec/cecCnf.c @@ -0,0 +1,328 @@ +/**CFile**************************************************************** + + FileName [cecCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [CNF computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_AddClausesMux( Cec_ManSat_t * p, Aig_Obj_t * pNode ) +{ + Aig_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Aig_IsComplement( pNode ) ); + assert( Aig_ObjIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = Cec_ObjSatNum(p,pNode); + VarI = Cec_ObjSatNum(p,pNodeI); + VarT = Cec_ObjSatNum(p,Aig_Regular(pNodeT)); + VarE = Cec_ObjSatNum(p,Aig_Regular(pNodeE)); + // get the complementation flags + fCompT = Aig_IsComplement(pNodeT); + fCompE = Aig_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 1^fCompT); + pLits[2] = toLitCond(VarF, 0); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 0^fCompT); + pLits[2] = toLitCond(VarF, 1); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + if ( p->pPars->fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = toLitCond(VarT, 0^fCompT); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarT, 1^fCompT); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_AddClausesSuper( Cec_ManSat_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper ) +{ + Aig_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsNode( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + pLits[0] = toLitCond(Cec_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); + pLits[1] = toLitCond(Cec_ObjSatNum(p,pNode), 1); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); + if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + pLits[i] = toLitCond(Cec_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); + if ( p->pPars->fPolarFlip ) + { + if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); + } + } + pLits[nLits-1] = toLitCond(Cec_ObjSatNum(p,pNode), 0); + if ( p->pPars->fPolarFlip ) + { + if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); + assert( RetValue ); + free( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || + (!fFirst && Aig_ObjRefs(pObj) > 1) || + (fUseMuxes && Aig_ObjIsMuxType(pObj)) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + // go through the branches + Cec_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Cec_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsPi(pObj) ); + Vec_PtrClear( vSuper ); + Cec_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ObjAddToFrontier( Cec_ManSat_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Cec_ObjSatNum(p,pObj) ) + return; + assert( Cec_ObjSatNum(p,pObj) == 0 ); + if ( Aig_ObjIsConst1(pObj) ) + return; + Vec_PtrPush( p->vUsedNodes, pObj ); + Cec_ObjSetSatNum( p, pObj, p->nSatVars++ ); + if ( Aig_ObjIsNode(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vFrontier; + Aig_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + // quit if CNF is ready + if ( Cec_ObjSatNum(p,pObj) ) + return; + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + Cec_ObjAddToFrontier( p, pObj, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( vFrontier, pNode, i ) + { + // create the supergate + assert( Cec_ObjSatNum(p,pNode) ); + if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) + { + Vec_PtrClear( p->vFanins ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( p->vFanins, pFanin, k ) + Cec_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Cec_AddClausesMux( p, pNode ); + } + else + { + Cec_CollectSuper( pNode, fUseMuxes, p->vFanins ); + Vec_PtrForEachEntry( p->vFanins, pFanin, k ) + Cec_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Cec_AddClausesSuper( p, pNode, p->vFanins ); + } + assert( Vec_PtrSize(p->vFanins) > 1 ); + } + Vec_PtrFree( vFrontier ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/cec/cecCore.c b/src/aig/cec/cecCore.c new file mode 100644 index 00000000..86287a96 --- /dev/null +++ b/src/aig/cec/cecCore.c @@ -0,0 +1,233 @@ +/**CFile**************************************************************** + + FileName [cecCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ) +{ + memset( p, 0, sizeof(Cec_ParSat_t) ); + p->nBTLimit = 100; // conflict limit at a node + p->nSatVarMax = 2000; // the max number of SAT variables + p->nCallsRecycle = 10; // calls to perform before recycling SAT solver + p->fFirstStop = 0; // stop on the first sat output + p->fPolarFlip = 0; // uses polarity adjustment + p->fVerbose = 0; // verbose stats +} + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManCswSetDefaultParams( Cec_ParCsw_t * p ) +{ + memset( p, 0, sizeof(Cec_ParCsw_t) ); + p->nWords = 15; // the number of simulation words + p->nRounds = 10; // the number of simulation rounds + p->nBTlimit = 10; // conflict limit at a node + p->fRewriting = 0; // enables AIG rewriting + p->fVerbose = 1; // verbose stats +} + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ) +{ + memset( p, 0, sizeof(Cec_ParCec_t) ); + p->nIters = 5; // iterations of SAT solving/sweeping + p->nBTLimitBeg = 2; // starting backtrack limit + p->nBTlimitMulti = 8; // multiple of backtrack limiter + p->fUseSmartCnf = 0; // use smart CNF computation + p->fRewriting = 0; // enables AIG rewriting + p->fSatSweeping = 0; // enables SAT sweeping + p->fFirstStop = 0; // stop on the first sat output + p->fVerbose = 1; // verbose stats +} + + +/**Function************************************************************* + + Synopsis [Performs equivalence checking.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_Sweep( Aig_Man_t * pAig, int nBTLimit ) +{ + Cec_MtrStatus_t Status; + Cec_ParCsw_t ParsCsw, * pParsCsw = &ParsCsw; + Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; + Caig_Man_t * pCaig; + Aig_Man_t * pSRAig; + int clk; + + Cec_ManCswSetDefaultParams( pParsCsw ); + pParsCsw->nBTlimit = nBTLimit; + pCaig = Caig_ManClassesPrepare( pAig, pParsCsw->nWords, pParsCsw->nRounds ); + + pSRAig = Caig_ManSpecReduce( pCaig ); + Aig_ManPrintStats( pSRAig ); + + Cec_ManSatSetDefaultParams( pParsSat ); + pParsSat->fFirstStop = 0; + pParsSat->nBTLimit = pParsCsw->nBTlimit; +clk = clock(); + Status = Cec_SatSolveOutputs( pSRAig, pParsSat ); + Cec_MiterStatusPrint( Status, "SRM ", clock() - clk ); + + Aig_ManStop( pSRAig ); + + Caig_ManDelete( pCaig ); + + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs equivalence checking.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_Solve( Aig_Man_t * pAig0, Aig_Man_t * pAig1, Cec_ParCec_t * pPars ) +{ + Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; + Cec_MtrStatus_t Status; + Aig_Man_t * pMiter; + int i, clk = clock(); + if ( pPars->fVerbose ) + { + Status = Cec_MiterStatusTrivial( pAig0 ); + Status.nNodes += pAig1? Aig_ManNodeNum( pAig1 ) : 0; + Cec_MiterStatusPrint( Status, "Init ", 0 ); + } + // create combinational miter + if ( pAig1 == NULL ) + { + Status = Cec_MiterStatus( pAig0 ); + if ( Status.nSat > 0 && pPars->fFirstStop ) + { + if ( pPars->fVerbose ) + printf( "Output %d is trivially SAT.\n", Status.iOut ); + return 0; + } + if ( Status.nUndec == 0 ) + { + if ( pPars->fVerbose ) + printf( "The miter has no undecided outputs.\n" ); + return 1; + } + pMiter = Cec_Duplicate( pAig0 ); + } + else + { + pMiter = Cec_DeriveMiter( pAig0, pAig1 ); + Status = Cec_MiterStatus( pMiter ); + if ( Status.nSat > 0 && pPars->fFirstStop ) + { + if ( pPars->fVerbose ) + printf( "Output %d is trivially SAT.\n", Status.iOut ); + Aig_ManStop( pMiter ); + return 0; + } + if ( Status.nUndec == 0 ) + { + if ( pPars->fVerbose ) + printf( "The problem is solved by structrual hashing.\n" ); + Aig_ManStop( pMiter ); + return 1; + } + } + if ( pPars->fVerbose ) + Cec_MiterStatusPrint( Status, "Strash", clock() - clk ); + // start parameter structures + Cec_ManSatSetDefaultParams( pParsSat ); + pParsSat->fFirstStop = pPars->fFirstStop; + pParsSat->nBTLimit = pPars->nBTLimitBeg; + for ( i = 0; i < pPars->nIters; i++ ) + { + // try SAT solving + clk = clock(); + pParsSat->nBTLimit *= pPars->nBTlimitMulti; + Status = Cec_SatSolveOutputs( pMiter, pParsSat ); + if ( pPars->fVerbose ) + Cec_MiterStatusPrint( Status, "SAT ", clock() - clk ); + if ( Status.nSat && pParsSat->fFirstStop ) + break; + if ( Status.nUndec == 0 ) + break; + + // try rewriting + + // try SAT sweeping + Cec_Sweep( pMiter, 10 ); + i = i; + } + Aig_ManStop( pMiter ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/cec/cecInt.h b/src/aig/cec/cecInt.h new file mode 100644 index 00000000..93221f83 --- /dev/null +++ b/src/aig/cec/cecInt.h @@ -0,0 +1,220 @@ +/**CFile**************************************************************** + + FileName [cecInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CEC_INT_H__ +#define __CEC_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig.h" +#include "satSolver.h" +#include "bar.h" +#include "cec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cec_ManSat_t_ Cec_ManSat_t; +struct Cec_ManSat_t_ +{ + // parameters + Cec_ParSat_t * pPars; + // AIGs used in the package + Aig_Man_t * pAig; // the AIG whose outputs are considered + Vec_Int_t * vStatus; // status for each output + // SAT solving + sat_solver * pSat; // recyclable SAT solver + int nSatVars; // the counter of SAT variables + int * pSatVars; // mapping of each node into its SAT var + Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned + int nRecycles; // the number of times SAT solver was recycled + int nCallsSince; // the number of calls since the last recycle + Vec_Ptr_t * vFanins; // fanins of the CNF node + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + // runtime stats + int timeSatUnsat; // unsat + int timeSatSat; // sat + int timeSatUndec; // undecided + int timeTotal; // total runtime +}; + +typedef struct Cec_ManCla_t_ Cec_ManCla_t; + +typedef struct Cec_ManCsw_t_ Cec_ManCsw_t; +struct Cec_ManCsw_t_ +{ + // parameters + Cec_ParCsw_t * pPars; + // AIGs used in the package + Aig_Man_t * pAig; // the AIG for SAT sweeping + Aig_Man_t * pFraig; // the AIG after SAT sweeping + // equivalence classes + Cec_ManCla_t * ppClasses; // equivalence classes of nodes + // choice node statistics + int nLits; // the number of lits in the cand equiv classes + int nReprs; // the number of proved equivalent pairs + int nEquivs; // the number of final equivalences + int nChoices; // the number of final choice nodes +}; + +typedef struct Cec_ManCec_t_ Cec_ManCec_t; +struct Cec_ManCec_t_ +{ + // parameters + Cec_ParCec_t * pPars; + // AIGs used in the package + Aig_Man_t * pAig; // the miter for equivalence checking + // mapping of PI/PO nodes + + // counter-example + int * pCex; // counter-example + int iOutput; // the output for this counter-example + + // statistics + +}; + +typedef struct Cec_MtrStatus_t_ Cec_MtrStatus_t; +struct Cec_MtrStatus_t_ +{ + int nInputs; // the total number of inputs + int nNodes; // the total number of nodes + int nOutputs; // the total number of outputs + int nUnsat; // the number of UNSAT outputs + int nSat; // the number of SAT outputs + int nUndec; // the number of undecided outputs + int iOut; // the satisfied output +}; + +// combinational simulation manager +typedef struct Caig_Man_t_ Caig_Man_t; +struct Caig_Man_t_ +{ + // parameters + Aig_Man_t * pAig; // the AIG to be used for simulation + int nWords; // the number of words to simulate + // AIG representation + int nPis; // the number of primary inputs + int nPos; // the number of primary outputs + int nNodes; // the number of internal nodes + int nObjs; // nPis + nNodes + nPos + 1 + int * pFans0; // fanin0 for all objects + int * pFans1; // fanin1 for all objects + // simulation info + unsigned short* pRefs; // reference counter for each node + unsigned * pSims; // simlulation information for each node + // recycable memory + unsigned * pMems; // allocated simulaton memory + int nWordsAlloc; // the number of allocated entries + int nMems; // the number of used entries + int nMemsMax; // the max number of used entries + int MemFree; // next free entry + // equivalence class representation + int * pReprs; // representatives of each node + int * pNexts; // nexts for each node + // temporaries + Vec_Ptr_t * vSims; // pointers to sim info + Vec_Int_t * vClassOld; // old class numbers + Vec_Int_t * vClassNew; // new class numbers +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Cec_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Cec_Lit2Var( int Lit ) { return Lit >> 1; } +static inline int Cec_LitIsCompl( int Lit ) { return Lit & 1; } +static inline int Cec_LitNot( int Lit ) { return Lit ^ 1; } +static inline int Cec_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Cec_LitRegular( int Lit ) { return Lit & ~01; } + +static inline int Cec_ObjSatNum( Cec_ManSat_t * p, Aig_Obj_t * pObj ) { return p->pSatVars[pObj->Id]; } +static inline void Cec_ObjSetSatNum( Cec_ManSat_t * p, Aig_Obj_t * pObj, int Num ) { p->pSatVars[pObj->Id] = Num; } + +static inline Aig_Obj_t * Cec_ObjFraig( Aig_Obj_t * pObj ) { return pObj->pData; } +static inline void Cec_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { pObj->pData = pNode; } + +static inline int Cec_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) +{ + return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig); +} +static inline void Cec_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) +{ + assert( !Cec_ObjIsConst1Cand( pAig, pObj ) ); + Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) ); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cecAig.c ==========================================================*/ +extern Aig_Man_t * Cec_Duplicate( Aig_Man_t * p ); +extern Aig_Man_t * Cec_DeriveMiter( Aig_Man_t * p0, Aig_Man_t * p1 ); +/*=== cecClass.c ==========================================================*/ +extern Aig_Man_t * Caig_ManSpecReduce( Caig_Man_t * p ); +extern int Caig_ManCompareEqual( unsigned * p0, unsigned * p1, int nWords ); +extern int Caig_ManCompareConst( unsigned * p, int nWords ); +extern void Caig_ManProcessClass( Caig_Man_t * p, int i ); +extern void Caig_ManProcessRefined( Caig_Man_t * p, Vec_Int_t * vRefined ); +extern Caig_Man_t * Caig_ManClassesPrepare( Aig_Man_t * pAig, int nWords, int nIters ); +/*=== cecCnf.c ==========================================================*/ +extern void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Aig_Obj_t * pObj ); +/*=== cecSat.c ==========================================================*/ +extern Cec_MtrStatus_t Cec_SatSolveOutputs( Aig_Man_t * pAig, Cec_ParSat_t * pPars ); +/*=== cecSim.c ==========================================================*/ +extern Caig_Man_t * Caig_ManCreate( Aig_Man_t * pAig ); +extern void Caig_ManDelete( Caig_Man_t * p ); +extern unsigned * Caig_ManSimRead( Caig_Man_t * p, int i ); +extern unsigned * Caig_ManSimRef( Caig_Man_t * p, int i ); +extern unsigned * Caig_ManSimDeref( Caig_Man_t * p, int i ); +extern int Caig_ManSimulateRound( Caig_Man_t * p, int fMiter ); +extern int Cec_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose ); +/*=== cecStatus.c ==========================================================*/ +extern int Cec_OutputStatus( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern Cec_MtrStatus_t Cec_MiterStatus( Aig_Man_t * p ); +extern Cec_MtrStatus_t Cec_MiterStatusTrivial( Aig_Man_t * p ); +extern void Cec_MiterStatusPrint( Cec_MtrStatus_t S, char * pString, int Time ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/cec/cecMan.c b/src/aig/cec/cecMan.c new file mode 100644 index 00000000..86415c53 --- /dev/null +++ b/src/aig/cec/cecMan.c @@ -0,0 +1,59 @@ +/**CFile**************************************************************** + + FileName [cecMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [Manager pcocures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/cec/cecSat.c b/src/aig/cec/cecSat.c index 37f63f05..9cf13ebc 100644 --- a/src/aig/cec/cecSat.c +++ b/src/aig/cec/cecSat.c @@ -4,23 +4,21 @@ SystemName [ABC: Logic synthesis and verification system.] - PackageName [Combinational equivalence checking.] + PackageName [Combinatinoal equivalence checking.] - Synopsis [Backend calling the SAT solver.] + Synopsis [SAT solver calls.] Author [Alan Mishchenko] Affiliation [UC Berkeley] - Date [Ver. 1.0. Started - June 30, 2007.] + Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: cecSat.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + Revision [$Id: cecSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ -#include "aig.h" -#include "cnf.h" -#include "solver.h" +#include "cecInt.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -32,7 +30,7 @@ /**Function************************************************************* - Synopsis [Writes CNF into a file.] + Synopsis [Creates the manager.] Description [] @@ -41,33 +39,25 @@ SeeAlso [] ***********************************************************************/ -solver * Cnf_WriteIntoSolverNew( Cnf_Dat_t * p ) +Cec_ManSat_t * Cec_ManCreate( Aig_Man_t * pAig, Cec_ParSat_t * pPars ) { - solver * pSat; - int i, status; - pSat = solver_new(); - for ( i = 0; i < p->nVars; i++ ) - solver_newVar( pSat ); - for ( i = 0; i < p->nClauses; i++ ) - { - if ( !solver_addClause( pSat, p->pClauses[i+1]-p->pClauses[i], p->pClauses[i] ) ) - { - solver_delete( pSat ); - return NULL; - } - } - status = solver_simplify(pSat); - if ( status == 0 ) - { - solver_delete( pSat ); - return NULL; - } - return pSat; + Cec_ManSat_t * p; + // create interpolation manager + p = ALLOC( Cec_ManSat_t, 1 ); + memset( p, 0, sizeof(Cec_ManSat_t) ); + p->pPars = pPars; + p->pAig = pAig; + // SAT solving + p->nSatVars = 1; + p->pSatVars = CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->vUsedNodes = Vec_PtrAlloc( 1000 ); + p->vFanins = Vec_PtrAlloc( 100 ); + return p; } /**Function************************************************************* - Synopsis [Adds the OR-clause.] + Synopsis [Frees the manager.] Description [] @@ -76,25 +66,19 @@ solver * Cnf_WriteIntoSolverNew( Cnf_Dat_t * p ) SeeAlso [] ***********************************************************************/ -int Cnf_DataWriteAndClausesNew( void * p, Cnf_Dat_t * pCnf ) +void Cec_ManStop( Cec_ManSat_t * p ) { -/* - sat_solver * pSat = p; - Aig_Obj_t * pObj; - int i, Lit; - Aig_ManForEachPo( pCnf->pMan, pObj, i ) - { - Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); - if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) ) - return 0; - } -*/ - return 1; + if ( p->pSat ) + sat_solver_delete( p->pSat ); + Vec_PtrFree( p->vUsedNodes ); + Vec_PtrFree( p->vFanins ); + FREE( p->pSatVars ); + free( p ); } /**Function************************************************************* - Synopsis [Adds the OR-clause.] + Synopsis [Recycles the SAT solver.] Description [] @@ -103,25 +87,38 @@ int Cnf_DataWriteAndClausesNew( void * p, Cnf_Dat_t * pCnf ) SeeAlso [] ***********************************************************************/ -int Cnf_DataWriteOrClauseNew( solver * pSat, Cnf_Dat_t * pCnf ) +void Cec_ManSatSolverRecycle( Cec_ManSat_t * p ) { - Aig_Obj_t * pObj; - int i, * pLits; - pLits = ALLOC( int, Aig_ManPoNum(pCnf->pMan) ); - Aig_ManForEachPo( pCnf->pMan, pObj, i ) - pLits[i] = solver_mkLit_args( pCnf->pVarNums[pObj->Id], 0 ); - if ( !solver_addClause( pSat, Aig_ManPoNum(pCnf->pMan), pLits ) ) + int Lit; + if ( p->pSat ) { - free( pLits ); - return 0; + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( p->vUsedNodes, pObj, i ) + Cec_ObjSetSatNum( p, pObj, 0 ); + Vec_PtrClear( p->vUsedNodes ); +// memset( p->pSatVars, 0, sizeof(int) * Aig_ManObjNumMax(p->pAigTotal) ); + sat_solver_delete( p->pSat ); } - free( pLits ); - return 1; + p->pSat = sat_solver_new(); + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is not used + // var 1 is reserved for const1 node - add the clause + p->nSatVars = 1; +// p->nSatVars = 0; + Lit = toLit( p->nSatVars ); + if ( p->pPars->fPolarFlip ) + Lit = lit_neg( Lit ); + sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); + Cec_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ ); + + p->nRecycles++; + p->nCallsSince = 0; } /**Function************************************************************* - Synopsis [Writes the given clause in a file in DIMACS format.] + Synopsis [Runs equivalence test for the two nodes.] Description [] @@ -130,36 +127,66 @@ int Cnf_DataWriteOrClauseNew( solver * pSat, Cnf_Dat_t * pCnf ) SeeAlso [] ***********************************************************************/ -void Sat_SolverPrintStatsNew( FILE * pFile, solver * pSat ) +int Cec_ManSatCheckNode( Cec_ManSat_t * p, Aig_Obj_t * pNode ) { -// printf( "starts : %8d\n", solver_num_assigns(pSat) ); - printf( "vars : %8d\n", solver_num_vars(pSat) ); - printf( "clauses : %8d\n", solver_num_clauses(pSat) ); - printf( "conflicts : %8d\n", solver_num_learnts(pSat) ); -} - -/**Function************************************************************* - - Synopsis [Returns a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] + int nBTLimit = p->pPars->nBTLimit; + int Lit, RetValue, status, clk; + + // sanity checks + assert( !Aig_IsComplement(pNode) ); + + p->nCallsSince++; // experiment with this!!! + + // check if SAT solver needs recycling + if ( p->pSat == NULL || + (p->pPars->nSatVarMax && + p->nSatVars > p->pPars->nSatVarMax && + p->nCallsSince > p->pPars->nCallsRecycle) ) + Cec_ManSatSolverRecycle( p ); + + // if the nodes do not have SAT variables, allocate them + Cec_CnfNodeAddToSolver( p, pNode ); + + // propage unit clauses + if ( p->pSat->qtail != p->pSat->qhead ) + { + status = sat_solver_simplify(p->pSat); + assert( status != 0 ); + assert( p->pSat->qtail == p->pSat->qhead ); + } -***********************************************************************/ -int * Sat_SolverGetModelNew( solver * pSat, int * pVars, int nVars ) -{ - int * pModel; - int i; - pModel = ALLOC( int, nVars+1 ); - for ( i = 0; i < nVars; i++ ) + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Lit = toLitCond( Cec_ObjSatNum(p,pNode), pNode->fPhase ); + if ( p->pPars->fPolarFlip ) + { + if ( pNode->fPhase ) Lit = lit_neg( Lit ); + } +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); +clk = clock(); + RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, + (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); + if ( RetValue == l_False ) + { +p->timeSatUnsat += clock() - clk; + Lit = lit_neg( Lit ); + RetValue = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); + assert( RetValue ); + p->timeSatUnsat++; + return 1; + } + else if ( RetValue == l_True ) { - assert( pVars[i] >= 0 && pVars[i] < solver_num_vars(pSat) ); - pModel[i] = (int)(solver_modelValue_Var( pSat, pVars[i] ) == solver_l_True); +p->timeSatSat += clock() - clk; + p->timeSatSat++; + return 0; + } + else // if ( RetValue == l_Undef ) + { +p->timeSatUndec += clock() - clk; + p->timeSatUndec++; + return -1; } - return pModel; } /**Function************************************************************* @@ -173,112 +200,51 @@ int * Sat_SolverGetModelNew( solver * pSat, int * pVars, int nVars ) SeeAlso [] ***********************************************************************/ -int Cec_RunSat( Aig_Man_t * pMan, sint64 nConfLimit, sint64 nInsLimit, int fFlipBits, int fAndOuts, int fVerbose ) +Cec_MtrStatus_t Cec_SatSolveOutputs( Aig_Man_t * pAig, Cec_ParSat_t * pPars ) { - solver * pSat; - Cnf_Dat_t * pCnf; - int status, RetValue, clk = clock(); - Vec_Int_t * vCiIds; - - assert( Aig_ManRegNum(pMan) == 0 ); - pMan->pData = NULL; - - // derive CNF - pCnf = Cnf_Derive( pMan, Aig_ManPoNum(pMan) ); -// pCnf = Cnf_DeriveSimple( pMan, Aig_ManPoNum(pMan) ); - - // convert into SAT solver - pSat = Cnf_WriteIntoSolverNew( pCnf ); - if ( pSat == NULL ) - { - Cnf_DataFree( pCnf ); - return 1; - } - - - if ( fAndOuts ) + Bar_Progress_t * pProgress = NULL; + Cec_MtrStatus_t Status; + Cec_ManSat_t * p; + Aig_Obj_t * pObj; + int i, status; + Status = Cec_MiterStatus( pAig ); + p = Cec_ManCreate( pAig, pPars ); + pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(pAig) ); + Aig_ManForEachPo( pAig, pObj, i ) { - assert( 0 ); - // assert each output independently - if ( !Cnf_DataWriteAndClausesNew( pSat, pCnf ) ) + Bar_ProgressUpdate( pProgress, i, "SAT..." ); + if ( Cec_OutputStatus(pAig, pObj) ) + continue; + status = Cec_ManSatCheckNode( p, Aig_ObjFanin0(pObj) ); + if ( status == 1 ) { - solver_delete( pSat ); - Cnf_DataFree( pCnf ); - return 1; + Status.nUndec--, Status.nUnsat++; + Aig_ObjPatchFanin0( pAig, pObj, Aig_ManConst0(pAig) ); } - } - else - { - // add the OR clause for the outputs - if ( !Cnf_DataWriteOrClauseNew( pSat, pCnf ) ) + if ( status == 0 ) { - solver_delete( pSat ); - Cnf_DataFree( pCnf ); - return 1; + Status.nUndec--, Status.nSat++; + Aig_ObjPatchFanin0( pAig, pObj, Aig_ManConst1(pAig) ); } + if ( status == -1 ) + continue; + // save the pattern (if it is first) + if ( Status.iOut == -1 ) + { + } + // quit if at least one of them is solved + if ( status == 0 && pPars->fFirstStop ) + break; } - vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); - Cnf_DataFree( pCnf ); - - -// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); -// PRT( "Time", clock() - clk ); - - // simplify the problem - clk = clock(); - status = solver_simplify(pSat); -// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); -// PRT( "Time", clock() - clk ); - if ( status == 0 ) - { - Vec_IntFree( vCiIds ); - solver_delete( pSat ); -// printf( "The problem is UNSATISFIABLE after simplification.\n" ); - return 1; - } - - // solve the miter - clk = clock(); - if ( fVerbose ) - solver_set_verbosity( pSat, 1 ); - status = solver_solve( pSat, 0, NULL ); - if ( status == solver_l_Undef ) - { -// printf( "The problem timed out.\n" ); - RetValue = -1; - } - else if ( status == solver_l_True ) - { -// printf( "The problem is SATISFIABLE.\n" ); - RetValue = 0; - } - else if ( status == solver_l_False ) - { -// printf( "The problem is UNSATISFIABLE.\n" ); - RetValue = 1; - } - else - assert( 0 ); -// PRT( "SAT sat_solver time", clock() - clk ); -// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); - - // if the problem is SAT, get the counterexample - if ( status == solver_l_True ) - { - pMan->pData = Sat_SolverGetModelNew( pSat, vCiIds->pArray, vCiIds->nSize ); - } - // free the sat_solver - if ( fVerbose ) - Sat_SolverPrintStatsNew( stdout, pSat ); -//sat_solver_store_write( pSat, "trace.cnf" ); -//sat_solver_store_free( pSat ); - solver_delete( pSat ); - Vec_IntFree( vCiIds ); - return RetValue; + Aig_ManCleanup( pAig ); + Bar_ProgressStop( pProgress ); + printf( " Confs = %8d. Recycles = %6d.\n", p->pPars->nBTLimit, p->nRecycles ); + Cec_ManStop( p ); + return Status; } - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/cec/cecSim.c b/src/aig/cec/cecSim.c new file mode 100644 index 00000000..8a5f3cd5 --- /dev/null +++ b/src/aig/cec/cecSim.c @@ -0,0 +1,459 @@ +/**CFile**************************************************************** + + FileName [cecSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [AIG simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Count PIs with fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManCountRelevantPis( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachPi( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) ) + Counter++; + else + pObj->iData = -1; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Count PIs with fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManCountRelevantPos( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachPo( pAig, pObj, i ) + if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + Counter++; + else + pObj->iData = -1; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Find the PO corresponding to the PO driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManFindPo( Aig_Man_t * pAig, int iNode ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachPo( pAig, pObj, i ) + if ( pObj->iData == iNode ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManCreate_rec( Caig_Man_t * p, Aig_Obj_t * pObj ) +{ + int iFan0, iFan1; + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsConst1(pObj) ); + if ( pObj->iData ) + return pObj->iData; + if ( Aig_ObjIsNode(pObj) ) + { + iFan0 = Caig_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj); + iFan1 = Caig_ManCreate_rec( p, Aig_ObjFanin1(pObj) ); + iFan1 = (iFan1 << 1) | Aig_ObjFaninC1(pObj); + } + else if ( Aig_ObjIsPo(pObj) ) + { + iFan0 = Caig_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj); + iFan1 = 0; + } + else + iFan0 = iFan1 = 0; + assert( Aig_ObjRefs(pObj) < (1<<16) ); + p->pFans0[p->nObjs] = iFan0; + p->pFans1[p->nObjs] = iFan1; + p->pRefs[p->nObjs] = (unsigned short)Aig_ObjRefs(pObj); + return pObj->iData = p->nObjs++; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Caig_Man_t * Caig_ManCreate( Aig_Man_t * pAig ) +{ + Caig_Man_t * p; + Aig_Obj_t * pObj; + int i, nObjs; + Aig_ManCleanData( pAig ); + p = (Caig_Man_t *)ALLOC( Caig_Man_t, 1 ); + memset( p, 0, sizeof(Caig_Man_t) ); + p->pAig = pAig; + p->nPis = Caig_ManCountRelevantPis(pAig); + p->nPos = Caig_ManCountRelevantPos(pAig); + p->nNodes = Aig_ManNodeNum(pAig); + nObjs = p->nPis + p->nPos + p->nNodes + 1; + p->pFans0 = ALLOC( int, nObjs ); + p->pFans1 = ALLOC( int, nObjs ); + p->pRefs = ALLOC( unsigned short, nObjs ); + p->pSims = CALLOC( unsigned, nObjs ); + // add objects + p->nObjs = 1; + Aig_ManForEachPo( pAig, pObj, i ) + if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + Caig_ManCreate_rec( p, pObj ); + assert( p->nObjs == nObjs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Caig_ManDelete( Caig_Man_t * p ) +{ + if ( p->vSims ) Vec_PtrFree( p->vSims ); + if ( p->vClassOld ) Vec_IntFree( p->vClassOld ); + if ( p->vClassNew ) Vec_IntFree( p->vClassNew ); + FREE( p->pFans0 ); + FREE( p->pFans1 ); + FREE( p->pRefs ); + FREE( p->pSims ); + FREE( p->pMems ); + FREE( p->pReprs ); + FREE( p->pNexts ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [References simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Caig_ManSimRead( Caig_Man_t * p, int i ) +{ + assert( i && p->pSims[i] > 0 ); + return p->pMems + p->pSims[i]; +} + +/**Function************************************************************* + + Synopsis [References simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Caig_ManSimRef( Caig_Man_t * p, int i ) +{ + unsigned * pSim; + assert( i ); + assert( p->pSims[i] == 0 ); + if ( p->MemFree == 0 ) + { + int * pPlace, Ent; + if ( p->nWordsAlloc == 0 ) + { + assert( p->pMems == NULL ); + p->nWordsAlloc = (1<<17); // -> 1Mb + p->nMems = 1; + } + p->nWordsAlloc *= 2; + p->pMems = REALLOC( unsigned, p->pMems, p->nWordsAlloc ); + pPlace = &p->MemFree; + for ( Ent = p->nMems * (p->nWords + 1); + Ent + p->nWords + 1 < p->nWordsAlloc; + Ent += p->nWords + 1 ) + { + *pPlace = Ent; + pPlace = p->pMems + Ent; + } + *pPlace = 0; + } + p->pSims[i] = p->MemFree; + pSim = p->pMems + p->MemFree; + p->MemFree = pSim[0]; + pSim[0] = p->pRefs[i]; + p->nMems++; + if ( p->nMemsMax < p->nMems ) + p->nMemsMax = p->nMems; + return pSim; +} + +/**Function************************************************************* + + Synopsis [Dereference simulaton info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Caig_ManSimDeref( Caig_Man_t * p, int i ) +{ + unsigned * pSim; + assert( i ); + assert( p->pSims[i] > 0 ); + pSim = p->pMems + p->pSims[i]; + if ( --pSim[0] == 0 ) + { + pSim[0] = p->MemFree; + p->MemFree = p->pSims[i]; + p->pSims[i] = 0; + p->nMems--; + } + return pSim; +} + +/**Function************************************************************* + + Synopsis [Simulates one round.] + + Description [Returns the number of PO entry if failed; 0 otherwise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Caig_ManSimulateRound( Caig_Man_t * p, int fMiter ) +{ + Vec_Int_t * vRefined = NULL; + unsigned * pRes0, * pRes1, * pRes; + int i, w, iFan0, iFan1; + if ( p->pReprs ) + vRefined = Vec_IntAlloc( 1000 ); + for ( i = 1; i < p->nObjs; i++ ) + { + if ( p->pFans0[i] == 0 ) // pi always has zero first fanin + { + pRes = Caig_ManSimRef( p, i ); + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = Aig_ManRandom( 0 ); + goto references; + } + if ( p->pFans1[i] == 0 ) // po always has non-zero 1st fanin and zero 2nd fanin + { + if ( fMiter ) + { + unsigned Const = Cec_LitIsCompl(p->pFans0[i])? ~0 : 0; + pRes0 = Caig_ManSimDeref( p, Cec_Lit2Var(p->pFans0[i]) ); + for ( w = 1; w <= p->nWords; w++ ) + if ( pRes0[w] != Const ) + return i; + } + continue; + } + pRes = Caig_ManSimRef( p, i ); + iFan0 = p->pFans0[i]; + iFan1 = p->pFans1[i]; + pRes0 = Caig_ManSimDeref( p, Cec_Lit2Var(p->pFans0[i]) ); + pRes1 = Caig_ManSimDeref( p, Cec_Lit2Var(p->pFans1[i]) ); + if ( Cec_LitIsCompl(iFan0) && Cec_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~(pRes0[w] | pRes1[w]); + else if ( Cec_LitIsCompl(iFan0) && !Cec_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~pRes0[w] & pRes1[w]; + else if ( !Cec_LitIsCompl(iFan0) && Cec_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w] & ~pRes1[w]; + else if ( !Cec_LitIsCompl(iFan0) && !Cec_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w] & pRes1[w]; +references: + if ( p->pReprs == NULL ) + continue; + // if this node is candidate constant, collect it + if ( p->pReprs[i] == 0 && !Caig_ManCompareConst(pRes + 1, p->nWords) ) + { + pRes[0]++; + Vec_IntPush( vRefined, i ); + } + // if the node belongs to a class, save it + if ( p->pReprs[i] > 0 || p->pNexts[i] > 0 ) + pRes[0]++; + // if this is the last node of the class, process it + if ( p->pReprs[i] > 0 && p->pNexts[i] == 0 ) + Caig_ManProcessClass( p, p->pReprs[i] ); + } + if ( p->pReprs ) + Caig_ManProcessRefined( p, vRefined ); + if ( p->pReprs ) + Vec_IntFree( vRefined ); + assert( p->nMems == 1 ); +/* + if ( p->nMems > 1 ) + { + for ( i = 1; i < p->nObjs; i++ ) + if ( p->pSims[i] ) + { + int x = 0; + } + } +*/ + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the bug is detected, 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose ) +{ + Caig_Man_t * p; + Cec_MtrStatus_t Status; + int i, RetValue = 0, clk, clkTotal = clock(); +/* + p = Caig_ManClassesPrepare( pAig, nWords, nIters ); +// if ( fVerbose ) + printf( "Maxcut = %6d. AIG mem = %8.3f Mb. Sim mem = %8.3f Mb.\n", + p->nMemsMax, + 1.0*(p->nObjs * 14)/(1<<20), + 1.0*(p->nMemsMax * (nWords+1))/(1<<20) ); + Caig_ManDelete( p ); + return 0; +*/ + Status = Cec_MiterStatus( pAig ); + if ( Status.nSat > 0 ) + { + printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut ); + return 1; + } + if ( Status.nUndec == 0 ) + { + printf( "Miter is trivially unsatisfiable.\n" ); + return 0; + } + Aig_ManRandom( 1 ); + p = Caig_ManCreate( pAig ); + p->nWords = nWords; + for ( i = 0; i < nIters; i++ ) + { + clk = clock(); + RetValue = Caig_ManSimulateRound( p, fMiter ); + if ( fVerbose ) + { + printf( "Iter %3d out of %3d and timeout %3d sec. ", i+1, nIters, TimeLimit ); + printf("Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC); + } + if ( RetValue > 0 ) + { + int iOut = Caig_ManFindPo(p->pAig, RetValue); + if ( fVerbose ) + printf( "Miter is satisfiable after simulation (output %d).\n", iOut ); + break; + } + if ( (clock() - clk)/CLOCKS_PER_SEC >= TimeLimit ) + { + printf( "No bug detected after %d rounds with time limit %d seconds.\n", i+1, TimeLimit ); + break; + } + } + if ( fVerbose ) + printf( "Maxcut = %6d. AIG mem = %8.3f Mb. Sim mem = %8.3f Mb.\n", + p->nMemsMax, + 1.0*(p->nObjs * 14)/(1<<20), + 1.0*(p->nMemsMax * 4 * (nWords+1))/(1<<20) ); + Caig_ManDelete( p ); + return RetValue > 0; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/cec/cecStatus.c b/src/aig/cec/cecStatus.c new file mode 100644 index 00000000..79d6ec66 --- /dev/null +++ b/src/aig/cec/cecStatus.c @@ -0,0 +1,187 @@ +/**CFile**************************************************************** + + FileName [cecStatus.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinatinoal equivalence checking.] + + Synopsis [Miter status.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecStatus.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cecInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns 1 if the output is known.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_OutputStatus( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pChild; + assert( Aig_ObjIsPo(pObj) ); + pChild = Aig_ObjChild0(pObj); + // check if the output is constant 0 + if ( pChild == Aig_ManConst0(p) ) + return 1; + // check if the output is constant 1 + if ( pChild == Aig_ManConst1(p) ) + return 1; + // check if the output is a primary input + if ( Aig_ObjIsPi(Aig_Regular(pChild)) ) + return 1; + // check if the output is 1 for the 0000 pattern + if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns number of used inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_CountInputs( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachPi( p, pObj, i ) + Counter += (int)(pObj->nRefs > 0); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Checks the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cec_MtrStatus_t Cec_MiterStatus( Aig_Man_t * p ) +{ + Cec_MtrStatus_t Status; + Aig_Obj_t * pObj, * pChild; + int i; + assert( p->nRegs == 0 ); + memset( &Status, 0, sizeof(Cec_MtrStatus_t) ); + Status.iOut = -1; + Status.nInputs = Cec_CountInputs( p ); + Status.nNodes = Aig_ManNodeNum( p ); + Status.nOutputs = Aig_ManPoNum(p); + Aig_ManForEachPo( p, pObj, i ) + { + pChild = Aig_ObjChild0(pObj); + // check if the output is constant 0 + if ( pChild == Aig_ManConst0(p) ) + Status.nUnsat++; + // check if the output is constant 1 + else if ( pChild == Aig_ManConst1(p) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + // check if the output is a primary input + else if ( Aig_ObjIsPi(Aig_Regular(pChild)) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + // check if the output is 1 for the 0000 pattern + else if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + else + Status.nUndec++; + } + return Status; +} + +/**Function************************************************************* + + Synopsis [Checks the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cec_MtrStatus_t Cec_MiterStatusTrivial( Aig_Man_t * p ) +{ + Cec_MtrStatus_t Status; + memset( &Status, 0, sizeof(Cec_MtrStatus_t) ); + Status.iOut = -1; + Status.nInputs = Aig_ManPiNum(p); + Status.nNodes = Aig_ManNodeNum( p ); + Status.nOutputs = Aig_ManPoNum(p); + Status.nUndec = Aig_ManPoNum(p); + return Status; +} + +/**Function************************************************************* + + Synopsis [Prints the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_MiterStatusPrint( Cec_MtrStatus_t S, char * pString, int Time ) +{ + printf( "%s:", pString ); + printf( " I =%6d", S.nInputs ); + printf( " N =%7d", S.nNodes ); + printf( " " ); + printf( " ? =%6d", S.nUndec ); + printf( " U =%6d", S.nUnsat ); + printf( " S =%6d", S.nSat ); + printf(" %7.2f sec\n", (float)(Time)/(float)(CLOCKS_PER_SEC)); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/cec/module.make b/src/aig/cec/module.make new file mode 100644 index 00000000..29f8c859 --- /dev/null +++ b/src/aig/cec/module.make @@ -0,0 +1,8 @@ +SRC += src/aig/cec/cecAig.c \ + src/aig/cec/cecClass.c \ + src/aig/cec/cecCnf.c \ + src/aig/cec/cecCore.c \ + src/aig/cec/cecMan.c \ + src/aig/cec/cecSat.c \ + src/aig/cec/cecSim.c \ + src/aig/cec/cecStatus.c diff --git a/src/aig/cgt/cgt.h b/src/aig/cgt/cgt.h index b9997d56..f8c1cc2e 100644 --- a/src/aig/cgt/cgt.h +++ b/src/aig/cgt/cgt.h @@ -52,8 +52,9 @@ struct Cgt_Par_t_ int nConfMax; // the max number of conflicts at a node int nVarsMin; // the min number of variables to recycle the SAT solver int nFlopsMin; // the min number of flops needed to recycle the SAT solver + int fAreaOnly; // derive clock gating to minimize area int fVerbose; // verbosity flag - + int fVeryVerbose; // verbosity flag }; //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/cgt/cgtAig.c b/src/aig/cgt/cgtAig.c index b30d3f16..d411c25a 100644 --- a/src/aig/cgt/cgtAig.c +++ b/src/aig/cgt/cgtAig.c @@ -67,7 +67,7 @@ void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevel void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) { Vec_PtrClear( vCands ); - if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) ) + if ( !Aig_ObjIsNode(pObj) ) return; Aig_ManIncrementTravId( pAig ); Cgt_ManDetectCandidates_rec( pAig, pObj, nLevelMax, vCands ); @@ -134,6 +134,67 @@ void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_P assert( Vec_PtrSize(vFanout) > 0 ); } +/**Function************************************************************* + + Synopsis [Computes visited nodes in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited ) +{ + if ( Aig_ObjIsPi(pObj) ) + return; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + assert( Aig_ObjIsNode(pObj) ); + Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited ); + Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited ); + Vec_PtrPush( vVisited, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes visited nodes in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vVisited ); + Aig_ManIncrementTravId( pAig ); + Vec_PtrForEachEntry( vFanout, pObj, i ) + Cgt_ManCollectVisited_rec( pAig, pObj, vVisited ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) +{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj)); } +static inline Aig_Obj_t * Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) +{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj)); } + /**Function************************************************************* Synopsis [Derives miter for clock-gating.] @@ -145,15 +206,46 @@ void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_P SeeAlso [] ***********************************************************************/ -Aig_Obj_t * Cgt_ManConstructMiter( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo ) +Aig_Obj_t * Cgt_ManConstructCareCondition( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo, Vec_Ptr_t * vCopy0, Vec_Ptr_t * vCopy1 ) { - Aig_Obj_t * pMiter, * pRoot; + Aig_Obj_t * pMiter, * pObj, * pTemp; int i; assert( Aig_ObjIsPi(pObjLo) ); - pMiter = Aig_ManConst0( pNew ); + // detect nodes and their cone Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout ); - Vec_PtrForEachEntry( p->vFanout, pRoot, i ) - pMiter = Aig_Or( pNew, pMiter, Aig_Exor(pNew, pRoot->pData, pRoot->pNext) ); + Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited ); + // add new variables if the observability condition depends on PI variables + Vec_PtrForEachEntry( p->vVisited, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL ) + { + pTemp = Aig_ObjCreatePi( pNew ); + Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp ); + } + if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL ) + { + pTemp = Aig_ObjCreatePi( pNew ); + Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp ); + } + } + // construct AIGs for the nodes + Vec_PtrForEachEntry( p->vVisited, pObj, i ) + { + pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) ); + Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp ); + pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp ); + } + // construct the care miter + pMiter = Aig_ManConst0( pNew ); + Vec_PtrForEachEntry( p->vFanout, pObj, i ) + { + pTemp = Aig_Exor( pNew, Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) ); + pMiter = Aig_Or( pNew, pMiter, pTemp ); + } return pMiter; } @@ -171,11 +263,12 @@ Aig_Obj_t * Cgt_ManConstructMiter( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ) { Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter; + Vec_Ptr_t * vCopy0, * vCopy1; int i; assert( Aig_ManRegNum(p->pAig) ); - Aig_ManCleanNext( p->pAig ); pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) ); + pNew->pName = Aig_UtilStrsav( "CG_miter" ); // build the first frame Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( p->pAig, pObj, i ) @@ -184,24 +277,126 @@ Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // Saig_ManForEachPo( p->pAig, pObj, i ) // pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - // build the second frame - Aig_ManConst1(p->pAig)->pNext = Aig_ManConst1(pNew); - Saig_ManForEachPi( p->pAig, pObj, i ) - pObj->pNext = Aig_ObjCreatePi( pNew ); - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - pObjLo->pNext = Aig_ObjChild0Copy(pObjLi); - Aig_ManForEachNode( p->pAig, pObj, i ) - if ( Aig_ObjLevel(pObj) <= p->pPars->nOdcMax ) - pObj->pNext = Aig_And( pNew, Aig_ObjChild0Next(pObj), Aig_ObjChild1Next(pObj) ); - // construct clock-gating miters for each register input - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - pObjLi->pData = Aig_ObjCreatePo( pNew, Cgt_ManConstructMiter(p, pNew, pObjLo) ); - Aig_ManCleanNext( p->pAig ); - Aig_ManSetPioNumbers( p->pAig ); + if ( p->pPars->nOdcMax > 0 ) + { + // create storage for observability conditions + vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); + vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); + // initialize register outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); + } + // compute observability condition for each latch output + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + // set the constants + Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) ); + // compute condition + pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 ); + // restore the values + Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); + Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); + // compute the miter + pMiter = Aig_Exor( pNew, pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); + pMiter = Aig_And( pNew, pMiter, pCare ); + pObjLi->pData = Aig_ObjCreatePo( pNew, pMiter ); + } + Vec_PtrFree( vCopy0 ); + Vec_PtrFree( vCopy1 ); + } + else + { + // construct clock-gating miters for each register input + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + pMiter = Aig_Exor( pNew, pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); + pObjLi->pData = Aig_ObjCreatePo( pNew, pMiter ); + } + } Aig_ManCleanup( pNew ); + Aig_ManSetPioNumbers( pNew ); return pNew; } +/**Function************************************************************* + + Synopsis [Adds relevant constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew ) +{ + Aig_Obj_t * pObj0, * pObj1; + if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) ) + return pObj->pData; + Aig_ObjSetTravIdCurrent( pCare, pObj ); + if ( Aig_ObjIsPi(pObj) ) + return pObj->pData = NULL; + pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew ); + if ( pObj0 == NULL ) + return pObj->pData = NULL; + pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew ); + if ( pObj1 == NULL ) + return pObj->pData = NULL; + pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) ); + pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) ); + return pObj->pData = Aig_And( pNew, pObj0, pObj1 ); +} + +/**Function************************************************************* + + Synopsis [Builds constraints belonging to the given partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves ) +{ + Vec_Int_t * vOuts; + Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig; + int i, k, iOut; + // go through the PIs of the partition + // label the corresponding PIs of the care set + Aig_ManIncrementTravId( pCare ); + Vec_PtrForEachEntry( vLeaves, pLeaf, i ) + { + pPi = Aig_ManPi( pCare, Aig_ObjPioNum(pLeaf) ); + Aig_ObjSetTravIdCurrent( pCare, pPi ); + pPi->pData = pLeaf->pData; + } + // construct the constraints + Vec_PtrForEachEntry( vLeaves, pLeaf, i ) + { + vOuts = Vec_VecEntry( vSuppsInv, Aig_ObjPioNum(pLeaf) ); + Vec_IntForEachEntry( vOuts, iOut, k ) + { + pPo = Aig_ManPo( pCare, iOut ); + if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) ) + continue; + Aig_ObjSetTravIdCurrent( pCare, pPo ); + if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) ) + continue; + pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew ); + if ( pObjAig == NULL ) + continue; + pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); + Aig_ObjCreatePo( pNew, pObjAig ); + } + } +} + /**Function************************************************************* Synopsis [Duplicates the AIG recursively.] @@ -213,15 +408,19 @@ Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ) SeeAlso [] ***********************************************************************/ -Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj ) +Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return pObj->pData; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsPi(pObj) ) - return pObj->pData = Aig_ObjCreatePi( pNew ); - Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); - Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj) ); + { + pObj->pData = Aig_ObjCreatePi( pNew ); + Vec_PtrPush( vLeaves, pObj ); + return pObj->pData; + } + Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves ); + Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj), vLeaves ); return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } @@ -236,32 +435,78 @@ Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj SeeAlso [] ***********************************************************************/ -Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart ) +Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pFrame, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ) { + Vec_Ptr_t * vRoots, * vLeaves, * vPos; Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; - assert( Aig_ManRegNum(pAig) == 0 ); + assert( Aig_ManRegNum(pFrame) == 0 ); + vRoots = Vec_PtrAlloc( 100 ); + vLeaves = Vec_PtrAlloc( 100 ); + vPos = Vec_PtrAlloc( 100 ); pNew = Aig_ManStart( nVarsMin ); - Aig_ManIncrementTravId( pAig ); - Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); - for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManPoNum(pAig); i++ ) + pNew->pName = Aig_UtilStrsav( "partition" ); + Aig_ManIncrementTravId( pFrame ); + Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew); + Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) ); + for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManPoNum(pFrame); i++ ) { - pObj = Aig_ManPo( pAig, i ); - Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); - pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + pObj = Aig_ManPo( pFrame, i ); + Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); + Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); + Vec_PtrPush( vPos, pObj ); } - for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManPoNum(pAig); i++ ) + for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManPoNum(pFrame); i++ ) { - pObj = Aig_ManPo( pAig, i ); - Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); - pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + pObj = Aig_ManPo( pFrame, i ); + Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); + Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); + Vec_PtrPush( vPos, pObj ); } - assert( nFlopsMin >= Aig_ManPoNum(pAig) || Aig_ManPoNum(pNew) >= nFlopsMin ); + assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin ); + // create constaints + if ( pCare ) + Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves ); + // create POs + Vec_PtrForEachEntry( vPos, pObj, i ) + pObj->pData = Aig_ObjCreatePo( pNew, Vec_PtrEntry(vRoots, i) ); + if ( pnOutputs != NULL ) + *pnOutputs = Vec_PtrSize( vPos ); + Vec_PtrFree( vRoots ); + Vec_PtrFree( vLeaves ); + Vec_PtrFree( vPos ); return pNew; } +/**Function************************************************************* + + Synopsis [Implements one clock-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates ) +{ + Aig_Obj_t * pGate, * pTotal; + int i; + assert( Vec_PtrSize(vGates) > 0 ); + pTotal = Aig_ManConst0(pNew); + Vec_PtrForEachEntry( vGates, pGate, i ) + { + if ( Aig_Regular(pGate)->pNext ) + pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) ); + else + pGate = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); + pTotal = Aig_Or( pNew, pTotal, pGate ); + } + return pTotal; +} + /**Function************************************************************* Synopsis [Derives AIG after clock-gating.] @@ -273,34 +518,74 @@ Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, SeeAlso [] ***********************************************************************/ -Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Ptr_t * vGates ) +Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ) { Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGate, * pGateNew; - int i; + Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew; + Vec_Ptr_t * vOne; + int i, k; + Aig_ManCleanNext( pAig ); + // label nodes + Vec_VecForEachEntry( vGates, pObj, i, k ) + { + if ( Aig_IsComplement(pObj) ) + Aig_Regular(pObj)->fMarkB = 1; + else + Aig_Regular(pObj)->fMarkA = 1; + } + // construct AIG assert( Aig_ManRegNum(pAig) ); pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) ); + pNew->pName = Aig_UtilStrsav( pAig->pName ); + pNew->pSpec = Aig_UtilStrsav( pAig->pSpec ); Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew); Aig_ManForEachPi( pAig, pObj, i ) pObj->pData = Aig_ObjCreatePi( pNew ); - Aig_ManForEachNode( pAig, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + if ( fReduce ) + { + Aig_ManForEachNode( pAig, pObj, i ) + { + assert( !(pObj->fMarkA && pObj->fMarkB) ); + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + if ( pObj->fMarkA ) + { + pObj->pNext = pObj->pData; + pObj->pData = Aig_ManConst0(pNew); + } + else if ( pObj->fMarkB ) + { + pObj->pNext = pObj->pData; + pObj->pData = Aig_ManConst1(pNew); + } + } + } + else + { + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + if ( pnUsedNodes != NULL ) + *pnUsedNodes = Aig_ManNodeNum(pNew); Saig_ManForEachPo( pAig, pObj, i ) pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { - pGate = Vec_PtrEntry( vGates, i ); - if ( pGate == NULL ) + vOne = Vec_VecEntry( vGates, i ); + if ( Vec_PtrSize(vOne) == 0 ) pObjNew = Aig_ObjChild0Copy(pObjLi); else { - pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); +// pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); + pGateNew = Cgt_ManBuildClockGate( pNew, vOne ); pObjNew = Aig_Mux( pNew, pGateNew, pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); } pObjLi->pData = Aig_ObjCreatePo( pNew, pObjNew ); } Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) ); + // unlabel nodes + Aig_ManCleanMarkAB( pAig ); + Aig_ManCleanNext( pAig ); return pNew; } diff --git a/src/aig/cgt/cgtCore.c b/src/aig/cgt/cgtCore.c index a06820b4..f49cd46f 100644 --- a/src/aig/cgt/cgtCore.c +++ b/src/aig/cgt/cgtCore.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "cgtInt.h" +#include "bar.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -42,13 +43,14 @@ void Cgt_SetDefaultParams( Cgt_Par_t * p ) { memset( p, 0, sizeof(Cgt_Par_t) ); - p->nLevelMax = 1000; // the max number of levels to look for clock-gates + p->nLevelMax = 25; // the max number of levels to look for clock-gates p->nCandMax = 1000; // the max number of candidates at each node p->nOdcMax = 0; // the max number of ODC levels to consider - p->nConfMax = 1000; // the max number of conflicts at a node - p->nVarsMin = 5000; // the min number of vars to recycle the SAT solver - p->nFlopsMin = 25; // the min number of flops to recycle the SAT solver - p->fVerbose = 0; // verbosity flag + p->nConfMax = 10; // the max number of conflicts at a node + p->nVarsMin = 1000; // the min number of vars to recycle the SAT solver + p->nFlopsMin = 5; // the min number of flops to recycle the SAT solver + p->fAreaOnly = 0; // derive clock-gating to minimize area + p->fVerbose = 1; // verbosity flag } /**Function************************************************************* @@ -62,14 +64,14 @@ void Cgt_SetDefaultParams( Cgt_Par_t * p ) SeeAlso [] ***********************************************************************/ -int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandFrame, Aig_Obj_t * pMiterFrame ) +int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart ) { unsigned * pInfoCand, * pInfoMiter; int w, nWords = Aig_BitWordNum( p->nPatts ); - pInfoCand = Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandFrame)) ); - pInfoMiter = Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterFrame) ); + pInfoCand = Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) ); + pInfoMiter = Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) ); // C => !M -- true is the same as C & M -- false - if ( !Aig_IsComplement(pCandFrame) ) + if ( !Aig_IsComplement(pCandPart) ) { for ( w = 0; w < nWords; w++ ) if ( pInfoCand[w] & pInfoMiter[w] ) @@ -106,6 +108,7 @@ void Cgt_SimulationRecord( Cgt_Man_t * p ) if ( p->nPatts == 32 * p->nPattWords ) { Vec_PtrReallocSimInfo( p->vPatts ); + Vec_PtrCleanSimInfo( p->vPatts, p->nPattWords, 2 * p->nPattWords ); p->nPattWords *= 2; } } @@ -121,15 +124,16 @@ void Cgt_SimulationRecord( Cgt_Man_t * p ) SeeAlso [] ***********************************************************************/ -void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart ) +void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart, int nOutputs ) { Vec_Ptr_t * vNodes = p->vFanout; Aig_Obj_t * pMiter, * pCand, * pMiterFrame, * pCandFrame, * pMiterPart, * pCandPart; - int i, k, RetValue; + int i, k, RetValue, nCalls; assert( Vec_VecSize(p->vGatesAll) == Aig_ManPoNum(p->pFrame) ); // go through all the registers inputs of this range - for ( i = iStart; i < iStart + Aig_ManPoNum(p->pPart); i++ ) + for ( i = iStart; i < iStart + nOutputs; i++ ) { + nCalls = p->nCalls; pMiter = Saig_ManLi( p->pAig, i ); Cgt_ManDetectCandidates( p->pAig, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes ); // go through the candidates of this PO @@ -153,6 +157,8 @@ void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart ) if ( RetValue == 0 ) Cgt_SimulationRecord( p ); } + else + p->nCallsFiltered++; // try reverse polarity if ( Cgt_SimulationFilter( p, Aig_Not(pCandPart), pMiterPart ) ) { @@ -165,9 +171,18 @@ void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart ) if ( RetValue == 0 ) Cgt_SimulationRecord( p ); } + else + p->nCallsFiltered++; } + + if ( p->pPars->fVerbose ) + { +// printf( "Flop %3d : Cand = %4d. Gate = %4d. SAT calls = %3d.\n", +// i, Vec_PtrSize(vNodes), Vec_PtrSize(Vec_VecEntry(p->vGatesAll, i)), p->nCalls-nCalls ); + } + } -} +} /**Function************************************************************* @@ -182,16 +197,33 @@ void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart ) ***********************************************************************/ int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart ) { - int iStop; - p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart ); - p->pCnf = Cnf_DeriveSimple( p->pPart, Aig_ManPoNum(p->pPart) ); + int nOutputs, iStop, clk, clkTotal = clock(); + int nCallsUnsat = p->nCallsUnsat; + int nCallsSat = p->nCallsSat; + int nCallsUndec = p->nCallsUndec; + int nCallsFiltered = p->nCallsFiltered; +clk = clock(); + p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart, p->pCare, p->vSuppsInv, &nOutputs ); + p->pCnf = Cnf_DeriveSimple( p->pPart, nOutputs ); p->pSat = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); sat_solver_compress( p->pSat ); - p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), 16 ); + p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), p->nPattWords ); Vec_PtrCleanSimInfo( p->vPatts, 0, p->nPattWords ); - Cgt_ClockGatingRangeCheck( p, iStart ); - iStop = iStart + Aig_ManPoNum(p->pPart); +p->timePrepare += clock() - clk; + Cgt_ClockGatingRangeCheck( p, iStart, nOutputs ); + iStop = iStart + nOutputs; + if ( p->pPars->fVeryVerbose ) + { + printf( "%5d : D =%4d. C =%5d. Var =%6d. Pr =%5d. Cex =%5d. F =%4d. Saved =%6d. ", + iStart, iStop-iStart, Aig_ManPoNum(p->pPart)-nOutputs, p->pSat->size, + p->nCallsUnsat-nCallsUnsat, + p->nCallsSat -nCallsSat, + p->nCallsUndec-nCallsUndec, + p->nCallsFiltered-nCallsFiltered ); + PRT( "Time", clock() - clkTotal ); + } Cgt_ManClean( p ); + p->nRecycles++; return iStop; } @@ -208,18 +240,30 @@ int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart ) ***********************************************************************/ Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) { - Cgt_Par_t Pars; + Bar_Progress_t * pProgress = NULL; + Cgt_Par_t Pars; Cgt_Man_t * p; Vec_Vec_t * vGatesAll; - int iStart; + int iStart, clk = clock(), clkTotal = clock(); + // reset random numbers + Aig_ManRandom( 1 ); if ( pPars == NULL ) Cgt_SetDefaultParams( pPars = &Pars ); p = Cgt_ManCreate( pAig, pCare, pPars ); p->pFrame = Cgt_ManDeriveAigForGating( p ); +p->timeAig += clock() - clk; assert( Aig_ManPoNum(p->pFrame) == Saig_ManRegNum(p->pAig) ); + pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p->pFrame) ); for ( iStart = 0; iStart < Aig_ManPoNum(p->pFrame); ) + { + Bar_ProgressUpdate( pProgress, iStart, NULL ); iStart = Cgt_ClockGatingRange( p, iStart ); + } + Bar_ProgressStop( pProgress ); vGatesAll = p->vGatesAll; + p->vGatesAll = NULL; +p->timeTotal = clock() - clkTotal; + Cgt_ManStop( p ); return vGatesAll; } @@ -238,11 +282,29 @@ Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pP { Aig_Man_t * pGated; Vec_Vec_t * vGatesAll; - Vec_Ptr_t * vGates; + Vec_Vec_t * vGates; + int nNodesUsed, clk = clock(); vGatesAll = Cgt_ClockGatingCandidates( pAig, pCare, pPars ); - vGates = Cgt_ManDecideSimple( pAig, vGatesAll ); - pGated = Cgt_ManDeriveGatedAig( pAig, vGates ); - Vec_PtrFree( vGates ); + if ( pPars->fAreaOnly ) + vGates = Cgt_ManDecideArea( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose ); + else + vGates = Cgt_ManDecideSimple( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose ); + if ( pPars->fVerbose ) + { +// printf( "Before CG: " ); +// Aig_ManPrintStats( pAig ); + } + pGated = Cgt_ManDeriveGatedAig( pAig, vGates, pPars->fAreaOnly, &nNodesUsed ); + if ( pPars->fVerbose ) + { +// printf( "After CG: " ); +// Aig_ManPrintStats( pGated ); + printf( "Nodes: Before CG = %6d. After CG = %6d. (%6.2f %%). Total after CG = %6d.\n", + Aig_ManNodeNum(pAig), nNodesUsed, + 100.0*nNodesUsed/Aig_ManNodeNum(pAig), + Aig_ManNodeNum(pGated) ); + } + Vec_VecFree( vGates ); Vec_VecFree( vGatesAll ); return pGated; } diff --git a/src/aig/cgt/cgtDecide.c b/src/aig/cgt/cgtDecide.c index 8f57bd4a..0fb2a681 100644 --- a/src/aig/cgt/cgtDecide.c +++ b/src/aig/cgt/cgtDecide.c @@ -25,8 +25,11 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); +extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); +extern int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ); +extern int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ); +extern int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -34,7 +37,7 @@ extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Ob /**Function************************************************************* - Synopsis [Chooses what clock-gate to use for each register.] + Synopsis [Collects POs in the transitive fanout.] Description [] @@ -43,11 +46,127 @@ extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Ob SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Cgt_ManDecide( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll ) +void Cgt_ManCollectFanoutPos_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) +{ + Aig_Obj_t * pFanout; + int f, iFanout; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsPo(pObj) ) + { + Vec_PtrPush( vFanout, pObj ); + return; + } + Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) + Cgt_ManCollectFanoutPos_rec( pAig, pFanout, vFanout ); +} + +/**Function************************************************************* + + Synopsis [Collects POs in the transitive fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cgt_ManCollectFanoutPos( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) +{ + Vec_PtrClear( vFanout ); + Aig_ManIncrementTravId( pAig ); + Cgt_ManCollectFanoutPos_rec( pAig, pObj, vFanout ); +} + +/**Function************************************************************* + + Synopsis [Checks if all PO fanouts can be gated by this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cgt_ManCheckGateComplete( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, Aig_Obj_t * pGate, Vec_Ptr_t * vFanout ) { Vec_Ptr_t * vGates; - vGates = Vec_PtrStart( Saig_ManRegNum(pAig) ); - return vGates; + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( vFanout, pObj, i ) + { + if ( Saig_ObjIsPo(pAig, pObj) ) + return 0; + vGates = Vec_VecEntry( vGatesAll, Aig_ObjPioNum(pObj) - Saig_ManPoNum(pAig) ); + if ( Vec_PtrFind( vGates, pGate ) == -1 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the set of complete clock gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Cgt_ManCompleteGates( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) +{ + Vec_Ptr_t * vFanout, * vGatesFull; + Aig_Obj_t * pGate, * pGateR; + int i, k; + vFanout = Vec_PtrAlloc( 100 ); + vGatesFull = Vec_PtrAlloc( 100 ); + Vec_VecForEachEntry( vGatesAll, pGate, i, k ) + { + pGateR = Aig_Regular(pGate); + if ( pGateR->fMarkA ) + continue; + pGateR->fMarkA = 1; + Cgt_ManCollectFanoutPos( pAig, pGateR, vFanout ); + if ( Cgt_ManCheckGateComplete( pAig, vGatesAll, pGate, vFanout ) ) + Vec_PtrPush( vGatesFull, pGate ); + } + Vec_PtrFree( vFanout ); + Vec_VecForEachEntry( vGatesAll, pGate, i, k ) + Aig_Regular(pGate)->fMarkA = 0; + return vGatesFull; +} + +/**Function************************************************************* + + Synopsis [Calculates coverage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Cgt_ManComputeCoverage( Aig_Man_t * pAig, Vec_Vec_t * vGates ) +{ + int nFrames = 32; + int nWords = 1; + Ssw_Sml_t * pSml; + Vec_Ptr_t * vOne; + int i, nTransTotal = 0, nTransSaved = 0; + pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); + Vec_VecForEachLevel( vGates, vOne, i ) + { + nTransSaved += Ssw_SmlNodeCountOnesRealVec( pSml, vOne ); + nTransTotal += 32 * nFrames * nWords; + } + Ssw_SmlStop( pSml ); + return (float)100.0*nTransSaved/nTransTotal; } /**Function************************************************************* @@ -62,14 +181,18 @@ Vec_Ptr_t * Cgt_ManDecide( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll ) SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll ) +Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) { + int nFrames = 32; + int nWords = 1; Ssw_Sml_t * pSml; - Vec_Ptr_t * vGates, * vCands; + Vec_Vec_t * vGates; + Vec_Ptr_t * vCands; Aig_Obj_t * pObjLi, * pObjLo, * pCand, * pCandBest; - int i, k, nHitsCur, nHitsMax; - vGates = Vec_PtrStart( Saig_ManRegNum(pAig) ); - pSml = Ssw_SmlSimulateSeq( pAig, 0, 32, 1 ); + int i, k, nHitsCur, nHitsMax, Counter = 0, clk = clock(); + int nTransTotal = 0, nTransSaved = 0; + vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); + pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { nHitsMax = 0; @@ -78,10 +201,10 @@ Vec_Ptr_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll ) Vec_PtrForEachEntry( vCands, pCand, k ) { // check if this is indeed a clock-gate - if ( !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) ) + if ( nOdcMax == 0 && !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) ) printf( "Clock gate candidate is invalid!\n" ); // find its characteristic number - nHitsCur = Ssw_SmlCountXorImplication( pSml, pObjLi, pObjLo, pCand ); + nHitsCur = Ssw_SmlNodeCountOnesReal( pSml, pCand ); if ( nHitsMax < nHitsCur ) { nHitsMax = nHitsCur; @@ -89,9 +212,80 @@ Vec_Ptr_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll ) } } if ( pCandBest != NULL ) - Vec_PtrWriteEntry( vGates, i, pCandBest ); + { + Vec_VecPush( vGates, i, pCandBest ); + Counter++; + nTransSaved += nHitsMax; + } + nTransTotal += 32 * nFrames * nWords; } Ssw_SmlStop( pSml ); + if ( fVerbose ) + { + printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", + Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); +// printf( "Gated transitions = %5.2f %%. (%5.2f %%.) ", +// 100.0*nTransSaved/nTransTotal, Cgt_ManComputeCoverage(pAig, vGates) ); + printf( "Gated transitions = %5.2f %%. ", Cgt_ManComputeCoverage(pAig, vGates) ); + PRT( "Time", clock() - clk ); + } +/* + { + Vec_Ptr_t * vCompletes; + vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); + printf( "Complete gates = %d. \n", Vec_PtrSize(vCompletes) ); + Vec_PtrFree( vCompletes ); + } +*/ + return vGates; +} + +/**Function************************************************************* + + Synopsis [Computes the set of complete clock gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) +{ + Vec_Vec_t * vGates; + Vec_Ptr_t * vCompletes, * vOne; + Aig_Obj_t * pGate; + int i, k, Counter = 0, clk = clock(); + // derive and label complete gates + vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); + // label complete gates + Vec_PtrForEachEntry( vCompletes, pGate, i ) + Aig_Regular(pGate)->fMarkA = 1; + // select only complete gates + vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); + Vec_VecForEachEntry( vGatesAll, pGate, i, k ) + if ( Aig_Regular(pGate)->fMarkA ) + Vec_VecPush( vGates, i, pGate ); + // unlabel complete gates + Vec_PtrForEachEntry( vCompletes, pGate, i ) + Aig_Regular(pGate)->fMarkA = 0; + // count the number of gated flops + Vec_VecForEachLevel( vGates, vOne, i ) + { + Counter += (int)(Vec_PtrSize(vOne) > 0); +// printf( "%d ", Vec_PtrSize(vOne) ); + } +// printf( "\n" ); + if ( fVerbose ) + { + printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", + Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); + printf( "Complete gates = %6d. Gated transitions = %5.2f %%. ", + Vec_PtrSize(vCompletes), Cgt_ManComputeCoverage(pAig, vGates) ); + PRT( "Time", clock() - clk ); + } + Vec_PtrFree( vCompletes ); return vGates; } diff --git a/src/aig/cgt/cgtInt.h b/src/aig/cgt/cgtInt.h index 7b4b6e63..23d851f3 100644 --- a/src/aig/cgt/cgtInt.h +++ b/src/aig/cgt/cgtInt.h @@ -48,12 +48,16 @@ struct Cgt_Man_t_ // user's data Cgt_Par_t * pPars; // user's parameters Aig_Man_t * pAig; // user's AIG manager - Aig_Man_t * pCare; // user's constraints + // user's constraints + Aig_Man_t * pCare; // constraint cones + Vec_Vec_t * vSuppsInv; // inverse support of the constraints + // result of clock-gating Vec_Vec_t * vGatesAll; // the computed clock-gates Vec_Ptr_t * vGates; // the selected clock-gates // internal data Aig_Man_t * pFrame; // clock gate AIG manager Vec_Ptr_t * vFanout; // temporary storage for fanouts + Vec_Ptr_t * vVisited; // temporary storage for visited nodes // SAT solving Aig_Man_t * pPart; // partition Cnf_Dat_t * pCnf; // CNF of the partition @@ -62,14 +66,21 @@ struct Cgt_Man_t_ int nPatts; // the number of patterns accumulated int nPattWords; // the number of pattern words // statistics + int nRecycles; // recycles int nCalls; // total calls int nCallsSat; // satisfiable calls int nCallsUnsat; // unsatisfiable calls int nCallsUndec; // undecided calls + int nCallsFiltered; // filtered out calls + int timeAig; // constructing AIG + int timePrepare; // partitioning and SAT solving int timeSat; // total runtime int timeSatSat; // satisfiable runtime int timeSatUnsat; // unsatisfiable runtime int timeSatUndec; // undecided runtime + int timeDecision; // making decision about what gates to use + int timeOther; // other runtime + int timeTotal; // total runtime }; //////////////////////////////////////////////////////////////////////// @@ -83,11 +94,11 @@ struct Cgt_Man_t_ /*=== cgtAig.c ==========================================================*/ extern void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ); extern Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ); -extern Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart ); -extern Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Ptr_t * vGates ); +extern Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ); +extern Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ); /*=== cgtDecide.c ==========================================================*/ -extern Vec_Ptr_t * Cgt_ManDecide( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll ); -extern Vec_Ptr_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll ); +extern Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ); +extern Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ); /*=== cgtMan.c ==========================================================*/ extern Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); extern void Cgt_ManClean( Cgt_Man_t * p ); diff --git a/src/aig/cgt/cgtMan.c b/src/aig/cgt/cgtMan.c index 9615d2e6..a3385228 100644 --- a/src/aig/cgt/cgtMan.c +++ b/src/aig/cgt/cgtMan.c @@ -53,7 +53,19 @@ Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPar p->pAig = pAig; p->vGatesAll = Vec_VecStart( Saig_ManRegNum(pAig) ); p->vFanout = Vec_PtrAlloc( 1000 ); + p->vVisited = Vec_PtrAlloc( 1000 ); p->nPattWords = 16; + if ( pCare == NULL ) + return p; + // check out the constraints + if ( Aig_ManPiNum(pCare) != Aig_ManPiNum(pAig) ) + { + printf( "The PI count of care (%d) and AIG (%d) differ. Careset is not used.\n", + Aig_ManPiNum(pCare), Aig_ManPiNum(pAig) ); + return p; + } + p->pCare = pCare; + p->vSuppsInv = (Vec_Vec_t *)Aig_ManSupportsInverse( p->pCare ); return p; } @@ -106,27 +118,16 @@ void Cgt_ManClean( Cgt_Man_t * p ) ***********************************************************************/ void Cgt_ManPrintStats( Cgt_Man_t * p ) { + printf( "Params: LevMax = %d. CandMax = %d. OdcMax = %d. ConfMax = %d. VarMin = %d. FlopMin = %d.\n", + p->pPars->nLevelMax, p->pPars->nCandMax, p->pPars->nOdcMax, + p->pPars->nConfMax, p->pPars->nVarsMin, p->pPars->nFlopsMin ); + printf( "SAT : Calls = %d. Unsat = %d. Sat = %d. Fails = %d. Recycles = %d. ", + p->nCalls, p->nCallsUnsat, p->nCallsSat, p->nCallsUndec, p->nRecycles ); + PRT( "Time", p->timeTotal ); /* - double nMemory = 1.0*Aig_ManObjNumMax(p->pAig)*p->nFrames*(2*sizeof(int)+2*sizeof(void*))/(1<<20); - - printf( "Parameters: F = %d. AddF = %d. C-lim = %d. Constr = %d. MaxLev = %d. Mem = %0.2f Mb.\n", - p->pPars->nFramesK, p->pPars->nFramesAddSim, p->pPars->nBTLimit, p->pPars->nConstrs, p->pPars->nMaxLevs, nMemory ); - printf( "AIG : PI = %d. PO = %d. Latch = %d. Node = %d. Ave SAT vars = %d.\n", - Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), Saig_ManRegNum(p->pAig), Aig_ManNodeNum(p->pAig), - 0/p->pPars->nIters ); - printf( "SAT calls : Proof = %d. Cex = %d. Fail = %d. Lits proved = %d.\n", - p->nSatProof, p->nSatCallsSat, p->nSatFailsReal, Cgt_ManCountEquivs(p) ); - printf( "SAT solver: Vars max = %d. Calls max = %d. Recycles = %d. Sim rounds = %d.\n", - p->nVarsMax, p->nCallsMax, p->nRecyclesTotal, p->nSimRounds ); - printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", - p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1), - p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) ); - - p->timeOther = p->timeTotal-p->timeBmc-p->timeReduce-p->timeMarkCones-p->timeSimSat-p->timeSat; - PRTP( "BMC ", p->timeBmc, p->timeTotal ); - PRTP( "Spec reduce", p->timeReduce, p->timeTotal ); - PRTP( "Mark cones ", p->timeMarkCones, p->timeTotal ); - PRTP( "Sim SAT ", p->timeSimSat, p->timeTotal ); + p->timeOther = p->timeTotal-p->timeAig-p->timePrepare-p->timeSat-p->timeDecision; + PRTP( "AIG ", p->timeAig, p->timeTotal ); + PRTP( "Prepare ", p->timePrepare, p->timeTotal ); PRTP( "SAT solving", p->timeSat, p->timeTotal ); PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); PRTP( " sat ", p->timeSatSat, p->timeTotal ); @@ -155,8 +156,13 @@ void Cgt_ManStop( Cgt_Man_t * p ) Aig_ManStop( p->pFrame ); Cgt_ManClean( p ); Vec_PtrFree( p->vFanout ); - Vec_PtrFree( p->vGates ); - Vec_VecFree( p->vGatesAll ); + Vec_PtrFree( p->vVisited ); + if ( p->vGates ) + Vec_PtrFree( p->vGates ); + if ( p->vGatesAll ) + Vec_VecFree( p->vGatesAll ); + if ( p->vSuppsInv ) + Vec_VecFree( p->vSuppsInv ); free( p ); } diff --git a/src/aig/cnf/cnfWrite.c b/src/aig/cnf/cnfWrite.c index 860c7e3e..8a6a9160 100644 --- a/src/aig/cnf/cnfWrite.c +++ b/src/aig/cnf/cnfWrite.c @@ -422,7 +422,7 @@ Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs ) OutVar = pCnf->pVarNums[ Aig_ManConst1(p)->Id ]; assert( OutVar <= Aig_ManObjNumMax(p) ); *pClas++ = pLits; - *pLits++ = 2 * OutVar; + *pLits++ = 2 * OutVar; // write the output literals Aig_ManForEachPo( p, pObj, i ) diff --git a/src/aig/dar/dar.h b/src/aig/dar/dar.h index 99c0276d..c2d53c89 100644 --- a/src/aig/dar/dar.h +++ b/src/aig/dar/dar.h @@ -47,6 +47,7 @@ struct Dar_RwrPar_t_ int fFanout; // support fanout representation int fUpdateLevel; // update level int fUseZeros; // performs zero-cost replacement + int fPower; // enables power-aware rewriting int fVerbose; // enables verbose output int fVeryVerbose; // enables very verbose output }; @@ -92,8 +93,8 @@ extern int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) /*=== darScript.c ========================================================*/ extern Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig ); extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ); -extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); -extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fVerbose ); +extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ); +extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); #ifdef __cplusplus diff --git a/src/aig/dar/darCore.c b/src/aig/dar/darCore.c index 3916a0b0..957b4cc9 100644 --- a/src/aig/dar/darCore.c +++ b/src/aig/dar/darCore.c @@ -47,6 +47,7 @@ void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ) pPars->fFanout = 1; pPars->fUpdateLevel = 0; pPars->fUseZeros = 0; + pPars->fPower = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } @@ -64,6 +65,7 @@ void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ) ***********************************************************************/ int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) { + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Dar_Man_t * p; // Bar_Progress_t * pProgress; Dar_Cut_t * pCut; @@ -74,6 +76,8 @@ int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) Dar_LibPrepare( pPars->nSubgMax ); // create rewriting manager p = Dar_ManStart( pAig, pPars ); + if ( pPars->fPower ) + pAig->vProbs = Saig_ManComputeSwitchProbs( pAig, 48, 16, 1 ); // remove dangling nodes Aig_ManCleanup( pAig ); // if updating levels is requested, start fanout and timing @@ -182,6 +186,11 @@ p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; // Aig_ManVerifyReverseLevel( pAig ); Aig_ManStopReverseLevels( pAig ); } + if ( pAig->vProbs ) + { + Vec_IntFree( pAig->vProbs ); + pAig->vProbs = NULL; + } // stop the rewriting manager Dar_ManStop( p ); Aig_ManCheckPhase( pAig ); diff --git a/src/aig/dar/darLib.c b/src/aig/dar/darLib.c index b3cf1438..24693df2 100644 --- a/src/aig/dar/darLib.c +++ b/src/aig/dar/darLib.c @@ -44,6 +44,7 @@ struct Dar_LibDat_t_ // library object data Aig_Obj_t * pFunc; // the corresponding AIG node if it exists int Level; // level of this node after it is constructured int TravId; // traversal ID of the library object data + float dProb; // probability of the node being 1 unsigned char fMffc; // set to one if node is part of MFFC unsigned char nLats[3]; // the number of latches on the input/output stem }; @@ -698,6 +699,12 @@ int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut ) pFanin = Aig_NotCond(pFanin, ((uPhase >> i) & 1) ); s_DarLib->pDatas[i].pFunc = pFanin; s_DarLib->pDatas[i].Level = Aig_Regular(pFanin)->Level; + // copy the propability of node being one + if ( p->pPars->fPower ) + { + float Prob = Aig_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pFanin)) ) ); + s_DarLib->pDatas[i].dProb = Aig_IsComplement(pFanin)? 1.0-Prob : Prob; + } } p->nCutsGood++; return 1; @@ -716,14 +723,14 @@ int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut ) SeeAlso [] ***********************************************************************/ -int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves ) +int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves, float * pPower ) { int i, nNodes; // mark the cut leaves for ( i = 0; i < nLeaves; i++ ) Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs++; // label MFFC with current ID - nNodes = Aig_NodeMffsLabel( p, pRoot ); + nNodes = Aig_NodeMffsLabel( p, pRoot, pPower ); // unmark the cut leaves for ( i = 0; i < nLeaves; i++ ) Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs--; @@ -821,10 +828,13 @@ void Dar_LibEvalAssignNums( Dar_Man_t * p, int Class, Aig_Obj_t * pRoot ) SeeAlso [] ***********************************************************************/ -int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required ) +int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required, float * pPower ) { + float Power0, Power1; Dar_LibDat_t * pData; int Area; + if ( pPower ) + *pPower = (float)0.0; if ( pObj->fTerm ) return 0; assert( pObj->Num > 3 ); @@ -838,12 +848,21 @@ int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required pData->TravId = Out; // this is a new node - get a bound on the area of its branches nNodesSaved--; - Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1 ); + Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1, pPower? &Power0 : NULL ); if ( Area > nNodesSaved ) return 0xff; - Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1 ); + Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1, pPower? &Power1 : NULL ); if ( Area > nNodesSaved ) return 0xff; + if ( pPower ) + { + Dar_LibDat_t * pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num; + Dar_LibDat_t * pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num; + pData->dProb = (pObj->fCompl0? 1.0 - pData0->dProb : pData0->dProb)* + (pObj->fCompl1? 1.0 - pData1->dProb : pData1->dProb); + *pPower = Power0 + 2.0 * pData0->dProb * (1.0 - pData0->dProb) + + Power1 + 2.0 * pData1->dProb * (1.0 - pData1->dProb); + } return Area + 1; } @@ -861,6 +880,7 @@ int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required ) { int fTraining = 0; + float PowerSaved, PowerAdded; Dar_LibObj_t * pObj; int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained, clk; clk = clock(); @@ -870,7 +890,7 @@ void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Requir if ( !Dar_LibCutMatch(p, pCut) ) return; // mark MFFC of the node - nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves ); + nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves, p->pPars->fPower? &PowerSaved : NULL ); // evaluate the cut Class = s_DarLib->pMap[pCut->uTruth]; Dar_LibEvalAssignNums( p, Class, pRoot ); @@ -882,8 +902,10 @@ void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Requir pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]); if ( Aig_Regular(s_DarLib->pDatas[pObj->Num].pFunc) == pRoot ) continue; - nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required ); + nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required, p->pPars->fPower? &PowerAdded : NULL ); nNodesGained = nNodesSaved - nNodesAdded; + if ( p->pPars->fPower && PowerSaved < PowerAdded ) + continue; if ( fTraining && nNodesGained >= 0 ) Dar_LibIncrementScore( Class, Out, nNodesGained + 1 ); if ( nNodesGained < 0 || (nNodesGained == 0 && !p->pPars->fUseZeros) ) diff --git a/src/aig/dar/darRefact.c b/src/aig/dar/darRefact.c index d19d48e4..ecf032be 100644 --- a/src/aig/dar/darRefact.c +++ b/src/aig/dar/darRefact.c @@ -235,7 +235,7 @@ int Dar_RefactTryGraph( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Ptr_t * vCut, K { pNode->pFunc = Vec_PtrEntry(vCut, i); pNode->Level = Aig_Regular(pNode->pFunc)->Level; - assert( Aig_Regular(pNode->pFunc)->Level < (1<<14)-1 ); + assert( Aig_Regular(pNode->pFunc)->Level < (1<<24)-1 ); } //printf( "Trying:\n" ); // compute the AIG size after adding the internal nodes diff --git a/src/aig/dar/darScript.c b/src/aig/dar/darScript.c index d82239f8..6df776e6 100644 --- a/src/aig/dar/darScript.c +++ b/src/aig/dar/darScript.c @@ -153,7 +153,7 @@ void Dar_ManHaigPrintStats( Aig_Man_t * pAig ) SeeAlso [] ***********************************************************************/ -Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) +Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ) //alias compress2 "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" { Aig_Man_t * pTemp; @@ -167,6 +167,8 @@ Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, i pParsRwr->fUpdateLevel = fUpdateLevel; pParsRef->fUpdateLevel = fUpdateLevel; + pParsRwr->fPower = fPower; + pParsRwr->fVerbose = 0;//fVerbose; pParsRef->fVerbose = 0;//fVerbose; @@ -224,7 +226,7 @@ Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, i SeeAlso [] ***********************************************************************/ -Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fVerbose ) +Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ) //alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" { Aig_Man_t * pTemp; @@ -238,6 +240,7 @@ Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, pParsRwr->fUpdateLevel = fUpdateLevel; pParsRef->fUpdateLevel = fUpdateLevel; pParsRwr->fFanout = fFanout; + pParsRwr->fPower = fPower; pParsRwr->fVerbose = 0;//fVerbose; pParsRef->fVerbose = 0;//fVerbose; @@ -329,7 +332,7 @@ Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) +Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ) //alias resyn "b; rw; rwz; b; rwz; b" //alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" { @@ -344,7 +347,7 @@ Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateL Aig_ManForEachObj( pAig, pObj, i ) pObj->pHaig = pObj; - pAig = Dar_ManCompress (pAig, fBalance, fUpdateLevel, fVerbose); + pAig = Dar_ManCompress(pAig, fBalance, fUpdateLevel, fPower, fVerbose); Vec_PtrPush( vAigs, pAig ); //Aig_ManPrintStats( pAig ); @@ -354,7 +357,7 @@ Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateL pObj->pHaig = pObj; } - pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, 1, fVerbose); + pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose); Vec_PtrPush( vAigs, pAig ); //Aig_ManPrintStats( pAig ); @@ -384,7 +387,7 @@ Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int clk = clock(); // vAigs = Dar_ManChoiceSynthesisExt(); - vAigs = Dar_ManChoiceSynthesis( pAig, fBalance, fUpdateLevel, fVerbose ); + vAigs = Dar_ManChoiceSynthesis( pAig, fBalance, fUpdateLevel, 0, fVerbose ); // swap the first and last network // this should lead to the primary choice being "better" because of synthesis @@ -441,7 +444,7 @@ Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) clk = clock(); // vAigs = Dar_ManChoiceSynthesisExt(); - vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, fVerbose ); + vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose ); // swap the first and last network // this should lead to the primary choice being "better" because of synthesis diff --git a/src/aig/dch/dch.h b/src/aig/dch/dch.h index f1718a78..d0092a5f 100644 --- a/src/aig/dch/dch.h +++ b/src/aig/dch/dch.h @@ -47,6 +47,7 @@ struct Dch_Pars_t_ int fSynthesis; // set to 1 to perform synthesis int fPolarFlip; // uses polarity adjustment int fSimulateTfo; // uses simulatin of TFO classes + int fPower; // uses power-aware rewriting int fVerbose; // verbose stats int timeSynth; // synthesis runtime int nNodesAhead; // the lookahead in terms of nodes diff --git a/src/aig/dch/dchCore.c b/src/aig/dch/dchCore.c index 76813d1a..27c039cf 100644 --- a/src/aig/dch/dchCore.c +++ b/src/aig/dch/dchCore.c @@ -48,6 +48,7 @@ void Dch_ManSetDefaultParams( Dch_Pars_t * p ) p->fSynthesis = 1; // derives three snapshots p->fPolarFlip = 1; // uses polarity adjustment p->fSimulateTfo = 1; // simulate TFO + p->fPower = 0; // power-aware rewriting p->fVerbose = 0; // verbose stats p->nNodesAhead = 1000; // the lookahead in terms of nodes p->nCallsRecycle = 100; // calls to perform before recycling SAT solver diff --git a/src/aig/fra/fraSec.c b/src/aig/fra/fraSec.c index ca73b17d..7545059f 100644 --- a/src/aig/fra/fraSec.c +++ b/src/aig/fra/fraSec.c @@ -404,7 +404,7 @@ clk = clock(); pNew = Aig_ManDupOrdered( pTemp = pNew ); Aig_ManStop( pTemp ); // pNew = Dar_ManRewriteDefault( pTemp = pNew ); - pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0 ); + pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { diff --git a/src/aig/fsim/fsim.h b/src/aig/fsim/fsim.h new file mode 100644 index 00000000..c890ff29 --- /dev/null +++ b/src/aig/fsim/fsim.h @@ -0,0 +1,97 @@ +/**CFile**************************************************************** + + FileName [fsim.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __FSIM_H__ +#define __FSIM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fsim_Man_t_ Fsim_Man_t; + +// simulation parameters +typedef struct Fsim_ParSim_t_ Fsim_ParSim_t; +struct Fsim_ParSim_t_ +{ + // user-controlled parameters + int nWords; // the number of machine words + int nIters; // the number of timeframes + int TimeLimit; // time limit in seconds + int fCheckMiter; // check if miter outputs are non-zero + int fVerbose; // enables verbose output + // internal parameters + int fCompressAig; // compresses internal data +}; + +// switching estimation parameters +typedef struct Fsim_ParSwitch_t_ Fsim_ParSwitch_t; +struct Fsim_ParSwitch_t_ +{ + // user-controlled parameters + int nWords; // the number of machine words + int nIters; // the number of timeframes + int nPref; // the number of first timeframes to skip + int nRandPiNum; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc) + int fProbOne; // collect probability of one + int fProbTrans; // collect probatility of switching + int fVerbose; // enables verbose output +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fsimCore.c ==========================================================*/ +extern void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p ); +extern void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p ); +/*=== fsimSim.c ==========================================================*/ +extern int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars ); +/*=== fsimSwitch.c ==========================================================*/ +extern Vec_Int_t * Fsim_ManSwitchSimulate( Aig_Man_t * pAig, Fsim_ParSwitch_t * pPars ); +/*=== fsimTsim.c ==========================================================*/ +extern Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/fsim/fsimCore.c b/src/aig/fsim/fsimCore.c new file mode 100644 index 00000000..2a159cbe --- /dev/null +++ b/src/aig/fsim/fsimCore.c @@ -0,0 +1,83 @@ +/**CFile**************************************************************** + + FileName [fsimCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Core procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p ) +{ + memset( p, 0, sizeof(Fsim_ParSim_t) ); + // user-controlled parameters + p->nWords = 8; // the number of machine words + p->nIters = 32; // the number of timeframes + p->TimeLimit = 60; // time limit in seconds + p->fCheckMiter = 0; // check if miter outputs are non-zero + p->fVerbose = 1; // enables verbose output + // internal parameters + p->fCompressAig = 0; // compresses internal data +} + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p ) +{ + memset( p, 0, sizeof(Fsim_ParSwitch_t) ); + // user-controlled parameters + p->nWords = 1; // the number of machine words + p->nIters = 48; // the number of timeframes + p->nPref = 16; // the number of first timeframes to skip + p->nRandPiNum = 0; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc) + p->fProbOne = 1; // collect probability of one + p->fProbTrans = 1; // collect probatility of switching + p->fVerbose = 1; // enables verbose output +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/fsim/fsimFront.c b/src/aig/fsim/fsimFront.c new file mode 100644 index 00000000..d40b1c6f --- /dev/null +++ b/src/aig/fsim/fsimFront.c @@ -0,0 +1,364 @@ +/**CFile**************************************************************** + + FileName [fsimFront.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Simulation frontier.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManStoreNum( Fsim_Man_t * p, int Num ) +{ + unsigned x = (unsigned)Num; + assert( Num >= 0 ); + while ( x & ~0x7f ) + { + *p->pDataCur++ = (x & 0x7f) | 0x80; + x >>= 7; + } + *p->pDataCur++ = x; + assert( p->pDataCur - p->pDataAig < p->nDataAig ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManRestoreNum( Fsim_Man_t * p ) +{ + int ch, i, x = 0; + for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ ) + x |= (ch & 0x7f) << (7 * i); + assert( p->pDataCur - p->pDataAig < p->nDataAig ); + return x | (ch << (7 * i)); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManStoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) +{ + if ( p->pDataAig2 ) + { + *p->pDataCur2++ = pObj->iNode; + *p->pDataCur2++ = pObj->iFan0; + *p->pDataCur2++ = pObj->iFan1; + return; + } + if ( pObj->iFan0 && pObj->iFan1 ) // and + { + assert( pObj->iNode ); + assert( pObj->iNode >= p->iNodePrev ); + assert( (pObj->iNode << 1) > pObj->iFan0 ); + assert( pObj->iFan0 > pObj->iFan1 ); + Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 3 ); + Fsim_ManStoreNum( p, (pObj->iNode << 1) - pObj->iFan0 ); + Fsim_ManStoreNum( p, pObj->iFan0 - pObj->iFan1 ); + p->iNodePrev = pObj->iNode; + } + else if ( !pObj->iFan0 && !pObj->iFan1 ) // ci + { + assert( pObj->iNode ); + assert( pObj->iNode >= p->iNodePrev ); + Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 1 ); + p->iNodePrev = pObj->iNode; + } + else // if ( !pObj->iFan0 && pObj->iFan1 ) // co + { + assert( pObj->iNode == 0 ); + assert( pObj->iFan0 != 0 ); + assert( pObj->iFan1 == 0 ); + assert( ((p->iNodePrev << 1) | 1) >= pObj->iFan0 ); + Fsim_ManStoreNum( p, (((p->iNodePrev << 1) | 1) - pObj->iFan0) << 1 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) +{ + int iValue = Fsim_ManRestoreNum( p ); + if ( (iValue & 3) == 3 ) // and + { + pObj->iNode = (iValue >> 2) + p->iNodePrev; + pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p ); + pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p ); + p->iNodePrev = pObj->iNode; + } + else if ( (iValue & 3) == 1 ) // ci + { + pObj->iNode = (iValue >> 2) + p->iNodePrev; + pObj->iFan0 = 0; + pObj->iFan1 = 0; + p->iNodePrev = pObj->iNode; + } + else // if ( (iValue & 1) == 0 ) // co + { + pObj->iNode = 0; + pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1); + pObj->iFan1 = 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Determine the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManFrontFindNext( Fsim_Man_t * p, char * pFront ) +{ + assert( p->iNumber < (1 << 30) - p->nFront ); + while ( 1 ) + { + if ( p->iNumber % p->nFront == 0 ) + p->iNumber++; + if ( pFront[p->iNumber % p->nFront] == 0 ) + { + pFront[p->iNumber % p->nFront] = 1; + return p->iNumber; + } + p->iNumber++; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Verifies the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManVerifyFront( Fsim_Man_t * p ) +{ + Fsim_Obj_t * pObj; + int * pFans0, * pFans1; // representation of fanins + int * pFrontToId; // mapping of nodes into frontier variables + int i, iVar0, iVar1; + pFans0 = ALLOC( int, p->nObjs ); + pFans1 = ALLOC( int, p->nObjs ); + pFans0[0] = pFans1[0] = 0; + pFans0[1] = pFans1[1] = 0; + pFrontToId = CALLOC( int, p->nFront ); + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + pFrontToId[1] = 1; + Fsim_ManForEachObj( p, pObj, i ) + { + if ( pObj->iNode ) + pFrontToId[pObj->iNode % p->nFront] = i; + iVar0 = Fsim_Lit2Var(pObj->iFan0); + iVar1 = Fsim_Lit2Var(pObj->iFan1); + pFans0[i] = Fsim_Var2Lit(pFrontToId[iVar0 % p->nFront], Fsim_LitIsCompl(pObj->iFan0)); + pFans1[i] = Fsim_Var2Lit(pFrontToId[iVar1 % p->nFront], Fsim_LitIsCompl(pObj->iFan1)); + } + for ( i = 0; i < p->nObjs; i++ ) + { + assert( pFans0[i] == p->pFans0[i] ); + assert( pFans1[i] == p->pFans1[i] ); + } + free( pFrontToId ); + free( pFans0 ); + free( pFans1 ); +} + +/**Function************************************************************* + + Synopsis [Determine the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig ) +{ + Fsim_Obj_t Obj, * pObj = &Obj; + char * pFront; // places used for the frontier + int * pIdToFront; // mapping of nodes into frontier places + int i, iVar0, iVar1, nCrossCut = 0, nCrossCutMax = 0; + // start the frontier + pFront = CALLOC( char, p->nFront ); + pIdToFront = ALLOC( int, p->nObjs ); + pIdToFront[0] = -1; + pIdToFront[1] = -1; + // add constant node + p->iNumber = 1; + if ( p->pRefs[1] ) + { + pIdToFront[1] = Fsim_ManFrontFindNext( p, pFront ); + nCrossCut = 1; + } + // allocate room for data + if ( fCompressAig ) + { + p->nDataAig = p->nObjs * 6; + p->pDataAig = ALLOC( unsigned char, p->nDataAig ); + p->pDataCur = p->pDataAig; + p->iNodePrev = 0; + } + else + { + p->pDataAig2 = ALLOC( int, 3 * p->nObjs ); + p->pDataCur2 = p->pDataAig2 + 6; + } + // iterate through the objects + for ( i = 2; i < p->nObjs; i++ ) + { + if ( p->pFans0[i] == 0 ) // ci + { + // store node + pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront ); + pObj->iNode = pIdToFront[i]; + pObj->iFan0 = 0; + pObj->iFan1 = 0; + Fsim_ManStoreObj( p, pObj ); + // handle CIs without fanout + if ( p->pRefs[i] == 0 ) + { + pFront[pIdToFront[i] % p->nFront] = 0; + pIdToFront[i] = -1; + } + } + else if ( p->pFans1[i] == 0 ) // co + { + assert( p->pRefs[i] == 0 ); + // get the fanin + iVar0 = Fsim_Lit2Var(p->pFans0[i]); + assert( pIdToFront[iVar0] > 0 ); + // store node + pObj->iNode = 0; + pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i])); + pObj->iFan1 = 0; + Fsim_ManStoreObj( p, pObj ); + // deref the fanin + if ( --p->pRefs[iVar0] == 0 ) + { + pFront[pIdToFront[iVar0] % p->nFront] = 0; + pIdToFront[iVar0] = -1; + nCrossCut--; + } + } + else + { + // get the fanins + iVar0 = Fsim_Lit2Var(p->pFans0[i]); + assert( pIdToFront[iVar0] > 0 ); + iVar1 = Fsim_Lit2Var(p->pFans1[i]); + assert( pIdToFront[iVar1] > 0 ); + // store node + pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront ); + pObj->iNode = pIdToFront[i]; + pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i])); + pObj->iFan1 = Fsim_Var2Lit(pIdToFront[iVar1], Fsim_LitIsCompl(p->pFans1[i])); + Fsim_ManStoreObj( p, pObj ); + // deref the fanins + if ( --p->pRefs[iVar0] == 0 ) + { + pFront[pIdToFront[iVar0] % p->nFront] = 0; + pIdToFront[iVar0] = -1; + nCrossCut--; + } + if ( --p->pRefs[iVar1] == 0 ) + { + pFront[pIdToFront[iVar1] % p->nFront] = 0; + pIdToFront[iVar1] = -1; + nCrossCut--; + } + // handle nodes without fanout (choice nodes) + if ( p->pRefs[i] == 0 ) + { + pFront[pIdToFront[i] % p->nFront] = 0; + pIdToFront[i] = -1; + } + } + if ( p->pRefs[i] ) + if ( nCrossCutMax < ++nCrossCut ) + nCrossCutMax = nCrossCut; + } + assert( p->pDataAig2 == NULL || p->pDataCur2 - p->pDataAig2 == (3 * p->nObjs) ); + assert( nCrossCut == 0 ); + assert( nCrossCutMax == p->nCrossCutMax ); + for ( i = 0; i < p->nFront; i++ ) + assert( pFront[i] == 0 ); + free( pFront ); + free( pIdToFront ); +// Fsim_ManVerifyFront( p ); + FREE( p->pFans0 ); + FREE( p->pFans1 ); + FREE( p->pRefs ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/fsim/fsimInt.h b/src/aig/fsim/fsimInt.h new file mode 100644 index 00000000..0944bf0c --- /dev/null +++ b/src/aig/fsim/fsimInt.h @@ -0,0 +1,134 @@ +/**CFile**************************************************************** + + FileName [fsimInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __FSIM_INT_H__ +#define __FSIM_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "saig.h" +#include "fsim.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// simulation object +typedef struct Fsim_Obj_t_ Fsim_Obj_t; +struct Fsim_Obj_t_ +{ + int iNode; // the node ID + int iFan0; // the first fanin + int iFan1; // the second fanin +}; + +// fast sequential simulation manager +struct Fsim_Man_t_ +{ + // parameters + Aig_Man_t * pAig; // the AIG to be used for simulation + int nWords; // the number of simulation words + // AIG representation + int nPis; // the number of primary inputs + int nPos; // the number of primary outputs + int nCis; // the number of combinational inputs + int nCos; // the number of combinational outputs + int nNodes; // the number of internal nodes + int nObjs; // nCis + nNodes + nCos + 2 + int * pFans0; // fanin0 for all objects + int * pFans1; // fanin1 for all objects + int * pRefs; // reference counter for each node + int * pRefsCopy; // reference counter for each node + Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids + Vec_Int_t * vLos; // register outputs + Vec_Int_t * vLis; // register inputs + // cross-cut representation + int nCrossCut; // temporary cross-cut variable + int nCrossCutMax; // maximum cross-cut variable + int nFront; // the size of frontier + // derived AIG representation + int nDataAig; // the length of allocated data + unsigned char * pDataAig; // AIG representation + unsigned char * pDataCur; // AIG representation (current position) + int iNodePrev; // previous extracted value + int iNumber; // the number of the last object + Fsim_Obj_t Obj; // current object + // temporary AIG representation + int * pDataAig2; // temporary representation + int * pDataCur2; // AIG representation (current position) + // simulation information + unsigned * pDataSim; // simulation data + unsigned * pDataSimCis; // simulation data for CIs + unsigned * pDataSimCos; // simulation data for COs + // other information + int * pData1; + int * pData2; +}; + +static inline unsigned * Fsim_SimData( Fsim_Man_t * p, int i ) { return p->pDataSim + i * p->nWords; } +static inline unsigned * Fsim_SimDataCi( Fsim_Man_t * p, int i ) { return p->pDataSimCis + i * p->nWords; } +static inline unsigned * Fsim_SimDataCo( Fsim_Man_t * p, int i ) { return p->pDataSimCos + i * p->nWords; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Fsim_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Fsim_Lit2Var( int Lit ) { return Lit >> 1; } +static inline int Fsim_LitIsCompl( int Lit ) { return Lit & 1; } +static inline int Fsim_LitNot( int Lit ) { return Lit ^ 1; } +static inline int Fsim_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Fsim_LitRegular( int Lit ) { return Lit & ~01; } + +#define Fsim_ManForEachObj( p, pObj, i )\ + for ( i = 2, p->pDataCur = p->pDataAig, p->iNodePrev = 0, pObj = &p->Obj;\ + i < p->nObjs && Fsim_ManRestoreObj( p, pObj ); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fsimFront.c ========================================================*/ +extern void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig ); +/*=== fsimMan.c ==========================================================*/ +extern Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig ); +extern void Fsim_ManDelete( Fsim_Man_t * p ); +extern void Fsim_ManTest( Aig_Man_t * pAig ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/fsim/fsimMan.c b/src/aig/fsim/fsimMan.c new file mode 100644 index 00000000..f7a40f40 --- /dev/null +++ b/src/aig/fsim/fsimMan.c @@ -0,0 +1,207 @@ +/**CFile**************************************************************** + + FileName [fsimMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Simulation manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fsim_ManCreate_rec( Fsim_Man_t * p, Aig_Obj_t * pObj ) +{ + int iFan0, iFan1, iTemp; + assert( !Aig_IsComplement(pObj) ); + if ( pObj->iData ) + return pObj->iData; + assert( !Aig_ObjIsConst1(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + { + iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + iFan1 = Fsim_ManCreate_rec( p, Aig_ObjFanin1(pObj) ); + assert( iFan0 != iFan1 ); + if ( --p->pRefs[iFan0] == 0 ) + p->nCrossCut--; + iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) ); + if ( --p->pRefs[iFan1] == 0 ) + p->nCrossCut--; + iFan1 = Fsim_Var2Lit( iFan1, Aig_ObjFaninC1(pObj) ); + if ( p->pAig->pEquivs ) + Fsim_ManCreate_rec( p, Aig_ObjEquiv(p->pAig, pObj) ); + } + else if ( Aig_ObjIsPo(pObj) ) + { + assert( Aig_ObjRefs(pObj) == 0 ); + iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + if ( --p->pRefs[iFan0] == 0 ) + p->nCrossCut--; + iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) ); + iFan1 = 0; + } + else + { + iFan0 = iFan1 = 0; + Vec_IntPush( p->vCis2Ids, Aig_ObjPioNum(pObj) ); + } + if ( iFan0 < iFan1 ) + iTemp = iFan0, iFan0 = iFan1, iFan1 = iTemp; + p->pFans0[p->nObjs] = iFan0; + p->pFans1[p->nObjs] = iFan1; + p->pRefs[p->nObjs] = Aig_ObjRefs(pObj); + if ( p->pRefs[p->nObjs] ) + if ( p->nCrossCutMax < ++p->nCrossCut ) + p->nCrossCutMax = p->nCrossCut; + return pObj->iData = p->nObjs++; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig ) +{ + Fsim_Man_t * p; + Aig_Obj_t * pObj; + int i, nObjs; + Aig_ManCleanData( pAig ); + p = (Fsim_Man_t *)ALLOC( Fsim_Man_t, 1 ); + memset( p, 0, sizeof(Fsim_Man_t) ); + p->pAig = pAig; + p->nPis = Saig_ManPiNum(pAig); + p->nPos = Saig_ManPoNum(pAig); + p->nCis = Aig_ManPiNum(pAig); + p->nCos = Aig_ManPoNum(pAig); + p->nNodes = Aig_ManNodeNum(pAig); + nObjs = p->nCis + p->nCos + p->nNodes + 2; + p->pFans0 = ALLOC( int, nObjs ); + p->pFans1 = ALLOC( int, nObjs ); + p->pRefs = ALLOC( int, nObjs ); + p->vCis2Ids = Vec_IntAlloc( Aig_ManPiNum(pAig) ); + // add objects (0=unused; 1=const1) + p->pFans0[0] = p->pFans1[0] = 0; + p->pFans0[1] = p->pFans1[1] = 0; + p->pRefs[0] = 0; + p->nObjs = 2; + pObj = Aig_ManConst1( pAig ); + pObj->iData = 1; + p->pRefs[1] = Aig_ObjRefs(pObj); + if ( p->pRefs[1] ) + p->nCrossCut = 1; + Aig_ManForEachPi( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) == 0 ) + Fsim_ManCreate_rec( p, pObj ); + Aig_ManForEachPo( pAig, pObj, i ) + Fsim_ManCreate_rec( p, pObj ); + assert( Vec_IntSize(p->vCis2Ids) == Aig_ManPiNum(pAig) ); + assert( p->nObjs == nObjs ); + // check references + assert( p->nCrossCut == 0 ); + Aig_ManForEachObj( pAig, pObj, i ) + { + assert( p->pRefs[pObj->iData] == 0 ); + p->pRefs[pObj->iData] = Aig_ObjRefs(pObj); + } + // collect flop outputs + p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( p->vLos, pObj->iData ); + // collect flop inputs + p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntPush( p->vLis, pObj->iData ); + // determine the frontier size + p->nFront = 1 + (int)(1.1 * p->nCrossCutMax); + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManDelete( Fsim_Man_t * p ) +{ + Vec_IntFree( p->vCis2Ids ); + Vec_IntFree( p->vLos ); + Vec_IntFree( p->vLis ); + FREE( p->pDataAig2 ); + FREE( p->pDataAig ); + FREE( p->pFans0 ); + FREE( p->pFans1 ); + FREE( p->pRefs ); + FREE( p->pDataSim ); + FREE( p->pDataSimCis ); + FREE( p->pDataSimCos ); + FREE( p->pData1 ); + FREE( p->pData2 ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Testing procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManTest( Aig_Man_t * pAig ) +{ + Fsim_Man_t * p; + p = Fsim_ManCreate( pAig ); + Fsim_ManFront( p, 0 ); + Fsim_ManDelete( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/fsim/fsimSim.c b/src/aig/fsim/fsimSim.c new file mode 100644 index 00000000..320c06a9 --- /dev/null +++ b/src/aig/fsim/fsimSim.c @@ -0,0 +1,560 @@ +/**CFile**************************************************************** + + FileName [fsimSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Simulation procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" +#include "ssw.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoRandom( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = Aig_ManRandom( 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoZero( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = 0; +} + +/**Function************************************************************* + + Synopsis [Returns index of the first pattern that failed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManSimInfoIsZero( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + if ( pInfo[w] ) + return 32*(w-1) + Aig_WordFindFirstBit( pInfo[w] ); + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoOne( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoCopy( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) +{ + unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); + unsigned * pInfo0 = Fsim_SimDataCi( p, iCi ); + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) +{ + unsigned * pInfo = Fsim_SimDataCo( p, iCo ); + unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); + int w; + if ( Fsim_LitIsCompl(iFan0) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w]; + else //if ( !Fsim_LitIsCompl(iFan0) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) +{ + unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); + unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); + unsigned * pInfo1 = Fsim_SimData( p, Fsim_Lit2Var(iFan1) % p->nFront ); + int w; + if ( Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else if ( Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + else if ( !Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else //if ( !Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & pInfo1[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoInit( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) ); + else + Fsim_ManSimInfoZero( p, Fsim_SimDataCi(p, i) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimInfoTransfer( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) ); + else + Fsim_ManSimInfoCopy( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManRestoreNum( Fsim_Man_t * p ) +{ + int ch, i, x = 0; + for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ ) + x |= (ch & 0x7f) << (7 * i); + assert( p->pDataCur - p->pDataAig < p->nDataAig ); + return x | (ch << (7 * i)); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) +{ + int iValue = Fsim_ManRestoreNum( p ); + if ( (iValue & 3) == 3 ) // and + { + pObj->iNode = (iValue >> 2) + p->iNodePrev; + pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p ); + pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p ); + p->iNodePrev = pObj->iNode; + } + else if ( (iValue & 3) == 1 ) // ci + { + pObj->iNode = (iValue >> 2) + p->iNodePrev; + pObj->iFan0 = 0; + pObj->iFan1 = 0; + p->iNodePrev = pObj->iNode; + } + else // if ( (iValue & 1) == 0 ) // co + { + pObj->iNode = 0; + pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1); + pObj->iFan1 = 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateRound2( Fsim_Man_t * p ) +{ + Fsim_Obj_t * pObj; + int i, iCis = 0, iCos = 0; + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) ); + Fsim_ManForEachObj( p, pObj, i ) + { + if ( pObj->iFan0 == 0 ) + Fsim_ManSimulateCi( p, pObj->iNode, iCis++ ); + else if ( pObj->iFan1 == 0 ) + Fsim_ManSimulateCo( p, iCos++, pObj->iFan0 ); + else + Fsim_ManSimulateNode( p, pObj->iNode, pObj->iFan0, pObj->iFan1 ); + } + assert( iCis == p->nCis ); + assert( iCos == p->nCos ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSimulateRound( Fsim_Man_t * p ) +{ + int * pCur, * pEnd; + int iCis = 0, iCos = 0; + if ( p->pDataAig2 == NULL ) + { + Fsim_ManSimulateRound2( p ); + return; + } + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) ); + pCur = p->pDataAig2 + 6; + pEnd = p->pDataAig2 + 3 * p->nObjs; + while ( pCur < pEnd ) + { + if ( pCur[1] == 0 ) + Fsim_ManSimulateCi( p, pCur[0], iCis++ ); + else if ( pCur[2] == 0 ) + Fsim_ManSimulateCo( p, iCos++, pCur[1] ); + else + Fsim_ManSimulateNode( p, pCur[0], pCur[1], pCur[2] ); + pCur += 3; + } + assert( iCis == p->nCis ); + assert( iCos == p->nCos ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManSimulateRoundTest( Fsim_Man_t * p ) +{ + Fsim_Obj_t * pObj; + int i, clk = clock(); + Fsim_ManForEachObj( p, pObj, i ) + { + } +// PRT( "Unpacking time", p->pPars->nIters * (clock() - clk) ); +} + +/**Function************************************************************* + + Synopsis [Returns index of the PO and pattern that failed it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManCheckPos( Fsim_Man_t * p, int * piPo, int * piPat ) +{ + int i, iPat; + for ( i = 0; i < p->nPos; i++ ) + { + iPat = Fsim_ManSimInfoIsZero( p, Fsim_SimDataCo(p, i) ); + if ( iPat >= 0 ) + { + *piPo = i; + *piPat = iPat; + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cex_t * Fsim_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids ) +{ + Ssw_Cex_t * p; + unsigned * pData; + int f, i, w, iPioId, Counter; + p = Ssw_SmlAllocCounterExample( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 ); + p->iFrame = iFrame; + p->iPo = iOut; + // fill in the binary data + Aig_ManRandom( 1 ); + Counter = p->nRegs; + pData = ALLOC( unsigned, nWords ); + for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) + for ( i = 0; i < Aig_ManPiNum(pAig); i++ ) + { + iPioId = Vec_IntEntry( vCis2Ids, i ); + if ( iPioId >= p->nPis ) + continue; + for ( w = nWords-1; w >= 0; w-- ) + pData[w] = Aig_ManRandom( 0 ); + if ( Aig_InfoHasBit( pData, iPat ) ) + Aig_InfoSetBit( p->pData, Counter + iPioId ); + } + free( pData ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars ) +{ + Fsim_Man_t * p; + Sec_MtrStatus_t Status; + int i, iOut, iPat, clk, clkTotal = clock(), clk2, clk2Total = 0; + assert( Aig_ManRegNum(pAig) > 0 ); + Status = Sec_MiterStatus( pAig ); + if ( Status.nSat > 0 ) + { + printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut ); + return 1; + } + if ( Status.nUndec == 0 ) + { + printf( "Miter is trivially unsatisfiable.\n" ); + return 0; + } + // create manager + clk = clock(); + p = Fsim_ManCreate( pAig ); + p->nWords = pPars->nWords; + if ( pPars->fVerbose ) + { + printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ", + p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, + 4.0*p->nWords*(p->nFront)/(1<<20) ); + PRT( "Time", clock() - clk ); + } + // create simulation frontier + clk = clock(); + Fsim_ManFront( p, pPars->fCompressAig ); + if ( pPars->fVerbose ) + { + printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ", + p->iNumber, Aig_Base2Log(p->iNumber), + 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); + PRT( "Time", clock() - clk ); + } + // perform simulation + Aig_ManRandom( 1 ); + assert( p->pDataSim == NULL ); + p->pDataSim = ALLOC( unsigned, p->nWords * p->nFront * sizeof(unsigned) ); + p->pDataSimCis = ALLOC( unsigned, p->nWords * p->nCis * sizeof(unsigned) ); + p->pDataSimCos = ALLOC( unsigned, p->nWords * p->nCos * sizeof(unsigned) ); + Fsim_ManSimInfoInit( p ); + for ( i = 0; i < pPars->nIters; i++ ) + { + Fsim_ManSimulateRound( p ); + if ( pPars->fVerbose ) + { + printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit ); + printf( "Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC ); + } + if ( pPars->fCheckMiter && Fsim_ManCheckPos( p, &iOut, &iPat ) ) + { + assert( pAig->pSeqModel == NULL ); + pAig->pSeqModel = Fsim_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids ); + if ( pPars->fVerbose ) + printf( "Miter is satisfiable after simulation (output %d).\n", iOut ); + break; + } + if ( (clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit ) + { + printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, pPars->TimeLimit ); + break; + } + clk2 = clock(); + if ( i < pPars->nIters - 1 ) + Fsim_ManSimInfoTransfer( p ); + clk2Total += clock() - clk2; + } + if ( pPars->fVerbose ) + { + printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ", + p->nCrossCutMax, + p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 4.0*p->nWords*(p->nFront+p->nCis+p->nCos)/(1<<20) ); + PRT( "Sim time", clock() - clkTotal ); + +// PRT( "Additional time", clk2Total ); +// Fsim_ManSimulateRoundTest( p ); +// Fsim_ManSimulateRoundTest2( p ); + } + Fsim_ManDelete( p ); + return pAig->pSeqModel != NULL; + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/fsim/fsimSwitch.c b/src/aig/fsim/fsimSwitch.c new file mode 100644 index 00000000..00046af6 --- /dev/null +++ b/src/aig/fsim/fsimSwitch.c @@ -0,0 +1,588 @@ +/**CFile**************************************************************** + + FileName [fsimSwitch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Computing switching activity.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoRandom( Fsim_Man_t * p, unsigned * pInfo, int nProbNum ) +{ + unsigned Mask; + int w, i; + if ( nProbNum ) + { + Mask = Aig_ManRandom( 0 ); + for ( i = 0; i < nProbNum; i++ ) + Mask &= Aig_ManRandom( 0 ); + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] ^= Mask; + } + else + { + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = Aig_ManRandom( 0 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoRandomShift( Fsim_Man_t * p, unsigned * pInfo, int nProbNum ) +{ + unsigned Mask; + int w, i; + Mask = Aig_ManRandom( 0 ); + for ( i = 0; i < nProbNum; i++ ) + Mask &= Aig_ManRandom( 0 ); + if ( p->nWords == 1 ) + pInfo[0] = (pInfo[0] << 16) | ((pInfo[0] ^ Mask) & 0xffff); + else + { + assert( (p->nWords & 1) == 0 ); // should be even number + for ( w = p->nWords-1; w >= 0; w-- ) + if ( w >= p->nWords/2 ) + pInfo[w] = pInfo[w - p->nWords/2]; + else + pInfo[w] ^= Mask; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoZero( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoOne( Fsim_Man_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoCopy( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoCopyShift( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 ) +{ + int w; + if ( p->nWords == 1 ) + pInfo[0] = (pInfo[0] << 16) | (pInfo0[0] & 0xffff); + else + { + assert( (p->nWords & 1) == 0 ); // should be even number + for ( w = p->nWords-1; w >= 0; w-- ) + { + if ( w >= p->nWords/2 ) + pInfo[w] = pInfo[w - p->nWords/2]; + else + pInfo[w] = pInfo0[w]; + } + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) +{ + unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); + unsigned * pInfo0 = Fsim_SimDataCi( p, iCi ); + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) +{ + unsigned * pInfo = Fsim_SimDataCo( p, iCo ); + unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); + int w; + if ( Fsim_LitIsCompl(iFan0) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w]; + else //if ( !Fsim_LitIsCompl(iFan0) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) +{ + unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); + unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); + unsigned * pInfo1 = Fsim_SimData( p, Fsim_Lit2Var(iFan1) % p->nFront ); + int w; + if ( Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else if ( Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + else if ( !Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else //if ( !Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & pInfo1[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoInit( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManSwitchSimInfoRandom( p, Fsim_SimDataCi(p, i), 0 ); + else + Fsim_ManSwitchSimInfoZero( p, Fsim_SimDataCi(p, i) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoTransfer( Fsim_Man_t * p, int nProbNum ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManSwitchSimInfoRandom( p, Fsim_SimDataCi(p, i), nProbNum ); + else + Fsim_ManSwitchSimInfoCopy( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimInfoTransferShift( Fsim_Man_t * p, int nProbNum ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManSwitchSimInfoRandomShift( p, Fsim_SimDataCi(p, i), nProbNum ); + else + Fsim_ManSwitchSimInfoCopyShift( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManSwitchSimInfoCountOnes( Fsim_Man_t * p, int iNode ) +{ + unsigned * pInfo; + int w, Counter = 0; + pInfo = Fsim_SimData( p, iNode % p->nFront ); + for ( w = p->nWords-1; w >= 0; w-- ) + Counter += Aig_WordCountOnes( pInfo[w] ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fsim_ManSwitchSimInfoCountTrans( Fsim_Man_t * p, int iNode ) +{ + unsigned * pInfo; + int w, Counter = 0; + assert( iNode % p->nFront ); + pInfo = Fsim_SimData( p, iNode % p->nFront ); + if ( p->nWords == 1 ) + return Aig_WordCountOnes( (pInfo[0] ^ (pInfo[0] >> 16)) & 0xffff ); + for ( w = p->nWords/2-1; w >= 0; w-- ) + Counter += Aig_WordCountOnes( pInfo[w] ^ pInfo[w + p->nWords/2] ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManSwitchSimulateRound( Fsim_Man_t * p, int fCount ) +{ + int * pCur, * pEnd; + int i, iCis = 0, iCos = 0; + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + Fsim_ManSwitchSimInfoOne( p, Fsim_SimData(p, 1) ); + pCur = p->pDataAig2 + 6; + pEnd = p->pDataAig2 + 3 * p->nObjs; + for ( i = 2; pCur < pEnd; i++ ) + { + if ( pCur[1] == 0 ) + Fsim_ManSwitchSimulateCi( p, pCur[0], iCis++ ); + else if ( pCur[2] == 0 ) + Fsim_ManSwitchSimulateCo( p, iCos++, pCur[1] ); + else + Fsim_ManSwitchSimulateNode( p, pCur[0], pCur[1], pCur[2] ); + if ( fCount && pCur[0] ) + { + if ( p->pData1 ) + p->pData1[i] += Fsim_ManSwitchSimInfoCountOnes( p, pCur[0] ); + if ( p->pData2 ) + p->pData2[i] += Fsim_ManSwitchSimInfoCountTrans( p, pCur[0] ); + } + pCur += 3; + } + assert( iCis == p->nCis ); + assert( iCos == p->nCos ); +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fsim_ManSwitchComputeSwitching( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fsim_ManSwitchComputeProbOne( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)nOnes / nTotal; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Fsim_ManSwitchSimulate( Aig_Man_t * pAig, Fsim_ParSwitch_t * pPars ) +{ + Vec_Int_t * vSwitching; + float * pSwitching; + Aig_Obj_t * pObj; + Fsim_Man_t * p; + int i, clk, clkTotal = clock(); + // create manager + clk = clock(); + p = Fsim_ManCreate( pAig ); + p->nWords = pPars->nWords; + // if the number of words is larger then 1, it should be even + if ( p->nWords > 1 && (p->nWords & 1) ) + p->nWords++; + // print stats + if ( pPars->fVerbose ) + { + printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ", + p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, + 4.0*pPars->nWords*(p->nFront)/(1<<20) ); + PRT( "Time", clock() - clk ); + } + // create simulation frontier + clk = clock(); + Fsim_ManFront( p, 0 ); + if ( pPars->fVerbose ) + { + printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ", + p->iNumber, Aig_Base2Log(p->iNumber), + 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); + PRT( "Time", clock() - clk ); + } + // perform simulation + Aig_ManRandom( 1 ); + assert( p->pDataSim == NULL ); + p->pDataSim = ALLOC( unsigned, pPars->nWords * p->nFront * sizeof(unsigned) ); + p->pDataSimCis = ALLOC( unsigned, pPars->nWords * p->nCis * sizeof(unsigned) ); + p->pDataSimCos = ALLOC( unsigned, pPars->nWords * p->nCos * sizeof(unsigned) ); + if ( pPars->fProbOne ) + p->pData1 = CALLOC( int, p->nObjs * sizeof(int) ); + if ( pPars->fProbTrans ) + p->pData2 = CALLOC( int, p->nObjs * sizeof(int) ); + Fsim_ManSwitchSimInfoInit( p ); + for ( i = 0; i < pPars->nIters; i++ ) + { + Fsim_ManSwitchSimulateRound( p, i >= pPars->nPref ); + if ( i < pPars->nIters - 1 ) + { +// if ( pPars->fProbTrans ) + Fsim_ManSwitchSimInfoTransferShift( p, pPars->nRandPiNum ); +// else +// Fsim_ManSwitchSimInfoTransfer( p, pPars->nRandPiNum ); + } + } + if ( pPars->fVerbose ) + { + printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ", + p->nCrossCutMax, + p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 4.0*pPars->nWords*(p->nFront+p->nCis+p->nCos)/(1<<20) ); + PRT( "Sim time", clock() - clkTotal ); + } + // derive the result + vSwitching = Vec_IntStart( Aig_ManObjNumMax(pAig) ); + pSwitching = (float *)vSwitching->pArray; +/* + if ( pPars->fProbOne && pPars->fProbTrans ) + { + Aig_ManForEachObj( pAig, pObj, i ) +// pSwitching[pObj->Id] = Fsim_ManSwitchComputeSwitching( p->pData1[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref) ); + pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData2[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref)/2 ); + } + else if ( !pPars->fProbOne && pPars->fProbTrans ) + { + Aig_ManForEachObj( pAig, pObj, i ) + pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData2[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref)/2 ); + } + else if ( pPars->fProbOne && !pPars->fProbTrans ) + { + Aig_ManForEachObj( pAig, pObj, i ) + pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData1[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref) ); + } + else + assert( 0 ); +*/ + if ( pPars->fProbOne && !pPars->fProbTrans ) + { + Aig_ManForEachObj( pAig, pObj, i ) + pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData1[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref) ); + } + else if ( !pPars->fProbOne && pPars->fProbTrans ) + { + Aig_ManForEachObj( pAig, pObj, i ) + pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData2[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref)/2 ); + } + else + assert( 0 ); + Fsim_ManDelete( p ); + return vSwitching; + +} + +/**Function************************************************************* + + Synopsis [Computes probability of switching (or of being 1).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManComputeSwitchProbs4( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + Fsim_ParSwitch_t Pars, * pPars = &Pars; + Fsim_ManSetDefaultParamsSwitch( pPars ); + pPars->nWords = 1; + pPars->nIters = nFrames; + pPars->nPref = nPref; + if ( fProbOne ) + { + pPars->fProbOne = 1; + pPars->fProbTrans = 0; + } + else + { + pPars->fProbOne = 0; + pPars->fProbTrans = 1; + } + pPars->fVerbose = 0; + return Fsim_ManSwitchSimulate( p, pPars ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/fsim/fsimTsim.c b/src/aig/fsim/fsimTsim.c new file mode 100644 index 00000000..963d7581 --- /dev/null +++ b/src/aig/fsim/fsimTsim.c @@ -0,0 +1,410 @@ +/**CFile**************************************************************** + + FileName [fsimTsim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast sequential AIG simulator.] + + Synopsis [Varius utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: fsimTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fsimInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define FSIM_ZER 1 +#define FSIM_ONE 2 +#define FSIM_UND 3 + +static inline int Aig_XsimNotCond( int Value, int fCompl ) +{ + if ( Value == FSIM_UND ) + return FSIM_UND; + if ( Value == FSIM_ZER + fCompl ) + return FSIM_ZER; + return FSIM_ONE; +} +static inline int Aig_XsimAndCond( int Value0, int Value1, int fCompl0, int fCompl1 ) +{ + if ( Value0 == FSIM_UND || Value1 == FSIM_UND ) + return FSIM_UND; + if ( Value0 == FSIM_ZER + fCompl0 || Value1 == FSIM_ZER + fCompl1 ) + return FSIM_ZER; + return FSIM_ONE; +} + +static inline int Fsim_ManTerSimInfoGet( unsigned * pInfo, int i ) +{ + return 3 & (pInfo[i >> 4] >> ((i & 15) << 1)); +} +static inline void Fsim_ManTerSimInfoSet( unsigned * pInfo, int i, int Value ) +{ + assert( Value >= FSIM_ZER && Value <= FSIM_UND ); + Value ^= Fsim_ManTerSimInfoGet( pInfo, i ); + pInfo[i >> 4] ^= (Value << ((i & 15) << 1)); +} + +static inline unsigned * Fsim_ManTerStateNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } +static inline void Fsim_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) +{ + Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Fsim_ManTerSimInfoGet(p->pDataSimCis, iCi) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) +{ + int Value = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) ); + Fsim_ManTerSimInfoSet( p->pDataSimCos, iCo, Aig_XsimNotCond( Value, Fsim_LitIsCompl(iFan0) ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) +{ + int Value0 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) ); + int Value1 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan1) ); + Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Aig_XsimAndCond( Value0, Value1, Fsim_LitIsCompl(iFan0), Fsim_LitIsCompl(iFan1) ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimInfoInit( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND ); + else + Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_ZER ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimInfoTransfer( Fsim_Man_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND ); + else + Fsim_ManTerSimInfoSet( p->pDataSimCis, i, Fsim_ManTerSimInfoGet( p->pDataSimCos, p->nPos+iPioNum-p->nPis ) ); + } +} + + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fsim_ManTerStateHash( unsigned * pState, int nWords, int nTableSize ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned uHash; + int i; + uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pState[i] * s_FPrimes[i & 0x7F]; + return uHash % nTableSize; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fsim_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) +{ + unsigned * pEntry; + int Hash; + Hash = Fsim_ManTerStateHash( pState, nWords, nBins ); + for ( pEntry = pBins[Hash]; pEntry; pEntry = Fsim_ManTerStateNext(pEntry, nWords) ) + if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) +{ + int Hash = Fsim_ManTerStateHash( pState, nWords, nBins ); + assert( !Fsim_ManTerStateLookup( pState, nWords, pBins, nBins ) ); + Fsim_ManTerStateSetNext( pState, nWords, pBins[Hash] ); + pBins[Hash] = pState; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Fsim_ManTerStateCreate( unsigned * pInfo, int nPis, int nCis, int nWords ) +{ + unsigned * pRes; + int i; + pRes = (unsigned *)CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) ); + for ( i = nPis; i < nCis; i++ ) + Fsim_ManTerSimInfoSet( pRes, i-nPis, Fsim_ManTerSimInfoGet(pInfo, i) ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fsim_ManTerStatePrint( unsigned * pState, int nRegs ) +{ + int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; + for ( i = 0; i < nRegs; i++ ) + { + Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + if ( Value == 1 ) + printf( "0" ), nZeros++; + else if ( Value == 2 ) + printf( "1" ), nOnes++; + else if ( Value == 3 ) + printf( "x" ), nDcs++; + else + assert( 0 ); + } + printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fsim_ManTerSimulateRound( Fsim_Man_t * p ) +{ + int * pCur, * pEnd; + int iCis = 0, iCos = 0; + if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) + Fsim_ManTerSimInfoSet( p->pDataSimCis, 1, FSIM_ONE ); + pCur = p->pDataAig2 + 6; + pEnd = p->pDataAig2 + 3 * p->nObjs; + while ( pCur < pEnd ) + { + if ( pCur[1] == 0 ) + Fsim_ManTerSimulateCi( p, pCur[0], iCis++ ); + else if ( pCur[2] == 0 ) + Fsim_ManTerSimulateCo( p, iCos++, pCur[1] ); + else + Fsim_ManTerSimulateNode( p, pCur[0], pCur[1], pCur[2] ); + pCur += 3; + } + assert( iCis == p->nCis ); + assert( iCos == p->nCos ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose ) +{ + Fsim_Man_t * p; + Vec_Ptr_t * vStates; + unsigned ** pBins, * pState; + int i, nWords, nBins, clk, clkTotal = clock(); + assert( Aig_ManRegNum(pAig) > 0 ); + // create manager + clk = clock(); + p = Fsim_ManCreate( pAig ); + if ( fVerbose ) + { + printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ", + p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, + 4.0*Aig_BitWordNum(2 * p->nFront)/(1<<20) ); + PRT( "Time", clock() - clk ); + } + // create simulation frontier + clk = clock(); + Fsim_ManFront( p, 0 ); + if ( fVerbose ) + { + printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ", + p->iNumber, Aig_Base2Log(p->iNumber), + 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); + PRT( "Time", clock() - clk ); + } + // allocate storage for terminary states + nWords = Aig_BitWordNum( 2*Aig_ManRegNum(pAig) ); + vStates = Vec_PtrAlloc( 1000 ); + nBins = Aig_PrimeCudd( 500 ); + pBins = ALLOC( unsigned *, nBins ); + memset( pBins, 0, sizeof(unsigned *) * nBins ); + // perform simulation + assert( p->pDataSim == NULL ); + p->pDataSim = ALLOC( unsigned, Aig_BitWordNum(2 * p->nFront) * sizeof(unsigned) ); + p->pDataSimCis = ALLOC( unsigned, Aig_BitWordNum(2 * p->nCis) * sizeof(unsigned) ); + p->pDataSimCos = ALLOC( unsigned, Aig_BitWordNum(2 * p->nCos) * sizeof(unsigned) ); + Fsim_ManTerSimInfoInit( p ); + // hash the first state + pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords ); + Vec_PtrPush( vStates, pState ); + Fsim_ManTerStateInsert( pState, nWords, pBins, nBins ); + // perform simuluation till convergence + for ( i = 0; ; i++ ) + { + Fsim_ManTerSimulateRound( p ); + Fsim_ManTerSimInfoTransfer( p ); + // hash the first state + pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords ); + Vec_PtrPush( vStates, pState ); + if ( Fsim_ManTerStateLookup(pState, nWords, pBins, nBins) ) + break; + Fsim_ManTerStateInsert( pState, nWords, pBins, nBins ); + } + if ( fVerbose ) + { + printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ", + p->nCrossCutMax, + p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), + 4.0*(Aig_BitWordNum(2 * p->nFront)+Aig_BitWordNum(2 * p->nCis)+Aig_BitWordNum(2 * p->nCos))/(1<<20) ); + PRT( "Sim time", clock() - clkTotal ); + } + free( pBins ); + Fsim_ManDelete( p ); + return vStates; + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/fsim/module.make b/src/aig/fsim/module.make new file mode 100644 index 00000000..91c733c3 --- /dev/null +++ b/src/aig/fsim/module.make @@ -0,0 +1,6 @@ +SRC += src/aig/fsim/fsimCore.c \ + src/aig/fsim/fsimFront.c \ + src/aig/fsim/fsimMan.c \ + src/aig/fsim/fsimSim.c \ + src/aig/fsim/fsimSwitch.c \ + src/aig/fsim/fsimTsim.c diff --git a/src/aig/hop/hop.h b/src/aig/hop/hop.h index db4799ca..6ffc4eac 100644 --- a/src/aig/hop/hop.h +++ b/src/aig/hop/hop.h @@ -64,7 +64,10 @@ typedef enum { struct Hop_Obj_t_ // 6 words { void * pData; // misc - Hop_Obj_t * pNext; // strashing table + union { + Hop_Obj_t * pNext; // strashing table + int PioNum; // the number of PI/PO + }; Hop_Obj_t * pFanin0; // fanin Hop_Obj_t * pFanin1; // fanin unsigned int Type : 3; // object type diff --git a/src/aig/hop/hopObj.c b/src/aig/hop/hopObj.c index 69f63ee6..f173248f 100644 --- a/src/aig/hop/hopObj.c +++ b/src/aig/hop/hopObj.c @@ -44,6 +44,7 @@ Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ) Hop_Obj_t * pObj; pObj = Hop_ManFetchMemory( p ); pObj->Type = AIG_PI; + pObj->PioNum = Vec_PtrSize( p->vPis ); Vec_PtrPush( p->vPis, pObj ); p->nObjs[AIG_PI]++; return pObj; diff --git a/src/aig/hop/hopTruth.c b/src/aig/hop/hopTruth.c index 47358715..42ded3ed 100644 --- a/src/aig/hop/hopTruth.c +++ b/src/aig/hop/hopTruth.c @@ -44,6 +44,12 @@ static inline void Hop_ManTruthFill( unsigned * pOut, int nVars ) for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(unsigned)0; } +static inline void Hop_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn[w]; +} //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -155,7 +161,7 @@ unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars vTtElems = NULL; // clear the data fields and set marks - nNodes = Hop_ManConvertAigToTruth_rec1( pRoot ); + nNodes = Hop_ManConvertAigToTruth_rec1( Hop_Regular(pRoot) ); // prepare memory nWords = Hop_TruthWordNum( nVars ); Vec_IntClear( vTruth ); @@ -199,9 +205,11 @@ unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars } } // clear the marks and compute the truth table - pTruth2 = Hop_ManConvertAigToTruth_rec2( pRoot, vTruth, nWords ); + pTruth2 = Hop_ManConvertAigToTruth_rec2( Hop_Regular(pRoot), vTruth, nWords ); // copy the result Hop_ManTruthCopy( pTruth, pTruth2, nVars ); + if ( Hop_IsComplement(pRoot) ) + Hop_ManTruthNot( pTruth, pTruth, nVars ); if ( vTtElems ) Vec_PtrFree( vTtElems ); return pTruth; diff --git a/src/aig/ioa/ioaWriteAig.c b/src/aig/ioa/ioaWriteAig.c index 12de42ad..ec37b40e 100644 --- a/src/aig/ioa/ioaWriteAig.c +++ b/src/aig/ioa/ioaWriteAig.c @@ -258,6 +258,12 @@ void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int unsigned char * pBuffer; unsigned uLit0, uLit1, uLit; + if ( Aig_ManPoNum(pMan) == 0 ) + { + printf( "AIG cannot be written because it has no POs.\n" ); + return; + } + // assert( Aig_ManIsStrash(pMan) ); // start the output stream pFile = fopen( pFileName, "wb" ); diff --git a/src/aig/kit/kit.h b/src/aig/kit/kit.h index 101cf2eb..e8dea11a 100644 --- a/src/aig/kit/kit.h +++ b/src/aig/kit/kit.h @@ -141,14 +141,14 @@ struct Kit_DsdMan_t_ }; #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif static inline int Kit_DsdVar2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } @@ -169,7 +169,9 @@ static inline unsigned Kit_DsdLitSupport( Kit_DsdNtk_t * pNtk, int Lit ) #define Kit_DsdNtkForEachObj( pNtk, pObj, i ) \ for ( i = 0; (i < (pNtk)->nNodes) && ((pObj) = (pNtk)->pNodes[i]); i++ ) #define Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) \ - for ( i = 0; (i < (pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ ) + for ( i = 0; (i < (int)(pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ ) +#define Kit_DsdObjForEachFaninReverse( pNtk, pObj, iLit, i ) \ + for ( i = (int)(pObj)->nFans - 1; (i >= 0) && ((iLit) = (pObj)->pFans[i], 1); i-- ) #define Kit_PlaForEachCube( pSop, nFanins, pCube ) \ for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) @@ -528,6 +530,7 @@ extern Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nD extern void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars ); extern void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk ); extern int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk ); +extern Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk ); extern unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk ); extern unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p ); extern Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p ); @@ -586,6 +589,7 @@ extern void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * /*=== kitTruth.c ==========================================================*/ extern void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start ); extern void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ); +extern void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn ); extern void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ); extern int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ); extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars ); @@ -608,6 +612,7 @@ extern void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int i extern int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ); extern int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ); extern void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ); +extern void Kit_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, short * pStore ); extern void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, short * pStore, unsigned * pAux ); extern unsigned Kit_TruthHash( unsigned * pIn, int nWords ); extern unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ); diff --git a/src/aig/kit/kitDsd.c b/src/aig/kit/kitDsd.c index 8d670419..75358093 100644 --- a/src/aig/kit/kitDsd.c +++ b/src/aig/kit/kitDsd.c @@ -139,9 +139,9 @@ Kit_DsdNtk_t * Kit_DsdNtkAlloc( int nVars ) Kit_DsdNtk_t * pNtk; pNtk = ALLOC( Kit_DsdNtk_t, 1 ); memset( pNtk, 0, sizeof(Kit_DsdNtk_t) ); - pNtk->pNodes = ALLOC( Kit_DsdObj_t *, nVars ); + pNtk->pNodes = ALLOC( Kit_DsdObj_t *, nVars+1 ); pNtk->nVars = nVars; - pNtk->nNodesAlloc = nVars; + pNtk->nNodesAlloc = nVars+1; pNtk->pMem = ALLOC( unsigned, 6 * Kit_TruthWordNum(nVars) ); return pNtk; } @@ -303,10 +303,13 @@ void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk ) ***********************************************************************/ void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ) { - Kit_DsdNtk_t * pTemp; + Kit_DsdNtk_t * pTemp, * pTemp2; pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); - Kit_DsdVerify( pTemp, pTruth, nVars ); - Kit_DsdPrintExpanded( pTemp ); +// Kit_DsdPrintExpanded( pTemp ); + pTemp2 = Kit_DsdExpand( pTemp ); + Kit_DsdPrint( stdout, pTemp2 ); + Kit_DsdVerify( pTemp2, pTruth, nVars ); + Kit_DsdNtkFree( pTemp2 ); Kit_DsdNtkFree( pTemp ); } @@ -392,7 +395,6 @@ unsigned * Kit_DsdTruthComputeNode_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, i pTruthPrime = Kit_DsdObjTruth( pObj ); // get storage for the temporary minterm pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); - // go through the minterms nMints = (1 << pObj->nFans); Kit_TruthClear( pTruthRes, pNtk->nVars ); @@ -406,6 +408,9 @@ unsigned * Kit_DsdTruthComputeNode_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, i Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars ); } */ + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( Kit_DsdLitIsCompl(iLit) ) + Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars ); pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); return pTruthRes; @@ -550,7 +555,6 @@ unsigned * Kit_DsdTruthComputeNodeOne_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk pTruthPrime = Kit_DsdObjTruth( pObj ); // get storage for the temporary minterm pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); - // go through the minterms nMints = (1 << pObj->nFans); Kit_TruthClear( pTruthRes, pNtk->nVars ); @@ -564,6 +568,9 @@ unsigned * Kit_DsdTruthComputeNodeOne_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars ); } */ + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( Kit_DsdLitIsCompl(iLit) ) + Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars ); pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); return pTruthRes; @@ -747,7 +754,6 @@ unsigned * Kit_DsdTruthComputeNodeTwo_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk pTruthPrime = Kit_DsdObjTruth( pObj ); // get storage for the temporary minterm pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); - // go through the minterms nMints = (1 << pObj->nFans); Kit_TruthClear( pTruthRes, pNtk->nVars ); @@ -761,8 +767,11 @@ unsigned * Kit_DsdTruthComputeNodeTwo_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars ); } */ +// Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) +// assert( !Kit_DsdLitIsCompl(iLit) ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - assert( !Kit_DsdLitIsCompl(iLit) ); + if ( Kit_DsdLitIsCompl(iLit) ) + Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars ); pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); return pTruthRes; @@ -957,7 +966,7 @@ int Kit_DsdCountLuts( Kit_DsdNtk_t * pNtk, int nLutSize ) /**Function************************************************************* - Synopsis [Counts the number of blocks of the given number of inputs.] + Synopsis [Returns the size of the largest non-DSD block.] Description [] @@ -980,6 +989,34 @@ int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk ) return nSizeMax; } +/**Function************************************************************* + + Synopsis [Returns the largest non-DSD block.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk ) +{ + Kit_DsdObj_t * pObj, * pObjMax = NULL; + unsigned i, nSizeMax = 0; + Kit_DsdNtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->Type != KIT_DSD_PRIME ) + continue; + if ( nSizeMax < pObj->nFans ) + { + nSizeMax = pObj->nFans; + pObjMax = pObj; + } + } + return pObjMax; +} + /**Function************************************************************* Synopsis [Finds the union of supports of the non-DSD blocks.] @@ -1125,10 +1162,46 @@ int Kit_DsdExpandNode_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit ) Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); } } - // if the incoming phase is complemented, absorb it into the prime node - if ( Kit_DsdLitIsCompl(iLit) ) - Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); - return Kit_DsdVar2Lit( pObjNew->Id, 0 ); + + if ( pObj->nFans == 3 && + (pTruthNew[0] == 0xCACACACA || pTruthNew[0] == 0xC5C5C5C5 || + pTruthNew[0] == 0x3A3A3A3A || pTruthNew[0] == 0x35353535) ) + { + // translate into regular MUXes + if ( pTruthNew[0] == 0xC5C5C5C5 ) + pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]); + else if ( pTruthNew[0] == 0x3A3A3A3A ) + pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]); + else if ( pTruthNew[0] == 0x35353535 ) + { + pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]); + pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]); + } + pTruthNew[0] = 0xCACACACA; + // resolve the complemented control input + if ( Kit_DsdLitIsCompl(pObjNew->pFans[2]) ) + { + unsigned char Temp = pObjNew->pFans[0]; + pObjNew->pFans[0] = pObjNew->pFans[1]; + pObjNew->pFans[1] = Temp; + pObjNew->pFans[2] = Kit_DsdLitNot(pObjNew->pFans[2]); + } + // resolve the complemented true input + if ( Kit_DsdLitIsCompl(pObjNew->pFans[1]) ) + { + iLit = Kit_DsdLitNot(iLit); + pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]); + pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]); + } + return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) ); + } + else + { + // if the incoming phase is complemented, absorb it into the prime node + if ( Kit_DsdLitIsCompl(iLit) ) + Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); + return Kit_DsdVar2Lit( pObjNew->Id, 0 ); + } } /**Function************************************************************* @@ -1834,7 +1907,7 @@ void Kit_DsdDecompose_rec( Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pObj, unsigned uS return; } } -/* + // if all decomposition methods failed and we are still above the limit, perform MUX-decomposition if ( nDecMux > 0 && (int)pObj->nFans > nDecMux ) { @@ -1852,14 +1925,14 @@ void Kit_DsdDecompose_rec( Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pObj, unsigned uS assert( pObj->Type == KIT_DSD_PRIME ); pTruth[0] = 0xCACACACA; pObj->nFans = 3; + pObj->pFans[2] = pObj->pFans[iBestVar]; pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++; pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++; - pObj->pFans[2] = pObj->pFans[iBestVar]; // call recursively Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux ); Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux ); } -*/ + } /**Function************************************************************* @@ -1959,6 +2032,27 @@ Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars ) ***********************************************************************/ Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux ) { +/* + Kit_DsdNtk_t * pNew; + Kit_DsdObj_t * pObjNew; + assert( nVars <= 16 ); + // create a new network + pNew = Kit_DsdNtkAlloc( nVars ); + // consider simple special cases + if ( nVars == 0 ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); + pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, (int)(pTruth[0] == 0) ); + return pNew; + } + if ( nVars == 1 ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); + pObjNew->pFans[0] = Kit_DsdVar2Lit( 0, 0 ); + pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, (int)(pTruth[0] != 0xAAAAAAAA) ); + return pNew; + } +*/ return Kit_DsdDecomposeInt( pTruth, nVars, nDecMux ); } diff --git a/src/aig/kit/kitTruth.c b/src/aig/kit/kitTruth.c index 9ddc7562..3f9188c7 100644 --- a/src/aig/kit/kitTruth.c +++ b/src/aig/kit/kitTruth.c @@ -155,7 +155,7 @@ void Kit_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int of variables is nVars. The total number of variables in nVarsAll. The last argument (Phase) contains shows where the variables should go.] - SideEffects [] + SideEffects [The input truth table is modified.] SeeAlso [] @@ -189,7 +189,7 @@ void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, of variables is nVars. The total number of variables in nVarsAll. The last argument (Phase) contains shows what variables should remain.] - SideEffects [] + SideEffects [The input truth table is modified.] SeeAlso [] @@ -215,6 +215,43 @@ void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, Kit_TruthCopy( pOut, pIn, nVarsAll ); } +/**Function************************************************************* + + Synopsis [Implement give permutation.] + + Description [The input and output truth tables are in pIn/pOut. + The number of variables is nVars. Permutation is in pPerm.] + + SideEffects [The input truth table is modified.] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn ) +{ + int * pTemp; + int i, Temp, fChange, Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { + assert( pPerm[i] != pPerm[i+1] ); + if ( pPerm[i] <= pPerm[i+1] ) + continue; + Counter++; + fChange = 1; + + Temp = pPerm[i]; + pPerm[i] = pPerm[i+1]; + pPerm[i+1] = Temp; + + Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + if ( fReturnIn ^ !(Counter & 1) ) + Kit_TruthCopy( pOut, pIn, nVars ); +} /**Function************************************************************* @@ -1289,6 +1326,60 @@ void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ) } } +/**Function************************************************************* + + Synopsis [Counts the number of 1's in each negative cofactor.] + + Description [The resulting numbers are stored in the array of shorts, + whose length is nVars. The number of 1's is counted in a different + space than the original function. For example, if the function depends + on k variables, the cofactors are assumed to depend on k-1 variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, short * pStore ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Counter; + memset( pStore, 0, sizeof(short) * nVars ); + if ( nVars <= 5 ) + { + if ( nVars > 0 ) + pStore[0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 ); + if ( nVars > 1 ) + pStore[1] = Kit_WordCountOnes( pTruth[0] & 0x33333333 ); + if ( nVars > 2 ) + pStore[2] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); + if ( nVars > 3 ) + pStore[3] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF ); + if ( nVars > 4 ) + pStore[4] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF ); + return; + } + // nVars >= 6 + // count 1's for all other variables + for ( k = 0; k < nWords; k++ ) + { + Counter = Kit_WordCountOnes( pTruth[k] ); + for ( i = 5; i < nVars; i++ ) + if ( (k & (1 << (i-5))) == 0 ) + pStore[i] += Counter; + } + // count 1's for the first five variables + for ( k = 0; k < nWords/2; k++ ) + { + pStore[0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); + pStore[1] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); + pStore[2] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); + pStore[3] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); + pStore[4] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); + pTruth += 2; + } +} + /**Function************************************************************* Synopsis [Counts the number of 1's in each cofactor.] @@ -1440,16 +1531,17 @@ unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, */ // collect the minterm counts Kit_TruthCountOnesInCofs( pIn, nVars, pStore ); -// Kit_TruthCountOnesInCofsSlow( pIn, nVars, pStore2, pAux ); -// for ( i = 0; i < 2*nVars; i++ ) -// { -// assert( pStore[i] == pStore2[i] ); -// } - +/* + Kit_TruthCountOnesInCofsSlow( pIn, nVars, pStore2, pAux ); + for ( i = 0; i < 2*nVars; i++ ) + { + assert( pStore[i] == pStore2[i] ); + } +*/ // canonicize phase for ( i = 0; i < nVars; i++ ) { - if ( pStore[2*i+0] >= pStore[2*i+1] ) + if ( pStore[2*i+0] <= pStore[2*i+1] ) continue; uCanonPhase |= (1 << i); Temp = pStore[2*i+0]; @@ -1463,11 +1555,12 @@ unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, // permute Counter = 0; + do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { - if ( pStore[2*i] >= pStore[2*(i+1)] ) + if ( pStore[2*i] <= pStore[2*(i+1)] ) continue; Counter++; fChange = 1; @@ -1485,17 +1578,18 @@ unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, pStore[2*(i+1)+1] = Temp; // if the polarity of variables is different, swap them - if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) ) - { - uCanonPhase ^= (1 << i); - uCanonPhase ^= (1 << (i+1)); - } +// if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) ) +// { +// uCanonPhase ^= (1 << i); +// uCanonPhase ^= (1 << (i+1)); +// } Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; } } while ( fChange ); + /* Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " ); for ( i = 0; i < nVars; i++ ) diff --git a/src/aig/mfx/mfx.h b/src/aig/mfx/mfx.h index 783de56c..aae9e625 100644 --- a/src/aig/mfx/mfx.h +++ b/src/aig/mfx/mfx.h @@ -53,6 +53,7 @@ struct Mfx_Par_t_ int fMoreEffort; // performs high-affort minimization int fSwapEdge; // performs edge swapping int fDelay; // performs optimization for delay + int fPower; // performs power-aware optimization int fVerbose; // enable basic stats int fVeryVerbose; // enable detailed stats }; diff --git a/src/aig/mfx/mfxCore.c b/src/aig/mfx/mfxCore.c index d9f73c9d..f67fb520 100644 --- a/src/aig/mfx/mfxCore.c +++ b/src/aig/mfx/mfxCore.c @@ -53,6 +53,7 @@ void Mfx_ParsDefault( Mfx_Par_t * pPars ) pPars->fArea = 0; pPars->fMoreEffort = 0; pPars->fSwapEdge = 0; + pPars->fPower = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } @@ -105,7 +106,9 @@ clk = clock(); return 1; } // solve the SAT problem - if ( p->pPars->fSwapEdge ) + if ( p->pPars->fPower ) + Mfx_EdgePower( p, pNode ); + else if ( p->pPars->fSwapEdge ) Mfx_EdgeSwapEval( p, pNode ); else { @@ -132,7 +135,7 @@ int Mfx_Node( Mfx_Man_t * p, Nwk_Obj_t * pNode ) { Hop_Obj_t * pObj; int RetValue; - + float dProb; int nGain, clk; p->nNodesTried++; // prepare data structure for this node @@ -170,7 +173,8 @@ p->timeSat += clock() - clk; } // minimize the local function of the node using bi-decomposition assert( p->nFanins == Nwk_ObjFaninNum(pNode) ); - pObj = Nwk_NodeIfNodeResyn( p->pManDec, pNode->pMan->pManHop, pNode->pFunc, p->nFanins, p->vTruth, p->uCare ); + dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; + pObj = Nwk_NodeIfNodeResyn( p->pManDec, pNode->pMan->pManHop, pNode->pFunc, p->nFanins, p->vTruth, p->uCare, dProb ); nGain = Hop_DagSize(pNode->pFunc) - Hop_DagSize(pObj); if ( nGain >= 0 ) { @@ -182,6 +186,45 @@ p->timeSat += clock() - clk; return 1; } +/**Function************************************************************* + + Synopsis [Marks nodes for power-optimization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Nwk_ManPowerEstimate( Nwk_Man_t * pNtk, int fProbOne ) +{ + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vProbs; + Vec_Int_t * vSwitching; + float * pProbability; + float * pSwitching; + Aig_Man_t * pAig; + Aig_Obj_t * pObjAig; + Nwk_Obj_t * pObjAbc; + int i; + // start the resulting array + vProbs = Vec_IntStart( Nwk_ManObjNumMax(pNtk) ); + pProbability = (float *)vProbs->pArray; + // map network into an AIG + pAig = Nwk_ManStrash( pNtk ); + vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, fProbOne ); + pSwitching = (float *)vSwitching->pArray; + Nwk_ManForEachObj( pNtk, pObjAbc, i ) + { + if ( (pObjAig = Aig_Regular(pObjAbc->pCopy)) ) + pProbability[pObjAbc->Id] = pSwitching[pObjAig->Id]; + } + Vec_IntFree( vSwitching ); + Aig_ManStop( pAig ); + return vProbs; +} + /**Function************************************************************* Synopsis [] @@ -253,6 +296,17 @@ int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib ) p->pManDec = Bdc_ManAlloc( pDecPars ); } + // precomputer power-aware metrics + if ( pPars->fPower ) + { + extern Vec_Int_t * Nwk_ManPowerEstimate( Nwk_Man_t * pNtk, int fProbOne ); + if ( pPars->fResub ) + p->vProbs = Nwk_ManPowerEstimate( pNtk, 0 ); + else + p->vProbs = Nwk_ManPowerEstimate( pNtk, 1 ); + printf( "Total switching before = %7.2f.\n", Nwl_ManComputeTotalSwitching(pNtk) ); + } + // compute don't-cares for each node nNodes = 0; p->nTotalNodesBeg = nTotalNodesBeg; @@ -276,6 +330,7 @@ int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib ) { pProgress = Bar_ProgressStart( stdout, Nwk_ManNodeNum(pNtk) ); vLevels = Nwk_ManLevelize( pNtk ); + Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) { if ( !p->pPars->fVeryVerbose ) @@ -303,6 +358,7 @@ int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib ) PRT( "Time", clock() - clk2 ); } } + Bar_ProgressStop( pProgress ); Vec_VecFree( vLevels ); } @@ -312,6 +368,9 @@ int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib ) assert( Nwk_ManVerifyLevel( pNtk ) ); assert( Nwk_ManVerifyTiming( pNtk ) ); + if ( pPars->fPower ) + printf( "Total switching after = %7.2f.\n", Nwl_ManComputeTotalSwitching(pNtk) ); + // free the manager p->timeTotal = clock() - clk; Mfx_ManStop( p ); diff --git a/src/aig/mfx/mfxInt.h b/src/aig/mfx/mfxInt.h index 0693200d..9095c8ce 100644 --- a/src/aig/mfx/mfxInt.h +++ b/src/aig/mfx/mfxInt.h @@ -81,6 +81,8 @@ struct Mfx_Man_t_ Vec_Ptr_t * vFanins; // the new set of fanins int nTotConfLim; // total conflict limit int nTotConfLevel; // total conflicts on this level + // switching activity + Vec_Int_t * vProbs; // the result of solving int nFanins; // the number of fanins int nWords; // the number of words @@ -136,6 +138,7 @@ extern void Mfx_ManStop( Mfx_Man_t * p ); extern void Mfx_ManClean( Mfx_Man_t * p ); /*=== mfxResub.c ==========================================================*/ extern void Mfx_PrintResubStats( Mfx_Man_t * p ); +extern int Mfx_EdgePower( Mfx_Man_t * p, Nwk_Obj_t * pNode ); extern int Mfx_EdgeSwapEval( Mfx_Man_t * p, Nwk_Obj_t * pNode ); extern int Mfx_ResubNode( Mfx_Man_t * p, Nwk_Obj_t * pNode ); extern int Mfx_ResubNode2( Mfx_Man_t * p, Nwk_Obj_t * pNode ); diff --git a/src/aig/mfx/mfxMan.c b/src/aig/mfx/mfxMan.c index 63531770..b8361a20 100644 --- a/src/aig/mfx/mfxMan.c +++ b/src/aig/mfx/mfxMan.c @@ -168,6 +168,8 @@ void Mfx_ManStop( Mfx_Man_t * p ) Aig_ManStop( p->pCare ); if ( p->vSuppsInv ) Vec_VecFree( (Vec_Vec_t *)p->vSuppsInv ); + if ( p->vProbs ) + Vec_IntFree( p->vProbs ); Mfx_ManClean( p ); Int_ManFree( p->pMan ); Vec_IntFree( p->vMem ); diff --git a/src/aig/mfx/mfxResub.c b/src/aig/mfx/mfxResub.c index 006656ee..312ae226 100644 --- a/src/aig/mfx/mfxResub.c +++ b/src/aig/mfx/mfxResub.c @@ -206,6 +206,8 @@ p->timeInt += clock() - clk; iVar = -1; while ( 1 ) { + float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); + assert( (pProbab != NULL) == p->pPars->fPower ); if ( fVeryVerbose ) { printf( "%3d: %2d ", p->nCexes, iVar ); @@ -222,6 +224,13 @@ p->timeInt += clock() - clk; assert( nWords <= p->nDivWords ); for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode); iVar++ ) { + if ( p->pPars->fPower ) + { + Nwk_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); + // only accept the divisor if it is "cool" + if ( pProbab[Nwk_ObjId(pDiv)] >= 0.2 ) + continue; + } pData = Vec_PtrEntry( p->vDivCexes, iVar ); for ( w = 0; w < nWords; w++ ) if ( pData[w] != ~0 ) @@ -429,6 +438,33 @@ int Mfx_EdgeSwapEval( Mfx_Man_t * p, Nwk_Obj_t * pNode ) return 0; } +/**Function************************************************************* + + Synopsis [Evaluates the possibility of replacing given edge by another edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mfx_EdgePower( Mfx_Man_t * p, Nwk_Obj_t * pNode ) +{ + Nwk_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + // try replacing area critical fanins + Nwk_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.4 ) + { + if ( Mfx_SolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } + return 0; +} + + /**Function************************************************************* Synopsis [Performs resubstitution for the node.] diff --git a/src/aig/ntl/ntl.h b/src/aig/ntl/ntl.h index 54db901f..ac266ca5 100644 --- a/src/aig/ntl/ntl.h +++ b/src/aig/ntl/ntl.h @@ -79,6 +79,10 @@ struct Ntl_Man_t_ Aig_Man_t * pAig; // the extracted AIG Tim_Man_t * pManTime; // the timing manager int iLastCi; // the last true CI + void * pNal; // additional data + void (*pNalF)(void *); // additional data + void (*pNalD)(void *,void *); // additional data + void (*pNalW)(void *,void *); // additional data // hashing names into models Ntl_Mod_t ** pModTable; // the hash table of names into models int nModTableSize; // the allocated table size @@ -93,6 +97,7 @@ struct Ntl_Mod_t_ Vec_Ptr_t * vObjs; // the array of all objects Vec_Ptr_t * vPis; // the array of PI objects Vec_Ptr_t * vPos; // the array of PO objects + Vec_Ptr_t * vNets; // the array of nets int nObjs[NTL_OBJ_VOID]; // counter of objects of each type // box attributes unsigned int attrWhite :1; // box has known logic @@ -104,6 +109,9 @@ struct Ntl_Mod_t_ Ntl_Net_t ** pTable; // the hash table of names into nets int nTableSize; // the allocated table size int nEntries; // the number of entries in the hash table + // clocks of the model + Vec_Ptr_t * vClocks; // the clock signals + Vec_Vec_t * vClockFlops; // the flops of each clock // delay information Vec_Int_t * vDelays; Vec_Int_t * vTimeInputs; @@ -154,6 +162,7 @@ struct Ntl_Net_t_ int iTemp; // other data }; Ntl_Obj_t * pDriver; // driver of the net + int NetId; // unique ID of the net char nVisits; // the number of times the net is visited char fMark; // temporary mark char pName[0]; // the name of this net @@ -175,18 +184,19 @@ struct Ntl_Lut_t_ //////////////////////////////////////////////////////////////////////// /// INLINED FUNCTIONS /// //////////////////////////////////////////////////////////////////////// + #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif -static inline Ntl_Mod_t * Ntl_ManRootModel( Ntl_Man_t * p ) { return (Ntl_Mod_t *)Vec_PtrEntry( p->vModels, 0 ); } +static inline Ntl_Mod_t * Ntl_ManRootModel( Ntl_Man_t * p ) { return (Ntl_Mod_t *)Vec_PtrEntry( p->vModels, 0 ); } static inline int Ntl_ModelPiNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PI]; } static inline int Ntl_ModelPoNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PO]; } @@ -195,8 +205,10 @@ static inline int Ntl_ModelLut1Num( Ntl_Mod_t * p ) { return p->nO static inline int Ntl_ModelLatchNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_LATCH]; } static inline int Ntl_ModelBoxNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_BOX]; } -static inline Ntl_Obj_t * Ntl_ModelPi( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPis, i); } -static inline Ntl_Obj_t * Ntl_ModelPo( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPos, i); } +static inline Ntl_Obj_t * Ntl_ModelPi( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPis, i); } +static inline Ntl_Obj_t * Ntl_ModelPo( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPos, i); } +static inline Ntl_Obj_t * Ntl_ModelObj( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vObjs, i); } +static inline Ntl_Net_t * Ntl_ModelNet( Ntl_Mod_t * p, int i ) { return (Ntl_Net_t *)Vec_PtrEntry(p->vNets, i); } static inline char * Ntl_ModelPiName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPi(p, i)->pFanio[0]->pName; } static inline char * Ntl_ModelPoName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPo(p, i)->pFanio[0]->pName; } @@ -253,8 +265,8 @@ static inline int Ntl_ObjIsSeqRoot( Ntl_Obj_t * p ) { return Ntl_O #define Ntl_ModelForEachPo( pNwk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize(pNwk->vPos)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vPos, i)), 1); i++ ) #define Ntl_ModelForEachNet( pNwk, pNet, i ) \ - for ( i = 0; i < pNwk->nTableSize; i++ ) \ - for ( pNet = pNwk->pTable[i]; pNet; pNet = pNet->pNext ) + Vec_PtrForEachEntry( pNwk->vNets, pNet, i ) \ + if ( pNet == NULL ) {} else #define Ntl_ModelForEachObj( pNwk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \ if ( pObj == NULL ) {} else @@ -359,6 +371,7 @@ extern ABC_DLL int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, int fPiOnl extern ABC_DLL int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ); extern ABC_DLL int Ntl_ModelClearNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ); extern ABC_DLL void Ntl_ModelDeleteNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ); +extern ABC_DLL void Ntl_ModelInsertNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ); extern ABC_DLL int Ntl_ModelCountNets( Ntl_Mod_t * p ); extern ABC_DLL int Ntl_ManAddModel( Ntl_Man_t * p, Ntl_Mod_t * pModel ); extern ABC_DLL Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, const char * pName ); diff --git a/src/aig/ntl/ntlCheck.c b/src/aig/ntl/ntlCheck.c index 47f14525..82ef388b 100644 --- a/src/aig/ntl/ntlCheck.c +++ b/src/aig/ntl/ntlCheck.c @@ -206,11 +206,13 @@ checkobjs: printf( "Net in bin %d does not have a name\n", i ); fStatus = 0; } +/* if ( pNet->pDriver == NULL ) { printf( "Net %s does not have a driver\n", pNet->pName ); fStatus = 0; } +*/ } // check objects diff --git a/src/aig/ntl/ntlCore.c b/src/aig/ntl/ntlCore.c index 6bff57d9..b170cdad 100644 --- a/src/aig/ntl/ntlCore.c +++ b/src/aig/ntl/ntlCore.c @@ -43,14 +43,14 @@ Aig_Man_t * Ntl_ManPerformChoicing( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ) { extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * pAig, int fUpdateLevel ); - extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); + extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ); extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); Aig_Man_t * pTemp; // perform synthesis //printf( "Pre-synthesis AIG: " ); //Aig_ManPrintStats( pAig ); // pTemp = Dar_ManBalance( pAig, 1 ); -// pTemp = Dar_ManCompress( pAig, 1, 1, 0 ); +// pTemp = Dar_ManCompress( pAig, 1, 1, 0, 0 ); pTemp = Dar_ManChoice( pAig, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose ); //printf( "Post-synthesis AIG: " ); //Aig_ManPrintStats( pTemp ); diff --git a/src/aig/ntl/ntlExtract.c b/src/aig/ntl/ntlExtract.c index 56710a25..6923ac7a 100644 --- a/src/aig/ntl/ntlExtract.c +++ b/src/aig/ntl/ntlExtract.c @@ -175,7 +175,7 @@ int Ntl_ManExtract_rec( Ntl_Man_t * p, Ntl_Net_t * pNet ) if ( !Ntl_ManExtract_rec( p, pNetFanin ) ) return 0; // add box inputs/outputs to COs/CIs - if ( Ntl_ObjIsBox(pObj) ) + if ( Ntl_ObjIsBox(pObj) ) { int LevelCur, LevelMax = -TIM_ETERNITY; assert( Ntl_BoxIsComb(pObj) ); @@ -370,7 +370,7 @@ int Ntl_ManCollapseBoxSeq1_rec( Ntl_Man_t * p, Ntl_Obj_t * pBox, int fSeq ) pNet->pCopy = Aig_Not(pNet->pCopy); pNet->nVisits = 2; // remember the class of this register - Vec_IntPush( p->vRegClasses, pObj->LatchId.regClass ); + Vec_IntPush( p->vRegClasses, p->pNal ? pBox->iTemp : pObj->LatchId.regClass ); } // compute AIG for the internal nodes Ntl_ModelForEachPo( pModel, pObj, i ) diff --git a/src/aig/ntl/ntlFraig.c b/src/aig/ntl/ntlFraig.c index 27d863af..d2ae4204 100644 --- a/src/aig/ntl/ntlFraig.c +++ b/src/aig/ntl/ntlFraig.c @@ -215,9 +215,9 @@ Aig_Obj_t ** Ntl_ManFraigDeriveClasses( Aig_Man_t * pAig, Ntl_Man_t * pNew, Aig_ void Ntl_ManReduce( Ntl_Man_t * p, Aig_Man_t * pAig ) { Aig_Obj_t * pObj, * pObjRepr; - Ntl_Net_t * pNet, * pNetRepr; + Ntl_Net_t * pNet, * pNetRepr, * pNetNew; Ntl_Mod_t * pRoot; - Ntl_Obj_t * pNode; + Ntl_Obj_t * pNode, * pNodeOld; int i, fCompl, Counter = 0; assert( pAig->pReprs ); pRoot = Ntl_ManRootModel( p ); @@ -271,10 +271,23 @@ void Ntl_ManReduce( Ntl_Man_t * p, Aig_Man_t * pAig ) pNode->pSop = fCompl? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" ); Ntl_ObjSetFanin( pNode, pNetRepr, 0 ); // make the new node drive the equivalent net (pNet) + pNodeOld = pNet->pDriver; if ( !Ntl_ModelClearNetDriver( pNet->pDriver, pNet ) ) printf( "Ntl_ManReduce(): Internal error! Net already has no driver.\n" ); if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) printf( "Ntl_ManReduce(): Internal error! Net already has a driver.\n" ); + + // remove this net from the hash table (but do not remove from the array) + Ntl_ModelDeleteNet( pRoot, pNet ); + // create new net with the same name + pNetNew = Ntl_ModelFindOrCreateNet( pRoot, pNet->pName ); + // clean the name + pNet->pName[0] = 0; + + // make the old node drive the new net without fanouts + if ( !Ntl_ModelSetNetDriver( pNodeOld, pNetNew ) ) + printf( "Ntl_ManReduce(): Internal error! Net already has a driver.\n" ); + Counter++; } } @@ -372,6 +385,11 @@ Ntl_Man_t * Ntl_ManFraig( Ntl_Man_t * p, int nPartSize, int nConfLimit, int nLev pAig = Ntl_ManExtract( p ); pNew = Ntl_ManInsertAig( p, pAig ); pAigCol = Ntl_ManCollapseComb( pNew ); + if ( pAigCol == NULL ) + { + Aig_ManStop( pAig ); + return pNew; + } // perform fraiging for the given design nPartSize = nPartSize? nPartSize : Aig_ManPoNum(pAigCol); @@ -406,13 +424,15 @@ Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVe pAig = Ntl_ManExtract( p ); pNew = Ntl_ManInsertAig( p, pAig ); pAigCol = Ntl_ManCollapseSeq( pNew, 0 ); -//Saig_ManDumpBlif( pAigCol, "1s.blif" ); + if ( pAigCol == NULL ) + { + Aig_ManStop( pAig ); + return pNew; + } // perform SCL for the given design pTemp = Aig_ManScl( pAigCol, fLatchConst, fLatchEqual, fVerbose ); Aig_ManStop( pTemp ); - if ( pNew->vRegClasses && Vec_IntSize(pNew->vRegClasses) && pAigCol->pReprs ) - Ntl_ManFilterRegisterClasses( pAigCol, pNew->vRegClasses, fVerbose ); // finalize the transformation pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, fVerbose ); @@ -435,25 +455,26 @@ Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVe ***********************************************************************/ Ntl_Man_t * Ntl_ManLcorr( Ntl_Man_t * p, int nConfMax, int fVerbose ) { - Ssw_Pars_t Pars, * pPars = &Pars; Ntl_Man_t * pNew, * pAux; Aig_Man_t * pAig, * pAigCol, * pTemp; + Ssw_Pars_t Pars, * pPars = &Pars; + Ssw_ManSetDefaultParamsLcorr( pPars ); + pPars->nBTLimit = nConfMax; + pPars->fVerbose = fVerbose; // collapse the AIG pAig = Ntl_ManExtract( p ); pNew = Ntl_ManInsertAig( p, pAig ); - pAigCol = Ntl_ManCollapseSeq( pNew, 0 ); + pAigCol = Ntl_ManCollapseSeq( pNew, pPars->nMinDomSize ); + if ( pAigCol == NULL ) + { + Aig_ManStop( pAig ); + return pNew; + } - // perform SCL for the given design -// pTemp = Fra_FraigLatchCorrespondence( pAigCol, 0, nConfMax, 0, fVerbose, NULL, 0 ); - Ssw_ManSetDefaultParamsLcorr( pPars ); - pPars->nBTLimit = nConfMax; - pPars->fVerbose = fVerbose; + // perform LCORR for the given design pTemp = Ssw_LatchCorrespondence( pAigCol, pPars ); - Aig_ManStop( pTemp ); - if ( p->vRegClasses && Vec_IntSize(p->vRegClasses) && pAigCol->pReprs ) - Ntl_ManFilterRegisterClasses( pAigCol, p->vRegClasses, fVerbose ); // finalize the transformation pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, fVerbose ); diff --git a/src/aig/ntl/ntlInsert.c b/src/aig/ntl/ntlInsert.c index 52f76151..21f2d246 100644 --- a/src/aig/ntl/ntlInsert.c +++ b/src/aig/ntl/ntlInsert.c @@ -42,7 +42,7 @@ ***********************************************************************/ Ntl_Man_t * Ntl_ManInsertMapping( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig ) { - char Buffer[100]; + char Buffer[1000]; Vec_Ptr_t * vCopies; Vec_Int_t * vCover; Ntl_Mod_t * pRoot; @@ -141,7 +141,7 @@ Ntl_Man_t * Ntl_ManInsertMapping( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t ***********************************************************************/ Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ) { - char Buffer[100]; + char Buffer[1000]; Ntl_Mod_t * pRoot; Ntl_Obj_t * pNode; Ntl_Net_t * pNet, * pNetCo; @@ -243,7 +243,6 @@ Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ) return p; } - /**Function************************************************************* Synopsis [Inserts the given mapping into the netlist.] @@ -257,7 +256,7 @@ Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ) ***********************************************************************/ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ) { - char Buffer[100]; + char Buffer[1000]; Vec_Ptr_t * vObjs; Vec_Int_t * vTruth; Vec_Int_t * vCover; @@ -276,8 +275,8 @@ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ) Ntl_ManForEachCiNet( p, pNet, i ) Nwk_ManCi( pNtk, i )->pCopy = pNet; // create a new node for each LUT - vTruth = Vec_IntAlloc( 1 << 16 ); - vCover = Vec_IntAlloc( 1 << 16 ); + vTruth = Vec_IntAlloc( 1 << 16 ); + vCover = Vec_IntAlloc( 1 << 16 ); nDigits = Aig_Base10Log( Nwk_ManNodeNum(pNtk) ); // go through the nodes in the topological order vObjs = Nwk_ManDfs( pNtk ); @@ -289,7 +288,6 @@ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ) pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); if ( Hop_IsComplement(pObj->pFunc) ) Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) ); - pNode->pSop = Kit_PlaFromTruth( p->pMemSops, pTruth, Nwk_ObjFaninNum(pObj), vCover ); if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) { Nwk_ObjForEachFanin( pObj, pFanin, k ) @@ -303,8 +301,17 @@ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ) Ntl_ObjSetFanin( pNode, pNet, k ); } } - else + else if ( Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) ) + { + pObj->pFunc = Hop_ManConst0(pNtk->pManHop); pNode->nFanins = 0; + } + else if ( Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) + { + pObj->pFunc = Hop_ManConst1(pNtk->pManHop); + pNode->nFanins = 0; + } + pNode->pSop = Kit_PlaFromTruth( p->pMemSops, pTruth, Nwk_ObjFaninNum(pObj), vCover ); sprintf( Buffer, "lut%0*d", nDigits, i ); if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) ) { @@ -334,11 +341,29 @@ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ) // get the corresponding PO and its driver pObj = Nwk_ManCo( pNtk, i ); pFanin = Nwk_ObjFanin0( pObj ); - // get the net driving the driver - pNet = pFanin->pCopy; - pNode = Ntl_ModelCreateNode( pRoot, 1 ); - pNode->pSop = pObj->fInvert? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" ); - Ntl_ObjSetFanin( pNode, pNet, 0 ); + // get the net driving this PO + pNet = pFanin->pCopy; + if ( Nwk_ObjFanoutNum(pFanin) == 1 && Ntl_ObjIsNode(pNet->pDriver) ) + { + pNode = pNet->pDriver; + if ( !Ntl_ModelClearNetDriver( pNode, pNet ) ) + { + printf( "Ntl_ManInsertNtk(): Internal error! Net already has no driver.\n" ); + return NULL; + } + // remove this net + Ntl_ModelDeleteNet( pRoot, pNet ); + Vec_PtrWriteEntry( pRoot->vNets, pNet->NetId, NULL ); + // update node's function + if ( pObj->fInvert ) + Kit_PlaComplement( pNode->pSop ); + } + else + { + pNode = Ntl_ModelCreateNode( pRoot, 1 ); + pNode->pSop = pObj->fInvert? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" ); + Ntl_ObjSetFanin( pNode, pNet, 0 ); + } // update the CO driver net assert( pNetCo->pDriver == NULL ); if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) ) diff --git a/src/aig/ntl/ntlMan.c b/src/aig/ntl/ntlMan.c index dd481537..8b26e405 100644 --- a/src/aig/ntl/ntlMan.c +++ b/src/aig/ntl/ntlMan.c @@ -108,6 +108,7 @@ Ntl_Man_t * Ntl_ManStartFrom( Ntl_Man_t * pOld ) pNew->pName = Ntl_ManStoreFileName( pNew, pOld->pName ); pNew->pSpec = Ntl_ManStoreName( pNew, pOld->pName ); Vec_PtrForEachEntry( pOld->vModels, pModel, i ) + { if ( i == 0 ) { Ntl_ManMarkCiCoNets( pOld ); @@ -116,15 +117,21 @@ Ntl_Man_t * Ntl_ManStartFrom( Ntl_Man_t * pOld ) } else pModel->pCopy = Ntl_ModelDup( pNew, pModel ); + } Vec_PtrForEachEntry( pOld->vModels, pModel, i ) Ntl_ModelForEachBox( pModel, pBox, k ) + { ((Ntl_Obj_t *)pBox->pCopy)->pImplem = pBox->pImplem->pCopy; + ((Ntl_Obj_t *)pBox->pCopy)->iTemp = pBox->iTemp; + } Ntl_ManForEachCiNet( pOld, pNet, i ) Vec_PtrPush( pNew->vCis, pNet->pCopy ); Ntl_ManForEachCoNet( pOld, pNet, i ) Vec_PtrPush( pNew->vCos, pNet->pCopy ); if ( pOld->pManTime ) pNew->pManTime = Tim_ManDup( pOld->pManTime, 0 ); + if ( pOld->pNal ) + pOld->pNalD( pOld, pNew ); return pNew; } @@ -195,13 +202,14 @@ void Ntl_ManFree( Ntl_Man_t * p ) if ( p->pMemSops ) Aig_MmFlexStop( p->pMemSops, 0 ); if ( p->pAig ) Aig_ManStop( p->pAig ); if ( p->pManTime ) Tim_ManStop( p->pManTime ); + if ( p->pNal ) p->pNalF( p->pNal ); FREE( p->pModTable ); free( p ); } /**Function************************************************************* - Synopsis [Deallocates the netlist manager.] + Synopsis [] Description [] @@ -219,6 +227,7 @@ void Ntl_ManPrintStats( Ntl_Man_t * p ) printf( "po = %5d ", Ntl_ModelPoNum(pRoot) ); printf( "lat = %5d ", Ntl_ModelLatchNum(pRoot) ); printf( "node = %5d ", Ntl_ModelNodeNum(pRoot) ); + printf( "\n " ); printf( "inv/buf = %5d ", Ntl_ModelLut1Num(pRoot) ); printf( "box = %4d ", Ntl_ModelBoxNum(pRoot) ); printf( "mod = %3d ", Vec_PtrSize(p->vModels) ); @@ -230,6 +239,50 @@ void Ntl_ManPrintStats( Ntl_Man_t * p ) fflush( stdout ); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nwk_ManPrintStatsShort( Ntl_Man_t * p, Aig_Man_t * pAig, Nwk_Man_t * pNtk ) +{ + Ntl_Mod_t * pRoot; + Ntl_Obj_t * pObj; + int i, Counter = 0; + pRoot = Ntl_ManRootModel( p ); + Ntl_ModelForEachBox( pRoot, pObj, i ) + if ( strcmp(pObj->pImplem->pName, "dff") == 0 ) + Counter++; + printf( "%-15s : ", p->pName ); + printf( "pi =%5d ", Ntl_ModelPiNum(pRoot) ); + printf( "po =%5d ", Ntl_ModelPoNum(pRoot) ); + printf( "ff =%5d ", Counter ); + if ( pAig != NULL ) + { + Counter = Aig_ManCountChoices( pAig ); + if ( Counter ) + printf( "cho =%7d ", Counter ); + else + printf( "aig =%7d ", Aig_ManNodeNum(pAig) ); + } + if ( pNtk == NULL ) + printf( "Mapping is not available.\n" ); + else + { + printf( "lut =%5d ", Nwk_ManNodeNum(pNtk) ); + printf( "lev =%3d ", Nwk_ManLevel(pNtk) ); +// printf( "del =%5.2f ", Nwk_ManDelayTraceLut(pNtk) ); + printf( "\n" ); + } +} + /**Function************************************************************* Synopsis [Deallocates the netlist manager.] @@ -283,6 +336,8 @@ void Ntl_ManSaveBoxType( Ntl_Obj_t * pObj ) ***********************************************************************/ void Ntl_ManPrintTypes( Ntl_Man_t * p ) { + Vec_Ptr_t * vFlops; + Ntl_Net_t * pNet; Ntl_Mod_t * pModel; Ntl_Obj_t * pObj; int i; @@ -296,7 +351,7 @@ void Ntl_ManPrintTypes( Ntl_Man_t * p ) { if ( !p->BoxTypes[i] ) continue; - printf( "%5d :", p->BoxTypes[i] ); + printf( "Type %2d Num = %7d :", i, p->BoxTypes[i] ); printf( " %s", ((i & 1) > 0)? "white ": "black " ); printf( " %s", ((i & 2) > 0)? "box ": "logic " ); printf( " %s", ((i & 4) > 0)? "comb ": "seq " ); @@ -304,9 +359,22 @@ void Ntl_ManPrintTypes( Ntl_Man_t * p ) printf( " %s", ((i & 16) > 0)? "no_merge": "merge " ); printf( "\n" ); } - printf( "Total box instances = %6d.\n\n", Ntl_ModelBoxNum(pModel) ); + printf( "MODEL STATISTICS:\n" ); + Ntl_ManForEachModel( p, pModel, i ) + if ( i ) printf( "Model %2d : Name = %10s Used = %6d.\n", i, pModel->pName, pModel->nUsed ); for ( i = 0; i < 32; i++ ) p->BoxTypes[i] = 0; + pModel = Ntl_ManRootModel( p ); + if ( pModel->vClockFlops ) + { + printf( "CLOCK STATISTICS:\n" ); + Vec_VecForEachLevel( pModel->vClockFlops, vFlops, i ) + { + pNet = Vec_PtrEntry( pModel->vClocks, i ); + printf( "Clock %2d : Name = %30s Flops = %6d.\n", i+1, pNet->pName, Vec_PtrSize(vFlops) ); + } + } + printf( "\n" ); } /**Function************************************************************* @@ -336,6 +404,7 @@ Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName ) p->vObjs = Vec_PtrAlloc( 100 ); p->vPis = Vec_PtrAlloc( 10 ); p->vPos = Vec_PtrAlloc( 10 ); + p->vNets = Vec_PtrAlloc( 100 ); // start the table p->nTableSize = Aig_PrimeCudd( 100 ); p->pTable = ALLOC( Ntl_Net_t *, p->nTableSize ); @@ -382,7 +451,9 @@ Ntl_Mod_t * Ntl_ModelStartFrom( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld ) } Ntl_ModelForEachNet( pModelOld, pNet, i ) { - if ( pNet->fMark ) + if ( pNet->pDriver == NULL ) + pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNet->pName ); + else if ( pNet->fMark ) { pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNet->pName ); ((Ntl_Net_t *)pNet->pCopy)->pDriver = pNet->pDriver->pCopy; @@ -485,6 +556,9 @@ void Ntl_ModelFree( Ntl_Mod_t * p ) if ( p->vTimeOutputs ) Vec_IntFree( p->vTimeOutputs ); if ( p->vTimeInputs ) Vec_IntFree( p->vTimeInputs ); if ( p->vDelays ) Vec_IntFree( p->vDelays ); + if ( p->vClocks ) Vec_PtrFree( p->vClocks ); + if ( p->vClockFlops ) Vec_VecFree( p->vClockFlops ); + Vec_PtrFree( p->vNets ); Vec_PtrFree( p->vObjs ); Vec_PtrFree( p->vPis ); Vec_PtrFree( p->vPos ); diff --git a/src/aig/ntl/ntlReadBlif.c b/src/aig/ntl/ntlReadBlif.c index d1a1b99d..3021d556 100644 --- a/src/aig/ntl/ntlReadBlif.c +++ b/src/aig/ntl/ntlReadBlif.c @@ -1322,6 +1322,7 @@ static char * Ioa_ReadParseTableBlif( Ioa_ReadMod_t * p, char * pTable, int nFan char * pProduct, * pOutput; int i, Polarity = -1; + p->pMan->nTablesRead++; // get the tokens Ioa_ReadSplitIntoTokens( vTokens, pTable, '.' ); @@ -1330,6 +1331,8 @@ static char * Ioa_ReadParseTableBlif( Ioa_ReadMod_t * p, char * pTable, int nFan if ( Vec_PtrSize(vTokens) == 1 ) { pOutput = Vec_PtrEntry( vTokens, 0 ); + if ( *pOutput == '\"' ) + return Ntl_ManStoreSop( p->pMan->pDesign->pMemSops, pOutput ); if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) { sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Ioa_ReadGetLine(p->pMan, pOutput), pOutput ); diff --git a/src/aig/ntl/ntlSweep.c b/src/aig/ntl/ntlSweep.c index fc95415d..b2c700fb 100644 --- a/src/aig/ntl/ntlSweep.c +++ b/src/aig/ntl/ntlSweep.c @@ -139,8 +139,11 @@ int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose ) } // remove the fanout nets Ntl_ObjForEachFanout( pObj, pNet, k ) - if ( pNet != NULL ) + if ( pNet != NULL && pNet->pName[0] != 0 ) + { Ntl_ModelDeleteNet( pRoot, pNet ); + Vec_PtrWriteEntry( pRoot->vNets, pNet->NetId, NULL ); + } // remove the object if ( Ntl_ObjIsNode(pObj) && Ntl_ObjFaninNum(pObj) == 1 ) pRoot->nObjs[NTL_OBJ_LUT1]--; @@ -150,7 +153,7 @@ int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose ) pObj->Type = NTL_OBJ_NONE; Counter++; } - + // print detailed statistics of sweeping @@ -191,7 +194,7 @@ int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose ) } } } - printf("\nLUTboxType =%d\n", numLutBox); +// printf("\nLUTboxType =%d\n", numLutBox); } } if ( !Ntl_ManCheck( p ) ) diff --git a/src/aig/ntl/ntlTable.c b/src/aig/ntl/ntlTable.c index aa122900..62f65d6c 100644 --- a/src/aig/ntl/ntlTable.c +++ b/src/aig/ntl/ntlTable.c @@ -58,6 +58,8 @@ Ntl_Net_t * Ntl_ModelCreateNet( Ntl_Mod_t * p, const char * pName ) pNet = (Ntl_Net_t *)Aig_MmFlexEntryFetch( p->pMan->pMemObjs, sizeof(Ntl_Net_t) + strlen(pName) + 1 ); memset( pNet, 0, sizeof(Ntl_Net_t) ); strcpy( pNet->pName, pName ); + pNet->NetId = Vec_PtrSize( p->vNets ); + Vec_PtrPush( p->vNets, pNet ); return pNet; } @@ -104,7 +106,7 @@ clk = clock(); /**Function************************************************************* - Synopsis [Finds or creates the net.] + Synopsis [Finds net.] Description [] @@ -125,7 +127,7 @@ Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, const char * pName ) /**Function************************************************************* - Synopsis [Finds or creates the net.] + Synopsis [Deletes net from the hash table.] Description [] @@ -150,6 +152,26 @@ void Ntl_ModelDeleteNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ) p->pTable[Key] = pEnt->pNext; else pPrev->pNext = pEnt->pNext; + p->nEntries--; +} + +/**Function************************************************************* + + Synopsis [Inserts net into the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_ModelInsertNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ) +{ + unsigned Key = Ntl_HashString( pNet->pName, p->nTableSize ); + assert( Ntl_ModelFindNet( p, pNet->pName ) == NULL ); + pNet->pNext = p->pTable[Key]; + p->pTable[Key] = pNet; } /**Function************************************************************* @@ -178,6 +200,17 @@ Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, const char * pName ) return pEnt; } +/**Function************************************************************* + + Synopsis [Creates new net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ Ntl_Net_t * Ntl_ModelDontFindCreateNet( Ntl_Mod_t * p, const char * pName ) { Ntl_Net_t * pEnt; diff --git a/src/aig/ntl/ntlUtil.c b/src/aig/ntl/ntlUtil.c index 51f3b818..6e797590 100644 --- a/src/aig/ntl/ntlUtil.c +++ b/src/aig/ntl/ntlUtil.c @@ -424,7 +424,7 @@ Vec_Vec_t * Ntl_ManTransformRegClasses( Ntl_Man_t * pMan, int nSizeMax, int fVer vParts = Vec_PtrAlloc( 100 ); for ( i = 0; i <= ClassMax; i++ ) { - if ( pClassNums[i] < nSizeMax ) + if ( pClassNums[i] == 0 || pClassNums[i] < nSizeMax ) continue; vPart = Vec_IntAlloc( pClassNums[i] ); Vec_IntForEachEntry( pMan->vRegClasses, Class, k ) diff --git a/src/aig/ntl/ntlWriteBlif.c b/src/aig/ntl/ntlWriteBlif.c index 6b7f0996..3df49270 100644 --- a/src/aig/ntl/ntlWriteBlif.c +++ b/src/aig/ntl/ntlWriteBlif.c @@ -140,6 +140,8 @@ void Ioa_WriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel, int fMain ) fprintf( pFile, " %s", pNet->pName ); fprintf( pFile, " %s\n", Ntl_ObjFanout0(pObj)->pName ); fprintf( pFile, "%s", pObj->pSop ); + if ( *pObj->pSop == '\"' ) + fprintf( pFile, "\n" ); } else if ( Ntl_ObjIsLatch(pObj) ) { @@ -390,6 +392,8 @@ void Ioa_WriteBlifModelGz( gzFile pFile, Ntl_Mod_t * pModel, int fMain ) gzprintf( pFile, " %s", pNet->pName ); gzprintf( pFile, " %s\n", Ntl_ObjFanout0(pObj)->pName ); gzprintf( pFile, "%s", pObj->pSop ); + if ( *pObj->pSop == '\"' ) + gzprintf( pFile, "\n" ); } else if ( Ntl_ObjIsLatch(pObj) ) { @@ -567,6 +571,8 @@ void Ioa_WriteBlifModelBz2( bz2file * b, Ntl_Mod_t * pModel, int fMain ) fprintfBz2( b, " %s", pNet->pName ); fprintfBz2( b, " %s\n", Ntl_ObjFanout0(pObj)->pName ); fprintfBz2( b, "%s", pObj->pSop ); + if ( *pObj->pSop == '\"' ) + fprintfBz2( b, "\n" ); } else if ( Ntl_ObjIsLatch(pObj) ) { @@ -625,7 +631,11 @@ void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName ) Ntl_Mod_t * pModel; int i, bzError; bz2file b; - + if ( p->pNal ) + { + p->pNalW( p, pFileName ); + return; + } // write the GZ file if (!strncmp(pFileName+strlen(pFileName)-3,".gz",3)) { diff --git a/src/aig/nwk/nwk.h b/src/aig/nwk/nwk.h index 603c1fb8..0ea8241b 100644 --- a/src/aig/nwk/nwk.h +++ b/src/aig/nwk/nwk.h @@ -123,14 +123,14 @@ struct Nwk_Obj_t_ //#pragma warning( disable : 4273 ) #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif static inline int Nwk_ManCiNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_CI]; } @@ -234,7 +234,7 @@ static inline int Nwk_ManTimeMore( float f1, float f2, float Eps ) { r extern ABC_DLL Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose ); /*=== nwkBidec.c ==========================================================*/ extern ABC_DLL void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose ); -extern ABC_DLL Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare ); +extern ABC_DLL Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); /*=== nwkCheck.c ==========================================================*/ extern ABC_DLL int Nwk_ManCheck( Nwk_Man_t * p ); /*=== nwkDfs.c ==========================================================*/ @@ -265,7 +265,8 @@ extern ABC_DLL Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int n /*=== nwkMan.c ============================================================*/ extern ABC_DLL Nwk_Man_t * Nwk_ManAlloc(); extern ABC_DLL void Nwk_ManFree( Nwk_Man_t * p ); -extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, void * pNtl ); +extern ABC_DLL float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk ); +extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl ); /*=== nwkMap.c ============================================================*/ extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ); /*=== nwkObj.c ============================================================*/ diff --git a/src/aig/nwk/nwkBidec.c b/src/aig/nwk/nwkBidec.c index e30d2c02..2b60d779 100644 --- a/src/aig/nwk/nwkBidec.c +++ b/src/aig/nwk/nwkBidec.c @@ -24,6 +24,26 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn[w]; +} +static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] | pIn1[w]; +} +static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & ~pIn1[w]; +} + static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCond( Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } //////////////////////////////////////////////////////////////////////// @@ -41,7 +61,7 @@ static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCo SeeAlso [] ***********************************************************************/ -Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare ) +Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ) { unsigned * pTruth; Bdc_Fun_t * pFunc; @@ -52,8 +72,33 @@ Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pR if ( Hop_IsComplement(pRoot) ) for ( i = Aig_TruthWordNum(nVars)-1; i >= 0; i-- ) pTruth[i] = ~pTruth[i]; - // decompose truth table - Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); + // perform power-aware decomposition + if ( dProb >= 0.0 ) + { + float Prob = (float)2.0 * dProb * (1.0 - dProb); + assert( Prob >= 0.0 && Prob <= 0.5 ); + if ( Prob >= 0.4 ) + { + Extra_TruthNot( puCare, puCare, nVars ); + if ( dProb > 0.5 ) // more 1s than 0s + Extra_TruthOr( pTruth, pTruth, puCare, nVars ); + else + Extra_TruthSharp( pTruth, pTruth, puCare, nVars ); + Extra_TruthNot( puCare, puCare, nVars ); + // decompose truth table + Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 ); + } + else + { + // decompose truth table + Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); + } + } + else + { + // decompose truth table + Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); + } // convert back into HOP Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) ); for ( i = 0; i < nVars; i++ ) @@ -106,7 +151,7 @@ void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose ) if ( Nwk_ObjFaninNum(pObj) > 15 ) continue; nNodes1 = Hop_DagSize(pObj->pFunc); - pObj->pFunc = Nwk_NodeIfNodeResyn( p, pNtk->pManHop, pObj->pFunc, Nwk_ObjFaninNum(pObj), vTruth, NULL ); + pObj->pFunc = Nwk_NodeIfNodeResyn( p, pNtk->pManHop, pObj->pFunc, Nwk_ObjFaninNum(pObj), vTruth, NULL, -1.0 ); nNodes2 = Hop_DagSize(pObj->pFunc); nGainTotal += nNodes1 - nNodes2; } diff --git a/src/aig/nwk/nwkMan.c b/src/aig/nwk/nwkMan.c index 55cdf42b..6b67d3c1 100644 --- a/src/aig/nwk/nwkMan.c +++ b/src/aig/nwk/nwkMan.c @@ -181,6 +181,42 @@ char * Nwk_FileNameGeneric( char * FileName ) return pRes; } +/**Function************************************************************* + + Synopsis [Marks nodes for power-optimization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk ) +{ + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vSwitching; + float * pSwitching; + Aig_Man_t * pAig; + Aig_Obj_t * pObjAig; + Nwk_Obj_t * pObjAbc; + float Result = (float)0; + int i; + // strash the network + // map network into an AIG + pAig = Nwk_ManStrash( pNtk ); + vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 ); + pSwitching = (float *)vSwitching->pArray; + Nwk_ManForEachObj( pNtk, pObjAbc, i ) + { + if ( (pObjAig = Aig_Regular(pObjAbc->pCopy)) ) + Result += Nwk_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id]; + } + Vec_IntFree( vSwitching ); + Aig_ManStop( pAig ); + return Result; +} + /**Function************************************************************* Synopsis [Prints stats of the manager.] @@ -192,7 +228,7 @@ char * Nwk_FileNameGeneric( char * FileName ) SeeAlso [] ***********************************************************************/ -void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, void * pNtl ) +void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl ) { extern int Ntl_ManLatchNum( void * p ); extern void Ioa_WriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName ); @@ -221,7 +257,9 @@ void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int printf( "aig = %6d ", Nwk_ManGetAigNodeNum(pNtk) ); printf( "lev = %3d ", Nwk_ManLevel(pNtk) ); // printf( "lev2 = %3d ", Nwk_ManLevelBackup(pNtk) ); - printf( "delay = %5.2f ", Nwk_ManDelayTraceLut(pNtk) ); + printf( "delay = %5.2f ", Nwk_ManDelayTraceLut(pNtk) ); + if ( fPower ) + printf( "power = %7.2f ", Nwl_ManComputeTotalSwitching(pNtk) ); Nwk_ManPrintLutSizes( pNtk, pLutLib ); printf( "\n" ); // Nwk_ManDelayTracePrint( pNtk, pLutLib ); diff --git a/src/aig/nwk/nwkMap.c b/src/aig/nwk/nwkMap.c index 88e08413..a70bb9b1 100644 --- a/src/aig/nwk/nwkMap.c +++ b/src/aig/nwk/nwkMap.c @@ -59,6 +59,7 @@ void Nwk_ManSetIfParsDefault( If_Par_t * pPars ) pPars->fExpRed = 1; //// pPars->fLatchPaths = 0; pPars->fEdge = 1; + pPars->fPower = 0; pPars->fCutMin = 0; pPars->fSeqMap = 0; pPars->fVerbose = 0; @@ -98,12 +99,29 @@ void Nwk_ManSetIfParsDefault( If_Par_t * pPars ) ***********************************************************************/ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) { + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vSwitching = NULL, * vSwitching2 = NULL; + float * pSwitching, * pSwitching2; If_Man_t * pIfMan; If_Obj_t * pIfObj; Aig_Obj_t * pNode, * pFanin, * pPrev; - int i; + int i, clk = clock(); + // set the number of registers (switch activity will be combinational) + Aig_ManSetRegNum( p, 0 ); + if ( pPars->fPower ) + { + vSwitching = Saig_ManComputeSwitchProbs( p, 48, 16, 0 ); + if ( pPars->fVerbose ) + { + PRT( "Computing switching activity", clock() - clk ); + } + pSwitching = (float *)vSwitching->pArray; + vSwitching2 = Vec_IntStart( Aig_ManObjNumMax(p) ); + pSwitching2 = (float *)vSwitching2->pArray; + } // start the mapping manager and set its parameters pIfMan = If_ManStart( pPars ); + pIfMan->vSwitching = vSwitching2; // load the AIG into the mapper Aig_ManForEachObj( p, pNode, i ) { @@ -116,6 +134,8 @@ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) pIfObj = If_ManCreateCi( pIfMan ); If_ObjSetLevel( pIfObj, Aig_ObjLevel(pNode) ); // printf( "pi=%d ", pIfObj->Level ); + if ( pIfMan->nLevelMax < (int)pIfObj->Level ) + pIfMan->nLevelMax = (int)pIfObj->Level; } else if ( Aig_ObjIsPo(pNode) ) { @@ -130,6 +150,8 @@ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) assert( Vec_PtrEntry(vAigToIf, i) == NULL ); Vec_PtrWriteEntry( vAigToIf, i, pIfObj ); pNode->pData = pIfObj; + if ( vSwitching2 ) + pSwitching2[pIfObj->Id] = pSwitching[pNode->Id]; // set up the choice node if ( Aig_ObjIsChoice( p, pNode ) ) { @@ -140,6 +162,8 @@ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) } // assert( If_ObjLevel(pIfObj) == Aig_ObjLevel(pNode) ); } + if ( vSwitching ) + Vec_IntFree( vSwitching ); return pIfMan; } diff --git a/src/aig/nwk/nwkMerge.c b/src/aig/nwk/nwkMerge.c index 531bc1c0..3aec4faa 100644 --- a/src/aig/nwk/nwkMerge.c +++ b/src/aig/nwk/nwkMerge.c @@ -913,7 +913,7 @@ int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand ) SeeAlso [] ***********************************************************************/ -void Nwl_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) +void Nwk_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) { Nwk_Obj_t * pFanin, * pObj; int i, k; @@ -985,7 +985,7 @@ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, Nwk_LMPars_t * pPars ) { if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize ) continue; - Nwl_ManCollectOverlapCands( pLut, vCands1, pPars ); + Nwk_ManCollectOverlapCands( pLut, vCands1, pPars ); if ( pPars->fUseDiffSupp ) Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) @@ -1022,9 +1022,11 @@ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, Nwk_LMPars_t * pPars ) Nwk_ManGraphReportMemoryUsage( p ); } vResult = p->vPairs; p->vPairs = NULL; +/* for ( i = 0; i < vResult->nSize; i += 2 ) printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); printf( "\n" ); +*/ Nwk_ManGraphFree( p ); return vResult; } diff --git a/src/aig/nwk/nwkStrash.c b/src/aig/nwk/nwkStrash.c index a4ce5e39..6c2a3677 100644 --- a/src/aig/nwk/nwkStrash.c +++ b/src/aig/nwk/nwkStrash.c @@ -133,6 +133,7 @@ Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk ) } Vec_PtrFree( vObjs ); Aig_ManCleanup( pMan ); + Aig_ManSetRegNum( pMan, 0 ); return pMan; } diff --git a/src/aig/nwk2/nwk.h b/src/aig/nwk2/nwk.h index 465bd651..bef16284 100644 --- a/src/aig/nwk2/nwk.h +++ b/src/aig/nwk2/nwk.h @@ -242,7 +242,7 @@ extern void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNe /*=== nwkMan.c ============================================================*/ extern Nwk_Man_t * Nwk_ManAlloc(); extern void Nwk_ManFree( Nwk_Man_t * p ); -//extern void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, void * pNtl ); +//extern void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl ); /*=== nwkObj.c ============================================================*/ extern Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * pMan, int nFanouts ); extern Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * pMan ); diff --git a/src/aig/nwk2/nwkMan.c b/src/aig/nwk2/nwkMan.c index 962cafd4..cd73f866 100644 --- a/src/aig/nwk2/nwkMan.c +++ b/src/aig/nwk2/nwkMan.c @@ -195,7 +195,7 @@ char * Nwk_FileNameGeneric( char * FileName ) ***********************************************************************/ /* -void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, void * pNtl ) +void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl ) { extern int Ntl_ManLatchNum( void * p ); extern void Ioa_WriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName ); diff --git a/src/aig/saig/module.make b/src/aig/saig/module.make index 7063bd2a..e583bcfe 100644 --- a/src/aig/saig/module.make +++ b/src/aig/saig/module.make @@ -6,12 +6,18 @@ SRC += src/aig/saig/saigAbs.c \ src/aig/saig/saigHaig.c \ src/aig/saig/saigInd.c \ src/aig/saig/saigIoa.c \ - src/aig/saig/saigLoc.c \ src/aig/saig/saigMiter.c \ src/aig/saig/saigPhase.c \ src/aig/saig/saigRetFwd.c \ src/aig/saig/saigRetMin.c \ src/aig/saig/saigRetStep.c \ src/aig/saig/saigScl.c \ + src/aig/saig/saigSimExt.c \ + src/aig/saig/saigSimFast.c \ + src/aig/saig/saigSimMv.c \ + src/aig/saig/saigSimSeq.c \ + src/aig/saig/saigStrSim.c \ + src/aig/saig/saigSwitch.c \ src/aig/saig/saigSynch.c \ - src/aig/saig/saigTrans.c + src/aig/saig/saigTrans.c \ + src/aig/saig/saigWnd.c diff --git a/src/aig/saig/saig.h b/src/aig/saig/saig.h index d96996cf..84ff272a 100644 --- a/src/aig/saig/saig.h +++ b/src/aig/saig/saig.h @@ -30,7 +30,6 @@ extern "C" { //////////////////////////////////////////////////////////////////////// #include "aig.h" -#include "int.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -40,6 +39,18 @@ extern "C" { /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// +typedef struct Sec_MtrStatus_t_ Sec_MtrStatus_t; +struct Sec_MtrStatus_t_ +{ + int nInputs; // the total number of inputs + int nNodes; // the total number of nodes + int nOutputs; // the total number of outputs + int nUnsat; // the number of UNSAT outputs + int nSat; // the number of SAT outputs + int nUndec; // the number of undecided outputs + int iOut; // the satisfied output +}; + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -79,7 +90,7 @@ static inline Aig_Obj_t * Saig_ObjLiToLo( Aig_Man_t * p, Aig_Obj_t * pObj ) { //////////////////////////////////////////////////////////////////////// /*=== sswAbs.c ==========================================================*/ -extern Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fDynamic, int fExtend, int fVerbose ); +extern Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fDynamic, int fExtend, int fSkipProof, int fVerbose ); /*=== saigBmc.c ==========================================================*/ extern int Saig_ManBmcSimple( Aig_Man_t * pAig, int nFrames, int nSizeMax, int nBTLimit, int fRewrite, int fVerbose, int * piFrame ); extern void Saig_BmcPerform( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConfMaxOne, int nConfMaxAll, int fVerbose ); @@ -95,11 +106,11 @@ extern int Saig_ManInduction( Aig_Man_t * p, int nFramesMax, int n /*=== saigIoa.c ==========================================================*/ extern void Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName ); extern Aig_Man_t * Saig_ManReadBlif( char * pFileName ); -/*=== saigInter.c ==========================================================*/ -extern int Saig_Interpolate( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * pDepth ); /*=== saigMiter.c ==========================================================*/ +extern Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p ); extern Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); extern Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); +extern Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ); extern Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames ); extern int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); extern int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); @@ -115,10 +126,23 @@ extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, in extern int Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs ); /*=== saigScl.c ==========================================================*/ extern void Saig_ManReportUselessRegisters( Aig_Man_t * pAig ); +/*=== saigSimExt.c ==========================================================*/ +//extern Vec_Int_t * Saig_ManExtendCounterExample( Aig_Man_t * p, int iFirstPi, Ssw_Cex_t * pCex, Vec_Ptr_t * vSimInfo ); +//extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, Ssw_Cex_t * pCex ); +/*=== saigSimMv.c ==========================================================*/ +extern int Saig_MvManSimulate( Aig_Man_t * pAig, int fVerbose ); +/*=== saigStrSim.c ==========================================================*/ +extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ); +/*=== saigSwitch.c ==========================================================*/ +extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); /*=== saigSynch.c ==========================================================*/ extern Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ); /*=== saigTrans.c ==========================================================*/ extern Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose ); +/*=== saigWnd.c ==========================================================*/ +extern Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ); +extern Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd ); +extern Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p ); #ifdef __cplusplus } diff --git a/src/aig/saig/saigAbs.c b/src/aig/saig/saigAbs.c index 8498f59a..d2a45b4e 100644 --- a/src/aig/saig/saigAbs.c +++ b/src/aig/saig/saigAbs.c @@ -23,6 +23,7 @@ #include "cnf.h" #include "satSolver.h" #include "satStore.h" +#include "ssw.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -105,7 +106,11 @@ int Saig_AbsMarkVisited_rec( Aig_Man_t * p, Vec_Str_t * vObj2Visit, Aig_Obj_t * if ( Saig_ObjIsPi( p, pObj ) ) return 1; if ( Saig_ObjIsLo( p, pObj ) ) + { + if ( i == 0 ) + return 1; return Saig_AbsMarkVisited_rec( p, vObj2Visit, Saig_ObjLoToLi(p, pObj), i-1 ); + } if ( Aig_ObjIsPo( pObj ) ) return Saig_AbsMarkVisited_rec( p, vObj2Visit, Aig_ObjFanin0(pObj), i ); Saig_AbsMarkVisited_rec( p, vObj2Visit, Aig_ObjFanin0(pObj), i ); @@ -130,8 +135,8 @@ Vec_Str_t * Saig_AbsMarkVisited( Aig_Man_t * p, int nFramesMax ) Aig_Obj_t * pObj; int i, f; vObj2Visit = Vec_StrStart( Aig_ManObjNumMax(p) * nFramesMax ); - Saig_ManForEachLo( p, pObj, i ) - Saig_AbsSetVisited( vObj2Visit, Aig_ManObjNumMax(p), pObj, 0 ); +// Saig_ManForEachLo( p, pObj, i ) +// Saig_AbsSetVisited( vObj2Visit, Aig_ManObjNumMax(p), pObj, 0 ); for ( f = 0; f < nFramesMax; f++ ) { Saig_AbsSetVisited( vObj2Visit, Aig_ManObjNumMax(p), Aig_ManConst1(p), f ); @@ -193,18 +198,19 @@ Vec_Ptr_t * Saig_AbsCreateFrames( Aig_Man_t * p, int nFramesMax, int fVerbose ) Vec_PtrClear( vLoObjs ); Vec_PtrClear( vLiObjs ); Aig_ManForEachPi( p, pObj, i ) - { + { if ( Saig_AbsVisited( vObj2Visit, Aig_ManObjNumMax(p), pObj, f ) ) { pObj->pData = Aig_ObjCreatePi(pFrame); if ( i >= Saig_ManPiNum(p) ) Vec_PtrPush( vLoObjs, pObj ); - } + } } // remember the number of (implicit) registers in this frame pFrame->nAsserts = Vec_PtrSize(vLoObjs); // create POs Aig_ManForEachPo( p, pObj, i ) + { if ( Saig_AbsVisited( vObj2Visit, Aig_ManObjNumMax(p), pObj, f ) ) { Saig_AbsCreateFrames_rec( pFrame, Aig_ObjFanin0(pObj) ); @@ -212,8 +218,10 @@ Vec_Ptr_t * Saig_AbsCreateFrames( Aig_Man_t * p, int nFramesMax, int fVerbose ) if ( i >= Saig_ManPoNum(p) ) Vec_PtrPush( vLiObjs, pObj ); } - Vec_PtrPush( vFrames, Cnf_Derive(pFrame, Aig_ManPoNum(pFrame)) ); - // set the new PIs to point to the recorresponding registers + } +// Vec_PtrPush( vFrames, Cnf_Derive(pFrame, Aig_ManPoNum(pFrame)) ); + Vec_PtrPush( vFrames, Cnf_DeriveSimple(pFrame, Aig_ManPoNum(pFrame)) ); + // set the new PIs to point to the corresponding registers Aig_ManCleanData( pFrame ); Vec_PtrForEachEntry( vLoObjs, pObj, i ) ((Aig_Obj_t *)pObj->pData)->pData = pObj; @@ -290,7 +298,10 @@ sat_solver * Saig_AbsCreateSolverDyn( Aig_Man_t * p, Vec_Ptr_t * vFrames ) // add auxiliary clauses (output, connectors, initial) // add output clause if ( !sat_solver_addclause( pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits) ) ) + { + printf( "SAT solver is not created correctly.\n" ); assert( 0 ); + } Vec_IntFree( vPoLits ); // add connecting clauses @@ -627,7 +638,7 @@ void Saig_AbsExtendOneStep( Aig_Man_t * p, Vec_Int_t * vFlops ) /**Function************************************************************* - Synopsis [Performs proof-based abstraction using BMC of the given depth.] + Synopsis [Derive a new counter-example.] Description [] @@ -636,63 +647,194 @@ void Saig_AbsExtendOneStep( Aig_Man_t * p, Vec_Int_t * vFlops ) SeeAlso [] ***********************************************************************/ -Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fDynamic, int fExtend, int fVerbose ) +Ssw_Cex_t * Saig_ManCexShrink( Aig_Man_t * p, Aig_Man_t * pAbs, Ssw_Cex_t * pCexAbs ) { - Aig_Man_t * pResult; - Cnf_Dat_t * pCnf; - Vec_Ptr_t * vFrames; - sat_solver * pSat; - Vec_Int_t * vCore; - Vec_Int_t * vFlops; - int clk = clock(), clk2 = clock(); - assert( Aig_ManRegNum(p) > 0 ); - Aig_ManSetPioNumbers( p ); - if ( fVerbose ) - printf( "Performing proof-based abstraction with %d frames and %d max conflicts.\n", nFrames, nConfMax ); - if ( fDynamic ) + Ssw_Cex_t * pCex; + Aig_Obj_t * pObj; + int i, f; + // start the counter-example + pCex = Ssw_SmlAllocCounterExample( Aig_ManRegNum(p), Saig_ManPiNum(p), pCexAbs->iFrame+1 ); + pCex->iFrame = pCexAbs->iFrame; + pCex->iPo = pCexAbs->iPo; + // copy the bit data + for ( f = 0; f <= pCexAbs->iFrame; f++ ) + { + Saig_ManForEachPi( pAbs, pObj, i ) + { + if ( i == Saig_ManPiNum(p) ) + break; + if ( Aig_InfoHasBit( pCexAbs->pData, pCexAbs->nRegs + pCexAbs->nPis * f + i ) ) + Aig_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * f + i ); + } + } + // verify the counter example + if ( !Ssw_SmlRunCounterExample( p, pCex ) ) { - // create CNF for the frames - vFrames = Saig_AbsCreateFrames( p, nFrames, fVerbose ); - // create dynamic solver - pSat = Saig_AbsCreateSolverDyn( p, vFrames ); + printf( "Saig_ManCexShrink(): Counter-example is invalid.\n" ); + Ssw_SmlFreeCounterExample( pCex ); + pCex = NULL; } else { - // create CNF for the AIG - pCnf = Cnf_DeriveSimple( p, Aig_ManPoNum(p) ); - // create SAT solver for the unrolled AIG - pSat = Saig_AbsCreateSolver( pCnf, nFrames ); + printf( "Counter-example verification is successful.\n" ); + printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). \n", pCex->iPo, pCex->iFrame ); + } + return pCex; +} + +/**Function************************************************************* + + Synopsis [Performs proof-based abstraction using BMC of the given depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManProofRefine( Aig_Man_t * p, Aig_Man_t * pAbs, Vec_Int_t * vFlops, int fVerbose ) +{ + extern void Saig_BmcPerform( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConfMaxOne, int nConfMaxAll, int fVerbose ); + extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, void * pCex, int fVerbose ); + + Vec_Int_t * vFlopsNew, * vPiToReg; + Aig_Obj_t * pObj; + int i, Entry, iFlop; + Saig_BmcPerform( pAbs, 2000, 2000, 5000, 1000000, fVerbose ); + if ( pAbs->pSeqModel == NULL ) + return NULL; +// Saig_ManExtendCounterExampleTest( p->pAig, 0, p->pAig->pSeqModel ); + vFlopsNew = Saig_ManExtendCounterExampleTest( pAbs, Saig_ManPiNum(p), pAbs->pSeqModel, fVerbose ); + if ( Vec_IntSize(vFlopsNew) == 0 ) + { + printf( "Discovered a true counter-example!\n" ); + p->pSeqModel = Saig_ManCexShrink( p, pAbs, pAbs->pSeqModel ); + Vec_IntFree( vFlopsNew ); + return NULL; } if ( fVerbose ) + printf( "Adding %d registers to the abstraction.\n", Vec_IntSize(vFlopsNew) ); + // vFlopsNew contains PI number that should be kept in pAbs + + // for each additional PI, collect the number of a register it stands for + Vec_IntForEachEntry( vFlops, Entry, i ) { - printf( "SAT solver: Vars = %7d. Clauses = %7d. ", pSat->size, pSat->stats.clauses ); - PRT( "Time", clock() - clk2 ); + pObj = Saig_ManLo( p, Entry ); + pObj->fMarkA = 1; } - // compute UNSAT core - vCore = Saig_AbsSolverUnsatCore( pSat, nConfMax, fVerbose ); - sat_solver_delete( pSat ); - if ( vCore == NULL ) + vPiToReg = Vec_IntAlloc( 1000 ); + Aig_ManForEachPi( p, pObj, i ) { - Saig_AbsFreeCnfs( vFrames ); - return NULL; + if ( pObj->fMarkA ) + { + pObj->fMarkA = 0; + continue; + } + if ( i < Saig_ManPiNum(p) ) + Vec_IntPush( vPiToReg, -1 ); + else + Vec_IntPush( vPiToReg, Aig_ObjPioNum(pObj)-Saig_ManPiNum(p) ); } // collect registers - if ( fDynamic ) + Vec_IntForEachEntry( vFlopsNew, Entry, i ) { - vFlops = Saig_AbsCollectRegistersDyn( p, vFrames, vCore ); - Saig_AbsFreeCnfs( vFrames ); + iFlop = Vec_IntEntry( vPiToReg, Entry ); + assert( iFlop >= 0 ); + assert( iFlop < Aig_ManRegNum(p) ); + Vec_IntPush( vFlops, iFlop ); } - else + Vec_IntFree( vPiToReg ); + Vec_IntFree( vFlopsNew ); + + Vec_IntSort( vFlops, 0 ); + Vec_IntForEachEntryStart( vFlops, Entry, i, 1 ) + assert( Vec_IntEntry(vFlops, i-1) != Entry ); + + return Saig_ManAbstraction( p, vFlops ); +} + +/**Function************************************************************* + + Synopsis [Performs proof-based abstraction using BMC of the given depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fDynamic, int fExtend, int fSkipProof, int fVerbose ) +{ + Aig_Man_t * pResult, * pTemp; + Cnf_Dat_t * pCnf; + Vec_Ptr_t * vFrames; + sat_solver * pSat; + Vec_Int_t * vCore; + Vec_Int_t * vFlops; + int Iter, clk = clock(), clk2 = clock(); + assert( Aig_ManRegNum(p) > 0 ); + Aig_ManSetPioNumbers( p ); + + if ( fSkipProof ) { - vFlops = Saig_AbsCollectRegisters( pCnf, nFrames, vCore ); - Cnf_DataFree( pCnf ); + assert( 0 ); + if ( fVerbose ) + printf( "Performing counter-example-based refinement.\n" ); +// vFlops = Vec_IntStartNatural( 100 ); +// Vec_IntPush( vFlops, 0 ); } - Vec_IntFree( vCore ); - if ( fVerbose ) + else { - printf( "The number of relevant registers is %d (out of %d). ", Vec_IntSize(vFlops), Aig_ManRegNum(p) ); - PRT( "Time", clock() - clk ); + if ( fVerbose ) + printf( "Performing proof-based abstraction with %d frames and %d max conflicts.\n", nFrames, nConfMax ); + if ( fDynamic ) + { + // create CNF for the frames + vFrames = Saig_AbsCreateFrames( p, nFrames, fVerbose ); + // create dynamic solver + pSat = Saig_AbsCreateSolverDyn( p, vFrames ); + } + else + { + // create CNF for the AIG + pCnf = Cnf_DeriveSimple( p, Aig_ManPoNum(p) ); + // create SAT solver for the unrolled AIG + pSat = Saig_AbsCreateSolver( pCnf, nFrames ); + } + if ( fVerbose ) + { + printf( "SAT solver: Vars = %7d. Clauses = %7d. ", pSat->size, pSat->stats.clauses ); + PRT( "Time", clock() - clk2 ); + } + // compute UNSAT core + vCore = Saig_AbsSolverUnsatCore( pSat, nConfMax, fVerbose ); + sat_solver_delete( pSat ); + if ( vCore == NULL ) + { + Saig_AbsFreeCnfs( vFrames ); + return NULL; + } + // collect registers + if ( fDynamic ) + { + vFlops = Saig_AbsCollectRegistersDyn( p, vFrames, vCore ); + Saig_AbsFreeCnfs( vFrames ); + } + else + { + vFlops = Saig_AbsCollectRegisters( pCnf, nFrames, vCore ); + Cnf_DataFree( pCnf ); + } + Vec_IntFree( vCore ); + if ( fVerbose ) + { + printf( "The number of relevant registers is %d (out of %d). ", Vec_IntSize(vFlops), Aig_ManRegNum(p) ); + PRT( "Time", clock() - clk ); + } } +/* // extend the abstraction if ( fExtend ) { @@ -702,8 +844,33 @@ Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, if ( fVerbose ) printf( " %d flops.\n", Vec_IntSize(vFlops) ); } +*/ // create the resulting AIG pResult = Saig_ManAbstraction( p, vFlops ); + + if ( fExtend ) + { + if ( !fVerbose ) + { + printf( "Init : " ); + Aig_ManPrintStats( pResult ); + } + printf( "Refining abstraction...\n" ); + for ( Iter = 0; ; Iter++ ) + { + pTemp = Saig_ManProofRefine( p, pResult, vFlops, fVerbose ); + if ( pTemp == NULL ) + break; + Aig_ManStop( pResult ); + pResult = pTemp; + printf( "%4d : ", Iter ); + if ( !fVerbose ) + Aig_ManPrintStats( pResult ); + else + printf( " -----------------------------------------------------\n" ); + } + } + Vec_IntFree( vFlops ); return pResult; } diff --git a/src/aig/saig/saigBmc.c b/src/aig/saig/saigBmc.c index a5235042..7cccce96 100644 --- a/src/aig/saig/saigBmc.c +++ b/src/aig/saig/saigBmc.c @@ -207,7 +207,7 @@ Aig_Obj_t * Saig_BmcIntervalExplore_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i SeeAlso [] ***********************************************************************/ -Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i ) +Aig_Obj_t * Saig_BmcIntervalConstruct_rec_OLD( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i ) { Aig_Obj_t * pRes; pRes = Saig_BmcObjFrame( p, pObj, i ); @@ -217,16 +217,16 @@ Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int if ( Saig_ObjIsPi( p->pAig, pObj ) ) pRes = Aig_ObjCreatePi(p->pFrm); else if ( Saig_ObjIsLo( p->pAig, pObj ) ) - pRes = Saig_BmcIntervalConstruct_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1 ); + pRes = Saig_BmcIntervalConstruct_rec_OLD( p, Saig_ObjLoToLi(p->pAig, pObj), i-1 ); else if ( Aig_ObjIsPo( pObj ) ) { - Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i ); + Saig_BmcIntervalConstruct_rec_OLD( p, Aig_ObjFanin0(pObj), i ); pRes = Saig_BmcObjChild0( p, pObj, i ); } else { - Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i ); - Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin1(pObj), i ); + Saig_BmcIntervalConstruct_rec_OLD( p, Aig_ObjFanin0(pObj), i ); + Saig_BmcIntervalConstruct_rec_OLD( p, Aig_ObjFanin1(pObj), i ); pRes = Aig_And( p->pFrm, Saig_BmcObjChild0(p, pObj, i), Saig_BmcObjChild1(p, pObj, i) ); } assert( pRes != AIG_VISITED ); @@ -234,6 +234,45 @@ Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int return pRes; } +/**Function************************************************************* + + Synopsis [Performs the actual construction of the output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i, Vec_Ptr_t * vVisited ) +{ + Aig_Obj_t * pRes; + pRes = Saig_BmcObjFrame( p, pObj, i ); + if ( pRes != NULL ) + return pRes; + if ( Saig_ObjIsPi( p->pAig, pObj ) ) + pRes = Aig_ObjCreatePi(p->pFrm); + else if ( Saig_ObjIsLo( p->pAig, pObj ) ) + pRes = Saig_BmcIntervalConstruct_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1, vVisited ); + else if ( Aig_ObjIsPo( pObj ) ) + { + Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited ); + pRes = Saig_BmcObjChild0( p, pObj, i ); + } + else + { + Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited ); + Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin1(pObj), i, vVisited ); + pRes = Aig_And( p->pFrm, Saig_BmcObjChild0(p, pObj, i), Saig_BmcObjChild1(p, pObj, i) ); + } + assert( pRes != NULL ); + Saig_BmcObjSetFrame( p, pObj, i, pRes ); + Vec_PtrPush( vVisited, pObj ); + Vec_PtrPush( vVisited, (void *)i ); + return pRes; +} + /**Function************************************************************* Synopsis [Adds new AIG nodes to the frames.] @@ -248,8 +287,8 @@ Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int void Saig_BmcInterval( Saig_Bmc_t * p ) { Aig_Obj_t * pTarget; -// Aig_Obj_t * pObj; -// int i; + Aig_Obj_t * pObj, * pRes; + int i, iFrame; int nNodes = Aig_ManObjNum( p->pFrm ); Vec_PtrClear( p->vTargets ); p->iFramePrev = p->iFrameLast; @@ -258,21 +297,25 @@ void Saig_BmcInterval( Saig_Bmc_t * p ) if ( p->iOutputLast == 0 ) { Saig_BmcObjSetFrame( p, Aig_ManConst1(p->pAig), p->iFrameLast, Aig_ManConst1(p->pFrm) ); -// Saig_ManForEachPi( p->pAig, pObj, i ) -// Saig_BmcObjSetFrame( p, pObj, p->iFrameLast, Aig_ObjCreatePi(p->pFrm) ); } for ( ; p->iOutputLast < Saig_ManPoNum(p->pAig); p->iOutputLast++ ) { if ( Aig_ManObjNum(p->pFrm) >= nNodes + p->nNodesMax ) return; - Saig_BmcIntervalExplore_rec( p, Aig_ManPo(p->pAig, p->iOutputLast), p->iFrameLast ); - pTarget = Saig_BmcIntervalConstruct_rec( p, Aig_ManPo(p->pAig, p->iOutputLast), p->iFrameLast ); - - ///////// -// if ( Aig_ObjIsConst1(Aig_Regular(pTarget)) ) -// continue; - +// Saig_BmcIntervalExplore_rec( p, Aig_ManPo(p->pAig, p->iOutputLast), p->iFrameLast ); + Vec_PtrClear( p->vVisited ); + pTarget = Saig_BmcIntervalConstruct_rec( p, Aig_ManPo(p->pAig, p->iOutputLast), p->iFrameLast, p->vVisited ); Vec_PtrPush( p->vTargets, pTarget ); + Aig_ObjCreatePo( p->pFrm, pTarget ); + Aig_ManCleanup( p->pFrm ); + // check if the node is gone + Vec_PtrForEachEntry( p->vVisited, pObj, i ) + { + iFrame = (int)(PORT_PTRINT_T)Vec_PtrEntry( p->vVisited, 1+i++ ); + pRes = Saig_BmcObjFrame( p, pObj, iFrame ); + if ( Aig_ObjIsNone( Aig_Regular(pRes) ) ) + Saig_BmcObjSetFrame( p, pObj, iFrame, NULL ); + } } } } @@ -489,6 +532,11 @@ int Saig_BmcSolveTargets( Saig_Bmc_t * p ) // generate counter-example Saig_BmcDeriveFailed( p, i ); p->pAig->pSeqModel = Saig_BmcGenerateCounterExample( p ); + + { +// extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, void * pCex ); +// Saig_ManExtendCounterExampleTest( p->pAig, 0, p->pAig->pSeqModel ); + } return l_True; } return l_False; @@ -564,7 +612,7 @@ void Saig_BmcPerform( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConf RetValue = Saig_BmcSolveTargets( p ); if ( fVerbose ) { - printf( "%3d : F = %3d. O = %3d. And = %7d. Var = %7d. Conf = %7d. ", + printf( "%3d : F = %3d. O =%4d. And = %7d. Var = %7d. Conf = %7d. ", Iter, p->iFrameLast, p->iOutputLast, Aig_ManNodeNum(p->pFrm), p->nSatVars, (int)p->pSat->stats.conflicts ); PRT( "Time", clock() - clk2 ); } diff --git a/src/aig/saig/saigDup.c b/src/aig/saig/saigDup.c index 61ea6ca0..e6534a1f 100644 --- a/src/aig/saig/saigDup.c +++ b/src/aig/saig/saigDup.c @@ -46,6 +46,7 @@ Aig_Man_t * Said_ManDupOrpos( Aig_Man_t * pAig ) int i; // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Aig_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs @@ -80,11 +81,12 @@ Aig_Man_t * Said_ManDupOrpos( Aig_Man_t * pAig ) ***********************************************************************/ Aig_Man_t * Saig_ManAbstraction( Aig_Man_t * pAig, Vec_Int_t * vFlops ) { - Aig_Man_t * pAigNew; + Aig_Man_t * pAigNew;//, * pTemp; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, Entry; // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Aig_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // label included flops @@ -123,6 +125,8 @@ Aig_Man_t * Saig_ManAbstraction( Aig_Man_t * pAig, Vec_Int_t * vFlops ) } Aig_ManSetRegNum( pAigNew, Vec_IntSize(vFlops) ); Aig_ManSeqCleanup( pAigNew ); +// pAigNew = Aig_ManDupSimpleDfs( pTemp = pAigNew ); +// Aig_ManStop( pTemp ); return pAigNew; } diff --git a/src/aig/saig/saigLoc.c b/src/aig/saig/saigLoc.c deleted file mode 100644 index edbf231c..00000000 --- a/src/aig/saig/saigLoc.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [saigLoc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Sequential AIG package.] - - Synopsis [Localization.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: saigLoc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "saig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/saig/saigMiter.c b/src/aig/saig/saigMiter.c index 84c8a4fe..6c4b3af0 100644 --- a/src/aig/saig/saigMiter.c +++ b/src/aig/saig/saigMiter.c @@ -28,6 +28,60 @@ /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [Checks the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p ) +{ + Sec_MtrStatus_t Status; + Aig_Obj_t * pObj, * pChild; + int i; + memset( &Status, 0, sizeof(Sec_MtrStatus_t) ); + Status.iOut = -1; + Status.nInputs = Saig_ManPiNum( p ); + Status.nNodes = Aig_ManNodeNum( p ); + Status.nOutputs = Saig_ManPoNum(p); + Saig_ManForEachPo( p, pObj, i ) + { + pChild = Aig_ObjChild0(pObj); + // check if the output is constant 0 + if ( pChild == Aig_ManConst0(p) ) + Status.nUnsat++; + // check if the output is constant 1 + else if ( pChild == Aig_ManConst1(p) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + // check if the output is a primary input + else if ( Saig_ObjIsPi(p, Aig_Regular(pChild)) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + // check if the output is 1 for the 0000 pattern + else if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + else + Status.nUndec++; + } + return Status; +} + /**Function************************************************************* Synopsis [Creates sequential miter.] @@ -141,6 +195,116 @@ Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) return pNew; } +/**Function************************************************************* + + Synopsis [Derives dual-rail AIG.] + + Description [Orders nodes as follows: PIs, ANDs, POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_AndDualRail( Aig_Man_t * pNew, Aig_Obj_t * pObj, Aig_Obj_t ** ppData, Aig_Obj_t ** ppNext ) +{ + Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); + Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); + Aig_Obj_t * p0Data = Aig_ObjFaninC0(pObj)? pFanin0->pNext : pFanin0->pData; + Aig_Obj_t * p0Next = Aig_ObjFaninC0(pObj)? pFanin0->pData : pFanin0->pNext; + Aig_Obj_t * p1Data = Aig_ObjFaninC1(pObj)? pFanin1->pNext : pFanin1->pData; + Aig_Obj_t * p1Next = Aig_ObjFaninC1(pObj)? pFanin1->pData : pFanin1->pNext; + *ppData = Aig_Or( pNew, + Aig_And(pNew, p0Data, Aig_Not(p0Next)), + Aig_And(pNew, p1Data, Aig_Not(p1Next)) ); + *ppNext = Aig_And( pNew, + Aig_And(pNew, Aig_Not(p0Data), p0Next), + Aig_And(pNew, Aig_Not(p1Data), p1Next) ); +} + +/**Function************************************************************* + + Synopsis [Derives dual-rail AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pMiter; + int i; + Aig_ManCleanData( p ); + Aig_ManCleanNext( p ); + // create the new manager + pNew = Aig_ManStart( 4*Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManConst1(p)->pData = Aig_ManConst0(pNew); + Aig_ManConst1(p)->pNext = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + { + pObj->pData = Aig_ObjCreatePi( pNew ); + pObj->pNext = Aig_ObjCreatePi( pNew ); + } + // duplicate internal nodes + Aig_ManForEachNode( p, pObj, i ) + Saig_AndDualRail( pNew, pObj, (Aig_Obj_t **)&pObj->pData, &pObj->pNext ); + // add the POs + if ( fMiter ) + { + pMiter = Aig_ManConst1(pNew); + Saig_ManForEachLo( p, pObj, i ) + { + pMiter = Aig_And( pNew, pMiter, + Aig_Or(pNew, pObj->pData, pObj->pNext) ); + } + Aig_ObjCreatePo( pNew, pMiter ); + Saig_ManForEachLi( p, pObj, i ) + { + if ( !Aig_ObjFaninC0(pObj) ) + { + Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pData ); + Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pNext ); + } + else + { + Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pNext ); + Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pData ); + } + } + } + else + { + Aig_ManForEachPo( p, pObj, i ) + { + if ( !Aig_ObjFaninC0(pObj) ) + { + Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pData ); + Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pNext ); + } + else + { + Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pNext ); + Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pData ); + } + } + } + Aig_ManSetRegNum( pNew, 2*Aig_ManRegNum(p) ); + Aig_ManCleanData( p ); + Aig_ManCleanNext( p ); + Aig_ManCleanup( pNew ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupSimple(): The check has failed.\n" ); + return pNew; +} + /**Function************************************************************* Synopsis [Create combinational timeframes by unrolling sequential circuits.] @@ -392,7 +556,7 @@ int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** Vec_Ptr_t * vSet0, * vSet1; Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1; int i, Counter = 0; - assert( Saig_ManRegNum(p) % 2 == 0 ); +// assert( Saig_ManRegNum(p) % 2 == 0 ); vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); Saig_ManForEachPo( p, pObj, i ) @@ -773,27 +937,47 @@ PRT( "Time", clock() - clkTotal ); SeeAlso [] ***********************************************************************/ -int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose ) +int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose ) { - int nFrames = 2; // modify to enable comparison over any number of frames Aig_Man_t * pPart0, * pPart1; int RetValue; if ( fVerbose ) - Aig_ManPrintStats( pMiter ); - // demiter the miter - if ( !Saig_ManDemiterSimple( pMiter, &pPart0, &pPart1 ) ) + printf( "Performing sequential verification combinational A/B miter.\n" ); + // consider the case when a miter is given + if ( p1 == NULL ) { - printf( "Demitering has failed.\n" ); - return -1; + if ( fVerbose ) + { + Aig_ManPrintStats( p0 ); + } + // demiter the miter + if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) + { + printf( "Demitering has failed.\n" ); + return -1; + } + } + else + { + pPart0 = Aig_ManDupSimple( p0 ); + pPart1 = Aig_ManDupSimple( p1 ); } if ( fVerbose ) { - Aig_ManPrintStats( pPart0 ); - Aig_ManPrintStats( pPart1 ); - Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL ); - Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); - printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" ); +// Aig_ManPrintStats( pPart0 ); +// Aig_ManPrintStats( pPart1 ); + if ( p1 == NULL ) + { +// Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL ); +// Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); +// printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" ); + } } + assert( Aig_ManRegNum(pPart0) > 0 ); + assert( Aig_ManRegNum(pPart1) > 0 ); + assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) ); + assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) ); + assert( Aig_ManRegNum(pPart0) == Aig_ManRegNum(pPart1) ); RetValue = Ssw_SecSpecial( pPart0, pPart1, nFrames, fVerbose ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); diff --git a/src/aig/saig/saigPhase.c b/src/aig/saig/saigPhase.c index 0f0b1c06..c6d84066 100644 --- a/src/aig/saig/saigPhase.c +++ b/src/aig/saig/saigPhase.c @@ -468,7 +468,7 @@ void Saig_TsiStateOrAll( Saig_Tsim_t * pTsi, unsigned * pState ) SeeAlso [] ***********************************************************************/ -Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits ) +Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits, int fVerbose ) { Saig_Tsim_t * pTsi; Aig_Obj_t * pObj, * pObjLi, * pObjLo; @@ -507,7 +507,11 @@ Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits ) // Saig_TsiStatePrint( pTsi, pState ); // check if this state exists if ( Saig_TsiStateLookup( pTsi, pState, pTsi->nWords ) ) + { + if ( fVerbose ) + printf( "Ternary simulation converged after %d iterations.\n", f ); return pTsi; + } // insert this state Saig_TsiStateInsert( pTsi, pState, pTsi->nWords ); // simulate internal nodes @@ -781,7 +785,7 @@ Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrame assert( Saig_ManPiNum(p) ); assert( Saig_ManPoNum(p) ); // perform terminary simulation - pTsi = Saig_ManReachableTernary( p, vInits ); + pTsi = Saig_ManReachableTernary( p, vInits, fVerbose ); if ( pTsi == NULL ) return NULL; // derive information @@ -837,7 +841,7 @@ Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose ) assert( Saig_ManPiNum(p) ); assert( Saig_ManPoNum(p) ); // perform terminary simulation - pTsi = Saig_ManReachableTernary( p, NULL ); + pTsi = Saig_ManReachableTernary( p, NULL, fVerbose ); if ( pTsi == NULL ) return NULL; // derive information diff --git a/src/aig/saig/saigSimExt.c b/src/aig/saig/saigSimExt.c new file mode 100644 index 00000000..49c85ff4 --- /dev/null +++ b/src/aig/saig/saigSimExt.c @@ -0,0 +1,325 @@ +/**CFile**************************************************************** + + FileName [saigSimExt.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Extending simulation trace to contain ternary values.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSimExt.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "ssw.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SAIG_ZER 1 +#define SAIG_ONE 2 +#define SAIG_UND 3 + +static inline int Saig_ManSimInfoNot( int Value ) +{ + if ( Value == SAIG_ZER ) + return SAIG_ONE; + if ( Value == SAIG_ONE ) + return SAIG_ZER; + return SAIG_UND; +} + +static inline int Saig_ManSimInfoAnd( int Value0, int Value1 ) +{ + if ( Value0 == SAIG_ZER || Value1 == SAIG_ZER ) + return SAIG_ZER; + if ( Value0 == SAIG_ONE && Value1 == SAIG_ONE ) + return SAIG_ONE; + return SAIG_UND; +} + +static inline int Saig_ManSimInfoGet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame ) +{ + unsigned * pInfo = Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) ); + return 3 & (pInfo[iFrame >> 4] >> ((iFrame & 15) << 1)); +} + +static inline void Saig_ManSimInfoSet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value ) +{ + unsigned * pInfo = Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) ); + assert( Value >= SAIG_ZER && Value <= SAIG_UND ); + Value ^= Saig_ManSimInfoGet( vSimInfo, pObj, iFrame ); + pInfo[iFrame >> 4] ^= (Value << ((iFrame & 15) << 1)); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs ternary simulation for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManExtendOneEval( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame ) +{ + int Value0, Value1, Value; + Value0 = Saig_ManSimInfoGet( vSimInfo, Aig_ObjFanin0(pObj), iFrame ); + if ( Aig_ObjFaninC0(pObj) ) + Value0 = Saig_ManSimInfoNot( Value0 ); + if ( Aig_ObjIsPo(pObj) ) + { + Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value0 ); + return Value0; + } + assert( Aig_ObjIsNode(pObj) ); + Value1 = Saig_ManSimInfoGet( vSimInfo, Aig_ObjFanin1(pObj), iFrame ); + if ( Aig_ObjFaninC1(pObj) ) + Value1 = Saig_ManSimInfoNot( Value1 ); + Value = Saig_ManSimInfoAnd( Value0, Value1 ); + Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value ); + return Value; +} + +/**Function************************************************************* + + Synopsis [Performs ternary simulation for one design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManSimDataInit( Aig_Man_t * p, Ssw_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes ) +{ + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f, Entry, iBit = 0; + Saig_ManForEachLo( p, pObj, i ) + Saig_ManSimInfoSet( vSimInfo, pObj, 0, Aig_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER ); + for ( f = 0; f <= pCex->iFrame; f++ ) + { + Saig_ManSimInfoSet( vSimInfo, Aig_ManConst1(p), f, SAIG_ONE ); + Saig_ManForEachPi( p, pObj, i ) + Saig_ManSimInfoSet( vSimInfo, pObj, f, Aig_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER ); + if ( vRes ) + Vec_IntForEachEntry( vRes, Entry, i ) + Saig_ManSimInfoSet( vSimInfo, Aig_ManPi(p, Entry), f, SAIG_UND ); + Aig_ManForEachNode( p, pObj, i ) + Saig_ManExtendOneEval( vSimInfo, pObj, f ); + Aig_ManForEachPo( p, pObj, i ) + Saig_ManExtendOneEval( vSimInfo, pObj, f ); + if ( f == pCex->iFrame ) + break; + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + Saig_ManSimInfoSet( vSimInfo, pObjLo, f+1, Saig_ManSimInfoGet(vSimInfo, pObjLi, f) ); + } + // make sure the output of the property failed + pObj = Aig_ManPo( p, pCex->iPo ); + return Saig_ManSimInfoGet( vSimInfo, pObj, pCex->iFrame ); +} + +/**Function************************************************************* + + Synopsis [Tries to assign ternary value to one of the primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManExtendOne( Aig_Man_t * p, Ssw_Cex_t * pCex, Vec_Ptr_t * vSimInfo, + int iPi, int iFrame, Vec_Int_t * vUndo, Vec_Int_t * vVis, Vec_Int_t * vVis2 ) +{ + Aig_Obj_t * pFanout, * pObj = Aig_ManPi(p, iPi); + int i, k, f, iFanout, Value, Value2, Entry; + // save original value + Value = Saig_ManSimInfoGet( vSimInfo, pObj, iFrame ); + assert( Value == SAIG_ZER || Value == SAIG_ONE ); + Vec_IntPush( vUndo, Aig_ObjId(pObj) ); + Vec_IntPush( vUndo, iFrame ); + Vec_IntPush( vUndo, Value ); + // update original value + Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, SAIG_UND ); + // traverse + Vec_IntClear( vVis ); + Vec_IntPush( vVis, Aig_ObjId(pObj) ); + for ( f = iFrame; f <= pCex->iFrame; f++ ) + { + Vec_IntClear( vVis2 ); + Vec_IntForEachEntry( vVis, Entry, i ) + { + pObj = Aig_ManObj( p, Entry ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) + { + assert( Aig_ObjId(pObj) < Aig_ObjId(pFanout) ); + Value = Saig_ManSimInfoGet( vSimInfo, pFanout, f ); + if ( Value == SAIG_UND ) + continue; + Value2 = Saig_ManExtendOneEval( vSimInfo, pFanout, f ); + if ( Value2 == Value ) + continue; + assert( Value2 == SAIG_UND ); +// assert( Vec_IntFind(vVis, Aig_ObjId(pFanout)) == -1 ); + if ( Aig_ObjIsNode(pFanout) ) + Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) ); + else if ( Saig_ObjIsLi(p, pFanout) ) + Vec_IntPush( vVis2, Aig_ObjId(pFanout) ); + Vec_IntPush( vUndo, Aig_ObjId(pFanout) ); + Vec_IntPush( vUndo, f ); + Vec_IntPush( vUndo, Value ); + } + } + if ( Vec_IntSize(vVis2) == 0 ) + break; + if ( f == pCex->iFrame ) + break; + // transfer + Vec_IntClear( vVis ); + Vec_IntForEachEntry( vVis2, Entry, i ) + { + pObj = Aig_ManObj( p, Entry ); + assert( Saig_ObjIsLi(p, pObj) ); + pFanout = Saig_ObjLiToLo( p, pObj ); + Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) ); + Value = Saig_ManSimInfoGet( vSimInfo, pObj, f ); + Saig_ManSimInfoSet( vSimInfo, pFanout, f+1, Value ); + } + } + // check the output + pObj = Aig_ManPo( p, pCex->iPo ); + Value = Saig_ManSimInfoGet( vSimInfo, pObj, pCex->iFrame ); + assert( Value == SAIG_ONE || Value == SAIG_UND ); + return (int)(Value == SAIG_ONE); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManExtendUndo( Aig_Man_t * p, Vec_Ptr_t * vSimInfo, Vec_Int_t * vUndo ) +{ + Aig_Obj_t * pObj; + int i, iFrame, Value; + for ( i = 0; i < Vec_IntSize(vUndo); i += 3 ) + { + pObj = Aig_ManObj( p, Vec_IntEntry(vUndo, i) ); + iFrame = Vec_IntEntry(vUndo, i+1); + Value = Vec_IntEntry(vUndo, i+2); + assert( Saig_ManSimInfoGet(vSimInfo, pObj, iFrame) == SAIG_UND ); + Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the array of PIs for flops that should not be absracted.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManExtendCounterExample( Aig_Man_t * p, int iFirstPi, Ssw_Cex_t * pCex, Vec_Ptr_t * vSimInfo, int fVerbose ) +{ + Vec_Int_t * vRes, * vResInv, * vUndo, * vVis, * vVis2; + int i, f, Value; + assert( Aig_ManRegNum(p) > 0 ); + assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Aig_BitWordNum(2*(pCex->iFrame+1)) ); + // start simulation data + Value = Saig_ManSimDataInit( p, pCex, vSimInfo, NULL ); + assert( Value == SAIG_ONE ); + // select the result + vRes = Vec_IntAlloc( 1000 ); + vResInv = Vec_IntAlloc( 1000 ); + vVis = Vec_IntAlloc( 1000 ); + vVis2 = Vec_IntAlloc( 1000 ); + vUndo = Vec_IntAlloc( 1000 ); + for ( i = iFirstPi; i < Saig_ManPiNum(p); i++ ) + { + Vec_IntClear( vUndo ); + for ( f = pCex->iFrame; f >= 0; f-- ) + if ( !Saig_ManExtendOne( p, pCex, vSimInfo, i, f, vUndo, vVis, vVis2 ) ) + { + Saig_ManExtendUndo( p, vSimInfo, vUndo ); + break; + } + if ( f >= 0 ) + Vec_IntPush( vRes, i ); + else + Vec_IntPush( vResInv, i ); + } + Vec_IntFree( vVis ); + Vec_IntFree( vVis2 ); + Vec_IntFree( vUndo ); + // resimulate to make sure it is valid + Value = Saig_ManSimDataInit( p, pCex, vSimInfo, vResInv ); + assert( Value == SAIG_ONE ); + Vec_IntFree( vResInv ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Returns the array of PIs for flops that should not be absracted.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, Ssw_Cex_t * pCex, int fVerbose ) +{ + Vec_Int_t * vRes; + Vec_Ptr_t * vSimInfo; + int clk; + Aig_ManFanoutStart( p ); + vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Aig_BitWordNum(2*(pCex->iFrame+1)) ); +clk = clock(); + vRes = Saig_ManExtendCounterExample( p, iFirstPi, pCex, vSimInfo, fVerbose ); + if ( fVerbose ) + { + printf( "Total new PIs = %3d. Non-removable PIs = %3d. ", Saig_ManPiNum(p)-iFirstPi, Vec_IntSize(vRes) ); +PRT( "Time", clock() - clk ); + } + Vec_PtrFree( vSimInfo ); + Aig_ManFanoutStop( p ); + return vRes; +// Vec_IntFree( vRes ); +// return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/saig/saigSimFast.c b/src/aig/saig/saigSimFast.c new file mode 100644 index 00000000..09bb6a06 --- /dev/null +++ b/src/aig/saig/saigSimFast.c @@ -0,0 +1,443 @@ +/**CFile**************************************************************** + + FileName [saigSimFast.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Fast sequential AIG simulator.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSimFast.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the AIG manager +typedef struct Faig_Man_t_ Faig_Man_t; +struct Faig_Man_t_ +{ + // parameters + int nPis; + int nPos; + int nCis; + int nCos; + int nFfs; + int nNos; + // offsets + int nPis1; + int nCis1; + int nCisNos1; + int nCisNosPos1; + int nObjs; + // allocated data + int nWords; + int pObjs[0]; +}; + +static inline int Faig_CheckIdPi( Faig_Man_t * p, int i ) { return i >= 1 && i < p->nPis1; } +static inline int Faig_CheckIdLo( Faig_Man_t * p, int i ) { return i >= p->nPis1 && i < p->nCis1; } +static inline int Faig_CheckIdNo( Faig_Man_t * p, int i ) { return i >= p->nCis1 && i < p->nCisNos1; } +static inline int Faig_CheckIdPo( Faig_Man_t * p, int i ) { return i >= p->nCisNos1 && i < p->nCisNosPos1; } +static inline int Faig_CheckIdLi( Faig_Man_t * p, int i ) { return i >= p->nCisNosPos1 && i < p->nObjs; } +static inline int Faig_CheckIdCo( Faig_Man_t * p, int i ) { return i >= p->nCisNos1 && i < p->nObjs; } +static inline int Faig_CheckIdObj( Faig_Man_t * p, int i ) { return i >= 0 && i < p->nObjs; } + +static inline int Faig_ObjIdToNumPi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPi(p,i) ); return i - 1; } +static inline int Faig_ObjIdToNumLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return i - p->nPis1; } +static inline int Faig_ObjIdToNumNo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdNo(p,i) ); return i - p->nCis1; } +static inline int Faig_ObjIdToNumPo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPo(p,i) ); return i - p->nCisNos1; } +static inline int Faig_ObjIdToNumLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return i - p->nCisNosPos1; } +static inline int Faig_ObjIdToNumCo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdCo(p,i) ); return i - p->nCisNos1; } + +static inline int Faig_ObjLoToLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return p->nObjs - (p->nCis1 - i); } +static inline int Faig_ObjLiToLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return p->nCis1 - (p->nObjs - i); } + +static inline int Faig_NodeChild0( Faig_Man_t * p, int n ) { return p->pObjs[n<<1]; } +static inline int Faig_NodeChild1( Faig_Man_t * p, int n ) { return p->pObjs[(n<<1)+1]; } +static inline int Faig_CoChild0( Faig_Man_t * p, int n ) { return p->pObjs[(p->nNos<<1)+n]; } +static inline int Faig_ObjFaninC( int iFan ) { return iFan & 1; } +static inline int Faig_ObjFanin( int iFan ) { return iFan >> 1; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if the manager is correct.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Faig_ManIsCorrect( Aig_Man_t * pAig ) +{ + return Aig_ManObjNumMax(pAig) == + 1 + Aig_ManPiNum(pAig) + Aig_ManNodeNum(pAig) + Aig_ManPoNum(pAig); +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Faig_Man_t * Faig_ManAlloc( Aig_Man_t * pAig ) +{ + Faig_Man_t * p; + int nWords; +// assert( Faig_ManIsCorrect(pAig) ); + nWords = 2 * Aig_ManNodeNum(pAig) + Aig_ManPoNum(pAig); + p = (Faig_Man_t *)ALLOC( char, sizeof(Faig_Man_t) + sizeof(int) * nWords ); +//printf( "Allocating %7.2f Mb.\n", 1.0 * (sizeof(Faig_Man_t) + sizeof(int) * nWords)/(1<<20) ); + memset( p, 0, sizeof(Faig_Man_t) ); + p->nPis = Aig_ManPiNum(pAig) - Aig_ManRegNum(pAig); + p->nPos = Aig_ManPoNum(pAig) - Aig_ManRegNum(pAig); + p->nCis = Aig_ManPiNum(pAig); + p->nCos = Aig_ManPoNum(pAig); + p->nFfs = Aig_ManRegNum(pAig); + p->nNos = Aig_ManNodeNum(pAig); + // offsets + p->nPis1 = p->nPis + 1; + p->nCis1 = p->nCis + 1; + p->nCisNos1 = p->nCis + p->nNos + 1; + p->nCisNosPos1 = p->nCis + p->nNos + p->nPos + 1; + p->nObjs = p->nCis + p->nNos + p->nCos + 1; + p->nWords = nWords; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Faig_Man_t * Faig_ManCreate( Aig_Man_t * pAig ) +{ + Faig_Man_t * p; + Aig_Obj_t * pObj; + int i, iWord = 0; + p = Faig_ManAlloc( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + { + p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); + p->pObjs[iWord++] = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); + } + Aig_ManForEachPo( pAig, pObj, i ) + p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); + assert( iWord == p->nWords ); + return p; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Faig_SimulateNode( Faig_Man_t * p, int Id, unsigned * pSimInfo ) +{ + int n = Faig_ObjIdToNumNo( p, Id ); + int iFan0 = Faig_NodeChild0( p, n ); + int iFan1 = Faig_NodeChild1( p, n ); + if ( Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) ) + return ~(pSimInfo[Faig_ObjFanin(iFan0)] | pSimInfo[Faig_ObjFanin(iFan1)]); + if ( Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) ) + return (~pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]); + if ( !Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) ) + return (pSimInfo[Faig_ObjFanin(iFan0)] & ~pSimInfo[Faig_ObjFanin(iFan1)]); + // if ( !Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) ) + return (pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]); +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Faig_SimulateCo( Faig_Man_t * p, int Id, unsigned * pSimInfo ) +{ + int n = Faig_ObjIdToNumCo( p, Id ); + int iFan0 = Faig_CoChild0( p, n ); + if ( Faig_ObjFaninC(iFan0) ) + return ~pSimInfo[Faig_ObjFanin(iFan0)]; + // if ( !Faig_ObjFaninC(iFan0) ) + return pSimInfo[Faig_ObjFanin(iFan0)]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Faig_SimulateRandomShift( unsigned uOld ) +{ + return (uOld << 16) | ((uOld ^ Aig_ManRandom(0)) & 0xffff); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Faig_SimulateTransferShift( unsigned uOld, unsigned uNew ) +{ + return (uOld << 16) | (uNew & 0xffff); +} + +/**Function************************************************************* + + Synopsis [Simulates the timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Faig_ManSimulateFrames( Faig_Man_t * p, int nFrames, int nPref, int fTrans ) +{ + int * pNumOnes = CALLOC( unsigned, p->nObjs ); + unsigned * pSimInfo = ALLOC( unsigned, p->nObjs ); + int f, i; +//printf( "Allocating %7.2f Mb.\n", 1.0 * 4 * p->nObjs/(1<<20) ); +//printf( "Allocating %7.2f Mb.\n", 1.0 * 4 * p->nObjs/(1<<20) ); + // set constant 1 + pSimInfo[0] = ~0; + for ( f = 0; f < nFrames; f++ ) + { + if ( fTrans ) + { + for ( i = 1; i < p->nPis1; i++ ) + pSimInfo[i] = f? Faig_SimulateRandomShift( pSimInfo[i] ) : Aig_ManRandom( 0 ); + for ( ; i < p->nCis1; i++ ) + pSimInfo[i] = f? Faig_SimulateTransferShift( pSimInfo[i], pSimInfo[Faig_ObjLoToLi(p,i)] ) : 0; + } + else + { + for ( i = 1; i < p->nPis1; i++ ) + pSimInfo[i] = Aig_ManRandom( 0 ); + for ( ; i < p->nCis1; i++ ) + pSimInfo[i] = f? pSimInfo[Faig_ObjLoToLi(p,i)] : 0; + } + for ( ; i < p->nCisNos1; i++ ) + pSimInfo[i] = Faig_SimulateNode( p, i, pSimInfo ); + for ( ; i < p->nObjs; i++ ) + pSimInfo[i] = Faig_SimulateCo( p, i, pSimInfo ); + if ( f < nPref ) + continue; + if ( fTrans ) + { + for ( i = 0; i < p->nObjs; i++ ) + pNumOnes[i] += Aig_WordCountOnes( (pSimInfo[i] ^ (pSimInfo[i] >> 16)) & 0xffff ); + } + else + { + for ( i = 0; i < p->nObjs; i++ ) + pNumOnes[i] += Aig_WordCountOnes( pSimInfo[i] ); + } + } + free( pSimInfo ); + return pNumOnes; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Faig_ManComputeSwitching( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Faig_ManComputeProbOne( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)nOnes / nTotal; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Faig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + extern char * Abc_FrameReadFlag( char * pFlag ); + int fTrans = 1; + Faig_Man_t * pAig; + Vec_Int_t * vSwitching; + int * pProbs; + float * pSwitching; + int nFramesReal, clk, clkTotal = clock(); + if ( fProbOne ) + fTrans = 0; + vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) ); + pSwitching = (float *)vSwitching->pArray; +clk = clock(); + pAig = Faig_ManCreate( p ); +//PRT( "\nCreation ", clock() - clk ); + Aig_ManRandom( 1 ); + // get the number of frames to simulate + // if the parameter "seqsimframes" is defined, use it + // otherwise, use the given number of frames "nFrames" + nFramesReal = nFrames; + if ( Abc_FrameReadFlag("seqsimframes") ) + nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") ); + if ( nFramesReal <= nPref ) + { + printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref ); + printf( "Setting the total number of frames to be %d.\n", nFrames ); + nFramesReal = nFrames; + } +//printf( "Simulating %d frames.\n", nFramesReal ); +clk = clock(); + pProbs = Faig_ManSimulateFrames( pAig, nFramesReal, nPref, fTrans ); +//PRT( "Simulation", clock() - clk ); +clk = clock(); + if ( fTrans ) + { + Aig_Obj_t * pObj; + int i, Counter = 0; + pObj = Aig_ManConst1(p); + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); + Aig_ManForEachPi( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); + Aig_ManForEachNode( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); + Aig_ManForEachPo( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); + assert( Counter == pAig->nObjs ); + } + else if ( fProbOne ) + { + Aig_Obj_t * pObj; + int i, Counter = 0; + pObj = Aig_ManConst1(p); + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachPi( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachNode( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachPo( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); + assert( Counter == pAig->nObjs ); + } + else + { + Aig_Obj_t * pObj; + int i, Counter = 0; + pObj = Aig_ManConst1(p); + pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachPi( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachNode( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachPo( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); + assert( Counter == pAig->nObjs ); + } + free( pProbs ); + free( pAig ); +//PRT( "Switch ", clock() - clk ); +//PRT( "TOTAL ", clock() - clkTotal ); + return vSwitching; +} + +/**Function************************************************************* + + Synopsis [Computes probability of switching (or of being 1).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + return Faig_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/saig/saigSimMv.c b/src/aig/saig/saigSimMv.c new file mode 100644 index 00000000..0e250a74 --- /dev/null +++ b/src/aig/saig/saigSimMv.c @@ -0,0 +1,726 @@ +/**CFile**************************************************************** + + FileName [saigSimMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Multi-valued simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSimMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SAIG_DIFF_VALUES 8 +#define SAIG_UNDEF_VALUE 0x1ffffffe //536870910 + +// old AIG +typedef struct Saig_MvObj_t_ Saig_MvObj_t; +struct Saig_MvObj_t_ +{ + int iFan0; + int iFan1; + unsigned Type : 3; + unsigned Value : 29; +}; + +// new AIG +typedef struct Saig_MvAnd_t_ Saig_MvAnd_t; +struct Saig_MvAnd_t_ +{ + int iFan0; + int iFan1; + int iNext; +}; + +// simulation manager +typedef struct Saig_MvMan_t_ Saig_MvMan_t; +struct Saig_MvMan_t_ +{ + // user data + Aig_Man_t * pAig; // original AIG + // parameters + int nStatesMax; // maximum number of states + int nLevelsMax; // maximum number of levels + int nValuesMax; // maximum number of values + int nFlops; // number of flops + // compacted AIG + Saig_MvObj_t * pAigOld; // AIG objects + Vec_Ptr_t * vFlops; // collected flops + Vec_Ptr_t * vTired; // collected flops + int * pTStates; // hash table for states + int nTStatesSize; // hash table size + Aig_MmFixed_t * pMemStates; // memory for states + Vec_Ptr_t * vStates; // reached states + int * pRegsUndef; // count the number of undef values + int ** pRegsValues; // write the first different values + int * nRegsValues; // count the number of different values + int nRUndefs; // the number of undef registers + int nRValues[SAIG_DIFF_VALUES+1]; // the number of registers with given values + // internal AIG + Saig_MvAnd_t * pAigNew; // AIG nodes + int nObjsAlloc; // the number of objects allocated + int nObjs; // the number of objects + int nPis; // the number of primary inputs + int * pTNodes; // hash table + int nTNodesSize; // hash table size + unsigned char * pLevels; // levels of AIG nodes +}; + +static inline int Saig_MvObjFaninC0( Saig_MvObj_t * pObj ) { return pObj->iFan0 & 1; } +static inline int Saig_MvObjFaninC1( Saig_MvObj_t * pObj ) { return pObj->iFan1 & 1; } +static inline int Saig_MvObjFanin0( Saig_MvObj_t * pObj ) { return pObj->iFan0 >> 1; } +static inline int Saig_MvObjFanin1( Saig_MvObj_t * pObj ) { return pObj->iFan1 >> 1; } + +static inline int Saig_MvConst0() { return 1; } +static inline int Saig_MvConst1() { return 0; } +static inline int Saig_MvConst( int c ) { return !c; } +static inline int Saig_MvUndef() { return SAIG_UNDEF_VALUE; } + +static inline int Saig_MvIsConst0( int iNode ) { return iNode == 1; } +static inline int Saig_MvIsConst1( int iNode ) { return iNode == 0; } +static inline int Saig_MvIsConst( int iNode ) { return iNode < 2; } +static inline int Saig_MvIsUndef( int iNode ) { return iNode == SAIG_UNDEF_VALUE;} + +static inline int Saig_MvRegular( int iNode ) { return (iNode & ~01); } +static inline int Saig_MvNot( int iNode ) { return (iNode ^ 01); } +static inline int Saig_MvNotCond( int iNode, int c ) { return (iNode ^ (c)); } +static inline int Saig_MvIsComplement( int iNode ) { return (int)(iNode & 01); } + +static inline int Saig_MvLit2Var( int iNode ) { return (iNode >> 1); } +static inline int Saig_MvVar2Lit( int iVar ) { return (iVar << 1); } +static inline int Saig_MvLev( Saig_MvMan_t * p, int iNode ) { return p->pLevels[iNode >> 1]; } + +// iterator over compacted objects +#define Saig_MvManForEachObj( pAig, pEntry ) \ + for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates reduced manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_MvObj_t * Saig_ManCreateReducedAig( Aig_Man_t * p, Vec_Ptr_t ** pvFlops ) +{ + Saig_MvObj_t * pAig, * pEntry; + Aig_Obj_t * pObj; + int i; + *pvFlops = Vec_PtrAlloc( Aig_ManRegNum(p) ); + pAig = CALLOC( Saig_MvObj_t, Aig_ManObjNumMax(p)+1 ); + Aig_ManForEachObj( p, pObj, i ) + { + pEntry = pAig + i; + pEntry->Type = pObj->Type; + if ( Aig_ObjIsPi(pObj) || i == 0 ) + { + if ( Saig_ObjIsLo(p, pObj) ) + { + pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1); + pEntry->iFan1 = -1; + Vec_PtrPush( *pvFlops, pEntry ); + } + continue; + } + pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); + if ( Aig_ObjIsPo(pObj) ) + continue; + assert( Aig_ObjIsNode(pObj) ); + pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); + } + pEntry = pAig + Aig_ManObjNumMax(p); + pEntry->Type = AIG_OBJ_VOID; + return pAig; +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Saig_MvCreateObj( Saig_MvMan_t * p, int iFan0, int iFan1 ) +{ + Saig_MvAnd_t * pNode; + if ( p->nObjs == p->nObjsAlloc ) + { + p->pAigNew = REALLOC( Saig_MvAnd_t, p->pAigNew, 2*p->nObjsAlloc ); + p->pLevels = REALLOC( unsigned char, p->pLevels, 2*p->nObjsAlloc ); + p->nObjsAlloc *= 2; + } + pNode = p->pAigNew + p->nObjs; + pNode->iFan0 = iFan0; + pNode->iFan1 = iFan1; + pNode->iNext = 0; + if ( iFan0 || iFan1 ) + p->pLevels[p->nObjs] = 1 + AIG_MAX( Saig_MvLev(p, iFan0), Saig_MvLev(p, iFan1) ); + else + p->pLevels[p->nObjs] = 0, p->nPis++; + return p->nObjs++; +} + +/**Function************************************************************* + + Synopsis [Creates multi-valued simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_MvMan_t * Saig_MvManStart( Aig_Man_t * pAig ) +{ + Saig_MvMan_t * p; + int i; + assert( Aig_ManRegNum(pAig) > 0 ); + p = (Saig_MvMan_t *)ALLOC( Saig_MvMan_t, 1 ); + memset( p, 0, sizeof(Saig_MvMan_t) ); + // set parameters + p->pAig = pAig; + p->nStatesMax = 200; + p->nLevelsMax = 4; + p->nValuesMax = SAIG_DIFF_VALUES; + p->nFlops = Aig_ManRegNum(pAig); + // compacted AIG + p->pAigOld = Saig_ManCreateReducedAig( pAig, &p->vFlops ); + p->nTStatesSize = Aig_PrimeCudd( p->nStatesMax ); + p->pTStates = CALLOC( int, p->nTStatesSize ); + p->pMemStates = Aig_MmFixedStart( sizeof(int) * (p->nFlops+1), p->nStatesMax ); + p->vStates = Vec_PtrAlloc( p->nStatesMax ); + Vec_PtrPush( p->vStates, NULL ); + p->pRegsUndef = CALLOC( int, p->nFlops ); + p->pRegsValues = ALLOC( int *, p->nFlops ); + p->pRegsValues[0] = ALLOC( int, p->nValuesMax * p->nFlops ); + for ( i = 1; i < p->nFlops; i++ ) + p->pRegsValues[i] = p->pRegsValues[i-1] + p->nValuesMax; + p->nRegsValues = CALLOC( int, p->nFlops ); + p->vTired = Vec_PtrAlloc( 100 ); + // internal AIG + p->nObjsAlloc = 1000000; + p->pAigNew = ALLOC( Saig_MvAnd_t, p->nObjsAlloc ); + p->nTNodesSize = Aig_PrimeCudd( p->nObjsAlloc / 3 ); + p->pTNodes = CALLOC( int, p->nTNodesSize ); + p->pLevels = ALLOC( unsigned char, p->nObjsAlloc ); + Saig_MvCreateObj( p, 0, 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Destroys multi-valued simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_MvManStop( Saig_MvMan_t * p ) +{ + Aig_MmFixedStop( p->pMemStates, 0 ); + Vec_PtrFree( p->vStates ); + Vec_PtrFree( p->vFlops ); + Vec_PtrFree( p->vTired ); + free( p->pRegsValues[0] ); + free( p->pRegsValues ); + free( p->nRegsValues ); + free( p->pRegsUndef ); + free( p->pAigOld ); + free( p->pTStates ); + free( p->pAigNew ); + free( p->pTNodes ); + free( p->pLevels ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Hashing the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Saig_MvHash( int iFan0, int iFan1, int TableSize ) +{ + unsigned Key = 0; + assert( iFan0 < iFan1 ); + Key ^= Saig_MvLit2Var(iFan0) * 7937; + Key ^= Saig_MvLit2Var(iFan1) * 2971; + Key ^= Saig_MvIsComplement(iFan0) * 911; + Key ^= Saig_MvIsComplement(iFan1) * 353; + return (int)(Key % TableSize); +} + +/**Function************************************************************* + + Synopsis [Returns the place where this node is stored (or should be stored).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Saig_MvTableFind( Saig_MvMan_t * p, int iFan0, int iFan1 ) +{ + Saig_MvAnd_t * pEntry; + int * pPlace = p->pTNodes + Saig_MvHash( iFan0, iFan1, p->nTNodesSize ); + for ( pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL; pEntry; + pPlace = &pEntry->iNext, pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL ) + if ( pEntry->iFan0 == iFan0 && pEntry->iFan1 == iFan1 ) + break; + return pPlace; +} + +/**Function************************************************************* + + Synopsis [Performs an AND-operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Saig_MvAnd( Saig_MvMan_t * p, int iFan0, int iFan1 ) +{ + if ( iFan0 == iFan1 ) + return iFan0; + if ( iFan0 == Saig_MvNot(iFan1) ) + return Saig_MvConst0(); + if ( Saig_MvIsConst(iFan0) ) + return Saig_MvIsConst1(iFan0) ? iFan1 : Saig_MvConst0(); + if ( Saig_MvIsConst(iFan1) ) + return Saig_MvIsConst1(iFan1) ? iFan0 : Saig_MvConst0(); + if ( Saig_MvIsUndef(iFan0) || Saig_MvIsUndef(iFan1) ) + return Saig_MvUndef(); + if ( Saig_MvLev(p, iFan0) >= p->nLevelsMax || Saig_MvLev(p, iFan1) >= p->nLevelsMax ) + return Saig_MvUndef(); + +// return Saig_MvUndef(); + + if ( iFan0 > iFan1 ) + { + int Temp = iFan0; + iFan0 = iFan1; + iFan1 = Temp; + } + { + int * pPlace; + pPlace = Saig_MvTableFind( p, iFan0, iFan1 ); + if ( *pPlace == 0 ) + *pPlace = Saig_MvCreateObj( p, iFan0, iFan1 ); + return Saig_MvVar2Lit( *pPlace ); + } +} + +/**Function************************************************************* + + Synopsis [Propagates one edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Saig_MvSimulateValue0( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj ) +{ + Saig_MvObj_t * pObj0 = pAig + Saig_MvObjFanin0(pObj); + if ( Saig_MvIsUndef( pObj0->Value ) ) + return Saig_MvUndef(); + return Saig_MvNotCond( pObj0->Value, Saig_MvObjFaninC0(pObj) ); +} +static inline int Saig_MvSimulateValue1( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj ) +{ + Saig_MvObj_t * pObj1 = pAig + Saig_MvObjFanin1(pObj); + if ( Saig_MvIsUndef( pObj1->Value ) ) + return Saig_MvUndef(); + return Saig_MvNotCond( pObj1->Value, Saig_MvObjFaninC1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Performs one iteration of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_MvSimulateFrame( Saig_MvMan_t * p, int fFirst ) +{ + int fPrintState = 0; + Saig_MvObj_t * pEntry; + int i, NewValue; + Saig_MvManForEachObj( p->pAigOld, pEntry ) + { + if ( pEntry->Type == AIG_OBJ_AND ) + { + pEntry->Value = Saig_MvAnd( p, + Saig_MvSimulateValue0(p->pAigOld, pEntry), + Saig_MvSimulateValue1(p->pAigOld, pEntry) ); +/* +printf( "%d = %d%s * %d%s --> %d\n", pEntry - p->pAigOld, + Saig_MvObjFanin0(pEntry), Saig_MvObjFaninC0(pEntry)? "-":"+", + Saig_MvObjFanin1(pEntry), Saig_MvObjFaninC1(pEntry)? "-":"+", pEntry->Value ); +*/ + } + else if ( pEntry->Type == AIG_OBJ_PO ) + pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry); + else if ( pEntry->Type == AIG_OBJ_PI ) + { + if ( pEntry->iFan1 == 0 ) // true PI + pEntry->Value = Saig_MvVar2Lit( Saig_MvCreateObj( p, 0, 0 ) ); +// else if ( fFirst ) // register output +// pEntry->Value = Saig_MvConst0(); +// else +// pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry); + } + else if ( pEntry->Type == AIG_OBJ_CONST1 ) + pEntry->Value = Saig_MvConst1(); + else if ( pEntry->Type != AIG_OBJ_NONE ) + assert( 0 ); + } + Vec_PtrClear( p->vTired ); + Vec_PtrForEachEntry( p->vFlops, pEntry, i ) + { + NewValue = Saig_MvSimulateValue0(p->pAigOld, pEntry); + if ( NewValue != (int)pEntry->Value ) + Vec_PtrPush( p->vTired, pEntry ); + pEntry->Value = NewValue; + if ( !fPrintState ) + continue; + if ( pEntry->Value == 536870910 ) + printf( "* " ); + else + printf( "%d ", pEntry->Value ); + } +if ( fPrintState ) +printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_MvSimHash( int * pState, int nFlops, int TableSize ) +{ + static int s_SPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned uHash = 0; + int i; + for ( i = 0; i < nFlops; i++ ) + uHash ^= pState[i] * s_SPrimes[i & 0x7F]; + return (int)(uHash % TableSize); +} + +/**Function************************************************************* + + Synopsis [Returns the place where this state is stored (or should be stored).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Saig_MvSimTableFind( Saig_MvMan_t * p, int * pState ) +{ + int * pEntry; + int * pPlace = p->pTStates + Saig_MvSimHash( pState+1, p->nFlops, p->nTStatesSize ); + for ( pEntry = (*pPlace)? Vec_PtrEntry(p->vStates, *pPlace) : NULL; pEntry; + pPlace = pEntry, pEntry = (*pPlace)? Vec_PtrEntry(p->vStates, *pPlace) : NULL ) + if ( memcmp( pEntry+1, pState+1, sizeof(int)*p->nFlops ) == 0 ) + break; + return pPlace; +} + +/**Function************************************************************* + + Synopsis [Saves current state.] + + Description [Returns -1 if there is no fixed point.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_MvSaveState( Saig_MvMan_t * p, int * piReg ) +{ + Saig_MvObj_t * pEntry; + int i, k, * pState, * pPlace, nMaxUndefs = 0; + int iTimesOld, iTimesNew; + *piReg = -1; + pState = (int *)Aig_MmFixedEntryFetch( p->pMemStates ); + pState[0] = 0; + Vec_PtrForEachEntry( p->vFlops, pEntry, i ) + { + iTimesOld = p->nRegsValues[i]; + // count the number of different def values + if ( !Saig_MvIsUndef( pEntry->Value ) && p->nRegsValues[i] < p->nValuesMax ) + { + for ( k = 0; k < p->nRegsValues[i]; k++ ) + if ( p->pRegsValues[i][k] == (int)pEntry->Value ) + break; + if ( k == p->nRegsValues[i] ) + p->pRegsValues[i][ p->nRegsValues[i]++ ] = pEntry->Value; + } + else // retire this register (consider moving this up!) + { + pEntry->Value = Saig_MvUndef(); + p->nRegsValues[i] = SAIG_DIFF_VALUES+1; + } + iTimesNew = p->nRegsValues[i]; + // count the number of times + if ( iTimesOld != iTimesNew ) + { + if ( iTimesOld > 0 ) + p->nRValues[iTimesOld]--; + if ( iTimesNew <= SAIG_DIFF_VALUES ) + p->nRValues[iTimesNew]++; + } + // count the number of undef values + if ( Saig_MvIsUndef( pEntry->Value ) ) + { + if ( p->pRegsUndef[i]++ == 0 ) + p->nRUndefs++; + } + // find def reg with the max number of undef values + if ( nMaxUndefs < p->pRegsUndef[i] ) + { + nMaxUndefs = p->pRegsUndef[i]; + *piReg = i; + } + // remember state + pState[i+1] = pEntry->Value; + +// if ( pEntry->Value == 536870910 ) +// printf( "* " ); +// else +// printf( "%d ", pEntry->Value ); + } +//printf( "\n" ); + pPlace = Saig_MvSimTableFind( p, pState ); + if ( *pPlace ) + return *pPlace; + *pPlace = Vec_PtrSize( p->vStates ); + Vec_PtrPush( p->vStates, pState ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Performs multi-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_MvManPostProcess( Saig_MvMan_t * p, int iState ) +{ + Saig_MvObj_t * pEntry; + int i, k, j, nTotal = 0, * pState, Counter = 0, iFlop; + Vec_Int_t * vUniques = Vec_IntAlloc( 100 ); + Vec_Int_t * vCounter = Vec_IntAlloc( 100 ); + // count registers that never became undef + Vec_PtrForEachEntry( p->vFlops, pEntry, i ) + if ( p->pRegsUndef[i] == 0 ) + nTotal++; + printf( "The number of registers that never became undef = %d. (Total = %d.)\n", nTotal, p->nFlops ); + Vec_PtrForEachEntry( p->vFlops, pEntry, i ) + { + if ( p->pRegsUndef[i] ) + continue; + Vec_IntForEachEntry( vUniques, iFlop, k ) + { + Vec_PtrForEachEntryStart( p->vStates, pState, j, 1 ) + if ( pState[iFlop+1] != pState[i+1] ) + break; + if ( j == Vec_PtrSize(p->vStates) ) + { + Vec_IntAddToEntry( vCounter, k, 1 ); + break; + } + } + if ( k == Vec_IntSize(vUniques) ) + { + Vec_IntPush( vUniques, i ); + Vec_IntPush( vCounter, 1 ); + } + } + Vec_IntForEachEntry( vUniques, iFlop, i ) + { + printf( "FLOP %5d : (%3d) ", iFlop, Vec_IntEntry(vCounter,i) ); +/* + for ( k = 0; k < p->nRegsValues[iFlop]; k++ ) + if ( p->pRegsValues[iFlop][k] == 536870910 ) + printf( "* " ); + else + printf( "%d ", p->pRegsValues[iFlop][k] ); + printf( "\n" ); +*/ + Vec_PtrForEachEntryStart( p->vStates, pState, k, 1 ) + { + if ( k == iState+1 ) + printf( " # " ); + if ( pState[iFlop+1] == 536870910 ) + printf( "*" ); + else + printf( "%d", pState[iFlop+1] ); + } + printf( "\n" ); +// if ( ++Counter == 10 ) +// break; + } + + Vec_IntFree( vUniques ); + Vec_IntFree( vCounter ); +} + +/**Function************************************************************* + + Synopsis [Performs multi-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_MvManSimulate( Aig_Man_t * pAig, int fVerbose ) +{ + Saig_MvMan_t * p; + Saig_MvObj_t * pEntry; + int f, i, k, iRegMax, iState, clk = clock(); + // start the manager + p = Saig_MvManStart( pAig ); +PRT( "Constructing the problem", clock() - clk ); + clk = clock(); + // initiliaze registers + Vec_PtrForEachEntry( p->vFlops, pEntry, i ) + { + pEntry->Value = Saig_MvConst0(); + if ( pEntry->iFan0 == 1 ) + printf( "Constant value %d\n", i ); + } + + Saig_MvSaveState( p, &iRegMax ); + // simulate until convergence + for ( f = 0; ; f++ ) + { +/* + if ( fVerbose ) + { + printf( "%3d : ", f+1 ); + printf( "*=%6d ", p->nRUndefs ); + for ( k = 1; k < SAIG_DIFF_VALUES; k++ ) + if ( p->nRValues[k] == 0 ) + printf( " " ); + else + printf( "%d=%6d ", k, p->nRValues[k] ); + printf( "aig=%6d", p->nObjs ); + printf( "\n" ); + } +*/ + Saig_MvSimulateFrame( p, f==0 ); + iState = Saig_MvSaveState( p, &iRegMax ); + if ( iState >= 0 ) + { + printf( "Converged after %d frames with lasso in state %d. Cycle = %d.\n", f+1, iState-1, f+2-iState ); + printf( "Total number of PIs = %d. AND nodes = %d.\n", p->nPis, p->nObjs - p->nPis ); + break; + } + if ( f >= p->nStatesMax && iRegMax >= 0 ) + { +/* + pEntry = Vec_PtrEntry( p->vFlops, iRegMax ); + assert( pEntry->Value != (unsigned)Saig_MvUndef() ); + pEntry->Value = Saig_MvUndef(); + printf( "Retiring flop %d.\n", iRegMax ); +*/ +// printf( "Retiring %d flops.\n", Vec_PtrSize(p->vTired) ); + Vec_PtrForEachEntry( p->vTired, pEntry, k ) + pEntry->Value = Saig_MvUndef(); + } + } +PRT( "Multi-value simulation", clock() - clk ); + // implement equivalences + Saig_MvManPostProcess( p, iState-1 ); + Saig_MvManStop( p ); + return 1; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/saig/saigSimSeq.c b/src/aig/saig/saigSimSeq.c new file mode 100644 index 00000000..26783346 --- /dev/null +++ b/src/aig/saig/saigSimSeq.c @@ -0,0 +1,513 @@ +/**CFile**************************************************************** + + FileName [saigSimSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Fast sequential AIG simulator.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSimSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "ssw.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// combinational simulation manager +typedef struct Raig_Man_t_ Raig_Man_t; +struct Raig_Man_t_ +{ + // parameters + Aig_Man_t * pAig; // the AIG to be used for simulation + int nWords; // the number of words to simulate + // AIG representation + int nPis; // the number of primary inputs + int nPos; // the number of primary outputs + int nCis; // the number of combinational inputs + int nCos; // the number of combinational outputs + int nNodes; // the number of internal nodes + int nObjs; // nCis + nNodes + nCos + 2 + int * pFans0; // fanin0 for all objects + int * pFans1; // fanin1 for all objects + Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids + Vec_Int_t * vLos; // register outputs + Vec_Int_t * vLis; // register inputs + // simulation info + int * pRefs; // reference counter for each node + unsigned * pSims; // simlulation information for each node + // recycable memory + unsigned * pMems; // allocated simulaton memory + int nWordsAlloc; // the number of allocated entries + int nMems; // the number of used entries + int nMemsMax; // the max number of used entries + int MemFree; // next free entry +}; + +static inline int Raig_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Raig_Lit2Var( int Lit ) { return Lit >> 1; } +static inline int Raig_LitIsCompl( int Lit ) { return Lit & 1; } +static inline int Raig_LitNot( int Lit ) { return Lit ^ 1; } +static inline int Raig_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Raig_LitRegular( int Lit ) { return Lit & ~01; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find the PO corresponding to the PO driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Raig_ManFindPo( Aig_Man_t * pAig, int iNode ) +{ + Aig_Obj_t * pObj; + int i; + Saig_ManForEachPo( pAig, pObj, i ) + if ( pObj->iData == iNode ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Raig_ManCreate_rec( Raig_Man_t * p, Aig_Obj_t * pObj ) +{ + int iFan0, iFan1; + assert( !Aig_IsComplement(pObj) ); + if ( pObj->iData ) + return pObj->iData; + assert( !Aig_ObjIsConst1(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + { + iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj); + iFan1 = Raig_ManCreate_rec( p, Aig_ObjFanin1(pObj) ); + iFan1 = (iFan1 << 1) | Aig_ObjFaninC1(pObj); + } + else if ( Aig_ObjIsPo(pObj) ) + { + iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj); + iFan1 = 0; + } + else + { + iFan0 = iFan1 = 0; + Vec_IntPush( p->vCis2Ids, Aig_ObjPioNum(pObj) ); + } + p->pFans0[p->nObjs] = iFan0; + p->pFans1[p->nObjs] = iFan1; + p->pRefs[p->nObjs] = Aig_ObjRefs(pObj); + return pObj->iData = p->nObjs++; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Raig_Man_t * Raig_ManCreate( Aig_Man_t * pAig ) +{ + Raig_Man_t * p; + Aig_Obj_t * pObj; + int i, nObjs; + Aig_ManCleanData( pAig ); + p = (Raig_Man_t *)ALLOC( Raig_Man_t, 1 ); + memset( p, 0, sizeof(Raig_Man_t) ); + p->pAig = pAig; + p->nPis = Saig_ManPiNum(pAig); + p->nPos = Saig_ManPoNum(pAig); + p->nCis = Aig_ManPiNum(pAig); + p->nCos = Aig_ManPoNum(pAig); + p->nNodes = Aig_ManNodeNum(pAig); + nObjs = p->nCis + p->nCos + p->nNodes + 2; + p->pFans0 = ALLOC( int, nObjs ); + p->pFans1 = ALLOC( int, nObjs ); + p->pRefs = ALLOC( int, nObjs ); + p->pSims = CALLOC( unsigned, nObjs ); + p->vCis2Ids = Vec_IntAlloc( Aig_ManPiNum(pAig) ); + // add objects (0=unused; 1=const1) + p->nObjs = 2; + pObj = Aig_ManConst1( pAig ); + pObj->iData = 1; + Aig_ManForEachPi( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) == 0 ) + Raig_ManCreate_rec( p, pObj ); + Aig_ManForEachPo( pAig, pObj, i ) + Raig_ManCreate_rec( p, pObj ); + assert( Vec_IntSize(p->vCis2Ids) == Aig_ManPiNum(pAig) ); + assert( p->nObjs == nObjs ); + // collect flop outputs + p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( p->vLos, pObj->iData ); + // collect flop inputs + p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + { + Vec_IntPush( p->vLis, pObj->iData ); + assert( p->pRefs[ pObj->iData ] == 0 ); + p->pRefs[ pObj->iData ]++; + } + return p; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Raig_ManDelete( Raig_Man_t * p ) +{ + Vec_IntFree( p->vCis2Ids ); + Vec_IntFree( p->vLos ); + Vec_IntFree( p->vLis ); + FREE( p->pFans0 ); + FREE( p->pFans1 ); + FREE( p->pRefs ); + FREE( p->pSims ); + FREE( p->pMems ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [References simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Raig_ManSimRef( Raig_Man_t * p, int i ) +{ + unsigned * pSim; + assert( i > 1 ); + assert( p->pSims[i] == 0 ); + if ( p->MemFree == 0 ) + { + int * pPlace, Ent; + if ( p->nWordsAlloc == 0 ) + { + assert( p->pMems == NULL ); + p->nWordsAlloc = (1<<17); // -> 1Mb + p->nMems = 1; + } + p->nWordsAlloc *= 2; + p->pMems = REALLOC( unsigned, p->pMems, p->nWordsAlloc ); + memset( p->pMems, 0xff, sizeof(unsigned) * (p->nWords + 1) ); + pPlace = &p->MemFree; + for ( Ent = p->nMems * (p->nWords + 1); + Ent + p->nWords + 1 < p->nWordsAlloc; + Ent += p->nWords + 1 ) + { + *pPlace = Ent; + pPlace = p->pMems + Ent; + } + *pPlace = 0; + } + p->pSims[i] = p->MemFree; + pSim = p->pMems + p->MemFree; + p->MemFree = pSim[0]; + pSim[0] = p->pRefs[i]; + p->nMems++; + if ( p->nMemsMax < p->nMems ) + p->nMemsMax = p->nMems; + return pSim; +} + +/**Function************************************************************* + + Synopsis [Dereference simulaton info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Raig_ManSimDeref( Raig_Man_t * p, int i ) +{ + unsigned * pSim; + assert( i ); + if ( i == 1 ) // const 1 + return p->pMems; + assert( p->pSims[i] > 0 ); + pSim = p->pMems + p->pSims[i]; + if ( --pSim[0] == 0 ) + { + pSim[0] = p->MemFree; + p->MemFree = p->pSims[i]; + p->pSims[i] = 0; + p->nMems--; + } + return pSim; +} + +/**Function************************************************************* + + Synopsis [Simulates one round.] + + Description [Returns the number of PO entry if failed; 0 otherwise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Raig_ManSimulateRound( Raig_Man_t * p, int fMiter, int fFirst, int * piPat ) +{ + unsigned * pRes0, * pRes1, * pRes; + int i, w, nCis, nCos, iFan0, iFan1, iPioNum; + // nove the values to the register outputs + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + continue; + pRes = Raig_ManSimRef( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) ); + if ( fFirst ) + memset( pRes + 1, 0, sizeof(unsigned) * p->nWords ); + else + { + pRes0 = Raig_ManSimDeref( p, Vec_IntEntry(p->vLis, iPioNum-p->nPis) ); + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w]; + } + // handle unused PIs + if ( pRes[0] == 0 ) + { + pRes[0] = 1; + Raig_ManSimDeref( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) ); + } + } + // simulate the logic + nCis = nCos = 0; + for ( i = 2; i < p->nObjs; i++ ) + { + if ( p->pFans0[i] == 0 ) // ci always has zero first fanin + { + iPioNum = Vec_IntEntry( p->vCis2Ids, nCis ); + if ( iPioNum < p->nPis ) + { + pRes = Raig_ManSimRef( p, i ); + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = Aig_ManRandom( 0 ); + // handle unused PIs + if ( pRes[0] == 0 ) + { + pRes[0] = 1; + Raig_ManSimDeref( p, i ); + } + } + else + assert( Vec_IntEntry(p->vLos, iPioNum-p->nPis) == i ); + nCis++; + continue; + } + if ( p->pFans1[i] == 0 ) // co always has non-zero 1st fanin and zero 2nd fanin + { + pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) ); + if ( nCos < p->nPos && fMiter ) + { + unsigned Const = Raig_LitIsCompl(p->pFans0[i])? ~0 : 0; + for ( w = 1; w <= p->nWords; w++ ) + if ( pRes0[w] != Const ) + { + *piPat = 32*(w-1) + Aig_WordFindFirstBit( pRes0[w] ^ Const ); + return i; + } + } + else + { + pRes = Raig_ManSimRef( p, i ); + assert( pRes[0] == 1 ); + if ( Raig_LitIsCompl(p->pFans0[i]) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~pRes0[w]; + else + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w]; + } + nCos++; + continue; + } + pRes = Raig_ManSimRef( p, i ); + assert( pRes[0] > 0 ); + iFan0 = p->pFans0[i]; + iFan1 = p->pFans1[i]; + pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) ); + pRes1 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans1[i]) ); + if ( Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~(pRes0[w] | pRes1[w]); + else if ( Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~pRes0[w] & pRes1[w]; + else if ( !Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w] & ~pRes1[w]; + else if ( !Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w] & pRes1[w]; + } + assert( nCis == p->nCis ); + assert( nCos == p->nCos ); + assert( p->nMems == 1 + Vec_IntSize(p->vLis) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cex_t * Raig_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids ) +{ + Ssw_Cex_t * p; + unsigned * pData; + int f, i, w, iPioId, Counter; + p = Ssw_SmlAllocCounterExample( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 ); + p->iFrame = iFrame; + p->iPo = iOut; + // fill in the binary data + Aig_ManRandom( 1 ); + Counter = p->nRegs; + pData = ALLOC( unsigned, nWords ); + for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) + for ( i = 0; i < Aig_ManPiNum(pAig); i++ ) + { + iPioId = Vec_IntEntry( vCis2Ids, i ); + if ( iPioId >= p->nPis ) + continue; + for ( w = 0; w < nWords; w++ ) + pData[w] = Aig_ManRandom( 0 ); + if ( Aig_InfoHasBit( pData, iPat ) ) + Aig_InfoSetBit( p->pData, Counter + iPioId ); + } + free( pData ); + return p; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the bug is detected, 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Raig_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose ) +{ + Raig_Man_t * p; + Sec_MtrStatus_t Status; + int i, iPat, RetValue = 0; + int clk, clkTotal = clock(); + assert( Aig_ManRegNum(pAig) > 0 ); + Status = Sec_MiterStatus( pAig ); + if ( Status.nSat > 0 ) + { + printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut ); + return 1; + } + if ( Status.nUndec == 0 ) + { + printf( "Miter is trivially unsatisfiable.\n" ); + return 0; + } + Aig_ManRandom( 1 ); + p = Raig_ManCreate( pAig ); + p->nWords = nWords; + // iterate through objects + for ( i = 0; i < nIters; i++ ) + { + clk = clock(); + RetValue = Raig_ManSimulateRound( p, fMiter, i==0, &iPat ); + if ( fVerbose ) + { + printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, nIters, TimeLimit ); + printf("Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC); + } + if ( RetValue > 0 ) + { + int iOut = Raig_ManFindPo(p->pAig, RetValue); + assert( pAig->pSeqModel == NULL ); + pAig->pSeqModel = Raig_ManGenerateCounter( pAig, i, iOut, nWords, iPat, p->vCis2Ids ); + if ( fVerbose ) + printf( "Miter is satisfiable after simulation (output %d).\n", iOut ); + break; + } + if ( (clock() - clk)/CLOCKS_PER_SEC >= TimeLimit ) + { + printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, TimeLimit ); + break; + } + } + if ( fVerbose ) + { + printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ", + p->nMemsMax, + 1.0*(p->nObjs * 16)/(1<<20), + 1.0*(p->nMemsMax * 4 * (nWords+1))/(1<<20) ); + PRT( "Total time", clock() - clkTotal ); + } + Raig_ManDelete( p ); + return RetValue > 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/saig/saigStrSim.c b/src/aig/saig/saigStrSim.c new file mode 100644 index 00000000..ce4b8e05 --- /dev/null +++ b/src/aig/saig/saigStrSim.c @@ -0,0 +1,971 @@ +/**CFile**************************************************************** + + FileName [saigStrSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Structural matching using simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigStrSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "ssw.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SAIG_WORDS 16 + +static inline Aig_Obj_t * Saig_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } +static inline void Saig_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Saig_StrSimHash( Aig_Obj_t * pObj ) +{ + static int s_SPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned * pSims; + unsigned uHash = 0; + int i; + assert( SAIG_WORDS <= 128 ); + pSims = pObj->pData; + for ( i = 0; i < SAIG_WORDS; i++ ) + uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; + return uHash; +} + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimIsEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + unsigned * pSims0 = pObj0->pData; + unsigned * pSims1 = pObj1->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + if ( pSims0[i] != pSims1[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is zero.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimIsZero( Aig_Obj_t * pObj ) +{ + unsigned * pSims = pObj->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + if ( pSims[i] != 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimIsOne( Aig_Obj_t * pObj ) +{ + unsigned * pSims = pObj->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + if ( pSims[i] != ~0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Assigns random simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimAssignRandom( Aig_Obj_t * pObj ) +{ + unsigned * pSims = pObj->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + pSims[i] = Aig_ManRandom(0); +} + +/**Function************************************************************* + + Synopsis [Assigns constant 0 simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimAssignOne( Aig_Obj_t * pObj ) +{ + unsigned * pSims = pObj->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + pSims[i] = ~0; +} + +/**Function************************************************************* + + Synopsis [Assigns constant 0 simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimAssignZeroInit( Aig_Obj_t * pObj ) +{ + unsigned * pSims = pObj->pData; + pSims[0] = 0; +} + +/**Function************************************************************* + + Synopsis [Simulated one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimulateNode( Aig_Obj_t * pObj, int i ) +{ + unsigned * pSims = pObj->pData; + unsigned * pSims0 = Aig_ObjFanin0(pObj)->pData; + unsigned * pSims1 = Aig_ObjFanin1(pObj)->pData; + if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + pSims[i] = ~(pSims0[i] | pSims1[i]); + else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + pSims[i] = (~pSims0[i] & pSims1[i]); + else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + pSims[i] = (pSims0[i] & ~pSims1[i]); + else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + pSims[i] = (pSims0[i] & pSims1[i]); +} + +/**Function************************************************************* + + Synopsis [Saves output of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSaveOutput( Aig_Obj_t * pObj, int i ) +{ + unsigned * pSims = pObj->pData; + unsigned * pSims0 = Aig_ObjFanin0(pObj)->pData; + if ( Aig_ObjFaninC0(pObj) ) + pSims[i] = ~pSims0[i]; + else + pSims[i] = pSims0[i]; +} + +/**Function************************************************************* + + Synopsis [Transfers simulation output to another node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimTransfer( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + unsigned * pSims0 = pObj0->pData; + unsigned * pSims1 = pObj1->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + pSims1[i] = pSims0[i]; +} + +/**Function************************************************************* + + Synopsis [Transfers simulation output to another node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimTransferNext( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int i ) +{ + unsigned * pSims0 = pObj0->pData; + unsigned * pSims1 = pObj1->pData; + assert( i < SAIG_WORDS - 1 ); + pSims1[i+1] = pSims0[i]; +} + +/**Function************************************************************* + + Synopsis [Perform one round of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimulateRound( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1; + int f, i; + // simulate the nodes + Aig_ManForEachObj( p0, pObj0, i ) + { + if ( !Aig_ObjIsPi(pObj0) && !Aig_ObjIsNode(pObj0) ) + continue; + pObj1 = Aig_ObjRepr(p0, pObj0); + if ( pObj1 == NULL ) + continue; + assert( Aig_ObjRepr(p1, pObj1) == pObj0 ); + Saig_StrSimAssignRandom( pObj0 ); + Saig_StrSimTransfer( pObj0, pObj1 ); + } + // simulate the timeframes + for ( f = 0; f < SAIG_WORDS; f++ ) + { + // simulate the first AIG + Aig_ManForEachNode( p0, pObj0, i ) + if ( Aig_ObjRepr(p0, pObj0) == NULL ) + Saig_StrSimulateNode( pObj0, f ); + Saig_ManForEachLi( p0, pObj0, i ) + Saig_StrSimSaveOutput( pObj0, f ); + if ( f < SAIG_WORDS - 1 ) + Saig_ManForEachLiLo( p0, pObj0, pObj1, i ) + Saig_StrSimTransferNext( pObj0, pObj1, f ); + // simulate the second AIG + Aig_ManForEachNode( p1, pObj1, i ) + if ( Aig_ObjRepr(p1, pObj1) == NULL ) + Saig_StrSimulateNode( pObj1, f ); + Saig_ManForEachLi( p1, pObj1, i ) + Saig_StrSimSaveOutput( pObj1, f ); + if ( f < SAIG_WORDS - 1 ) + Saig_ManForEachLiLo( p1, pObj1, pObj0, i ) + Saig_StrSimTransferNext( pObj1, pObj0, f ); + } +} + +/**Function************************************************************* + + Synopsis [Checks if the entry exists in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_StrSimTableLookup( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pEntry; + int iEntry; + // find the hash entry + iEntry = Saig_StrSimHash( pObj ) % nTableSize; + // check if there are nodes with this signatures + for ( pEntry = ppTable[iEntry]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) ) + if ( Saig_StrSimIsEqual( pEntry, pObj ) ) + return pEntry; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Inserts the entry into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimTableInsert( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj ) +{ + // find the hash entry + int iEntry = Saig_StrSimHash( pObj ) % nTableSize; + // check if there are nodes with this signatures + if ( ppTable[iEntry] == NULL ) + ppTable[iEntry] = pObj; + else + { + Saig_ObjSetNext( ppNexts, pObj, Saig_ObjNext(ppNexts, ppTable[iEntry]) ); + Saig_ObjSetNext( ppNexts, ppTable[iEntry], pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Perform one round of matching.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimDetectUnique( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t ** ppTable, ** ppNexts, ** ppCands; + Aig_Obj_t * pObj, * pEntry; + int i, nTableSize, Counter; + + // allocate the hash table hashing simulation info into nodes + nTableSize = Aig_PrimeCudd( Aig_ManObjNum(p0)/2 ); + ppTable = CALLOC( Aig_Obj_t *, nTableSize ); + ppNexts = CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) ); + ppCands = CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) ); + + // hash nodes of the first AIG + Aig_ManForEachObj( p0, pObj, i ) + { + if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjRepr(p0, pObj) ) + continue; + if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) ) + continue; + // check if the entry exists + pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj ); + if ( pEntry == NULL ) // insert + Saig_StrSimTableInsert( ppTable, ppNexts, nTableSize, pObj ); + else // mark the entry as not unique + pEntry->fMarkA = 1; + } + + // hash nodes from the second AIG + Aig_ManForEachObj( p1, pObj, i ) + { + if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjRepr(p1, pObj) ) + continue; + if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) ) + continue; + // check if the entry exists + pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj ); + if ( pEntry == NULL ) // skip + continue; + // if there is no candidate, label it + if ( Saig_ObjNext( ppCands, pEntry ) == NULL ) + Saig_ObjSetNext( ppCands, pEntry, pObj ); + else // mark the entry as not unique + pEntry->fMarkA = 1; + } + + // create representatives for the unique entries + Counter = 0; + for ( i = 0; i < nTableSize; i++ ) + for ( pEntry = ppTable[i]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) ) + if ( !pEntry->fMarkA && (pObj = Saig_ObjNext( ppCands, pEntry )) ) + { +// assert( Aig_ObjIsNode(pEntry) == Aig_ObjIsNode(pObj) ); + if ( Aig_ObjType(pEntry) != Aig_ObjType(pObj) ) + continue; + Aig_ObjSetRepr( p0, pEntry, pObj ); + Aig_ObjSetRepr( p1, pObj, pEntry ); + Counter++; + } + + // cleanup + Aig_ManCleanMarkA( p0 ); + free( ppTable ); + free( ppNexts ); + free( ppCands ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of matched flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimCountMatchedFlops( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Saig_ManForEachLo( p, pObj, i ) + if ( Aig_ObjRepr(p, pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of matched nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimCountMatchedNodes( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjRepr(p, pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimPrepareAig( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManReprStart( p, Aig_ManObjNumMax(p) ); + // allocate simulation info + p->pData2 = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), SAIG_WORDS ); + Aig_ManForEachObj( p, pObj, i ) + pObj->pData = Vec_PtrEntry( p->pData2, i ); + // set simulation info for constant1 and register outputs + Saig_StrSimAssignOne( Aig_ManConst1(p) ); + Saig_ManForEachLo( p, pObj, i ) + Saig_StrSimAssignZeroInit( pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSetInitMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1; + int i; + pObj0 = Aig_ManConst1( p0 ); + pObj1 = Aig_ManConst1( p1 ); + Aig_ObjSetRepr( p0, pObj0, pObj1 ); + Aig_ObjSetRepr( p1, pObj1, pObj0 ); + Saig_ManForEachPi( p0, pObj0, i ) + { + pObj1 = Aig_ManPi( p1, i ); + Aig_ObjSetRepr( p0, pObj0, pObj1 ); + Aig_ObjSetRepr( p1, pObj1, pObj0 ); + } +} + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSetFinalMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1; + Aig_Obj_t * pFanin00, * pFanin01; + Aig_Obj_t * pFanin10, * pFanin11; + int i, CountAll = 0, CountNot = 0; + Aig_ManIncrementTravId( p0 ); + Aig_ManForEachObj( p0, pObj0, i ) + { + pObj1 = Aig_ObjRepr( p0, pObj0 ); + if ( pObj1 == NULL ) + continue; + CountAll++; + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + if ( Aig_ObjIsNode(pObj0) ) + { + assert( Aig_ObjIsNode(pObj1) ); + pFanin00 = Aig_ObjFanin0(pObj0); + pFanin01 = Aig_ObjFanin1(pObj0); + pFanin10 = Aig_ObjFanin0(pObj1); + pFanin11 = Aig_ObjFanin1(pObj1); + if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 || + Aig_ObjRepr(p0, pFanin01) != pFanin11 ) + { + Aig_ObjSetTravIdCurrent(p0, pObj0); + CountNot++; + } + } + else if ( Saig_ObjIsLo(p0, pObj0) ) + { + assert( Saig_ObjIsLo(p1, pObj1) ); + pFanin00 = Aig_ObjFanin0( Saig_ObjLoToLi(p0, pObj0) ); + pFanin10 = Aig_ObjFanin0( Saig_ObjLoToLi(p1, pObj1) ); + if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 ) + { + Aig_ObjSetTravIdCurrent(p0, pObj0); + CountNot++; + } + } + } + // remove irrelevant matches + Aig_ManForEachObj( p0, pObj0, i ) + { + pObj1 = Aig_ObjRepr( p0, pObj0 ); + if ( pObj1 == NULL ) + continue; + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + if ( Aig_ObjIsTravIdCurrent( p0, pObj0 ) ) + { + Aig_ObjSetRepr( p0, pObj0, NULL ); + Aig_ObjSetRepr( p1, pObj1, NULL ); + } + } + printf( "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n", + CountAll, CountNot, 100.0*CountNot/CountAll ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSetContiguousMatching_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int i, iFanout = -1; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsPo( p, pObj ) ) + return; + if ( Saig_ObjIsLi( p, pObj ) ) + { + Saig_StrSimSetContiguousMatching_rec( p, Saig_ObjLiToLo(p, pObj) ); + return; + } + assert( Aig_ObjIsPi(pObj) || Aig_ObjIsNode(pObj) ); + if ( Aig_ObjRepr(p, pObj) == NULL ) + return; + // go through the fanouts + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Saig_StrSimSetContiguousMatching_rec( p, pFanout ); + // go through the fanins + if ( !Aig_ObjIsPi( pObj ) ) + { + Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin0(pObj) ); + Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin1(pObj) ); + } +} + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSetContiguousMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1; + int i, CountAll = 0, CountNot = 0; + // mark nodes reachable through the PIs + Aig_ManIncrementTravId( p0 ); + Aig_ObjSetTravIdCurrent( p0, Aig_ManConst1(p0) ); + Saig_ManForEachPi( p0, pObj0, i ) + Saig_StrSimSetContiguousMatching_rec( p0, pObj0 ); + // remove irrelevant matches + Aig_ManForEachObj( p0, pObj0, i ) + { + pObj1 = Aig_ObjRepr( p0, pObj0 ); + if ( pObj1 == NULL ) + continue; + CountAll++; + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + if ( !Aig_ObjIsTravIdCurrent( p0, pObj0 ) ) + { + Aig_ObjSetRepr( p0, pObj0, NULL ); + Aig_ObjSetRepr( p1, pObj1, NULL ); + CountNot++; + } + } + printf( "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n", + CountAll, CountNot, 100.0*CountNot/CountAll ); +} + + + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_StrSimMatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pNext, * pObj; + int i, k, iFan; + Vec_PtrClear( vNodes ); + Aig_ManIncrementTravId( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + if ( Aig_ObjRepr( p, pObj ) != NULL ) + continue; + if ( Saig_ObjIsLo(p, pObj) ) + { + pNext = Saig_ObjLoToLi(p, pObj); + pNext = Aig_ObjFanin0(pNext); + if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + if ( Aig_ObjIsNode(pObj) ) + { + pNext = Aig_ObjFanin0(pObj); + if ( Aig_ObjRepr( p, pNext )&& !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + pNext = Aig_ObjFanin1(pObj); + if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + Aig_ObjForEachFanout( p, pObj, pNext, iFan, k ) + { + if ( Saig_ObjIsPo(p, pNext) ) + continue; + if ( Saig_ObjIsLi(p, pNext) ) + pNext = Saig_ObjLiToLo(p, pNext); + if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + } +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_StrSimMatchingCountUnmached( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + if ( Aig_ObjRepr( p, pObj ) != NULL ) + continue; + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_StrSimMatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose ) +{ + Vec_Ptr_t * vNodes0, * vNodes1; + Aig_Obj_t * pNext0, * pNext1; + int d, k; + vNodes0 = Vec_PtrAlloc( 1000 ); + vNodes1 = Vec_PtrAlloc( 1000 ); + if ( fVerbose ) + { + int nUnmached = Ssw_StrSimMatchingCountUnmached(p0); + printf( "Extending islands by %d steps:\n", nDist ); + printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", + 0, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0), + nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) ); + } + for ( d = 0; d < nDist; d++ ) + { + Ssw_StrSimMatchingExtendOne( p0, vNodes0 ); + Ssw_StrSimMatchingExtendOne( p1, vNodes1 ); + Vec_PtrForEachEntry( vNodes0, pNext0, k ) + { + pNext1 = Aig_ObjRepr( p0, pNext0 ); + if ( pNext1 == NULL ) + continue; + assert( pNext0 == Aig_ObjRepr( p1, pNext1 ) ); + if ( Saig_ObjIsPi(p1, pNext1) ) + continue; + Aig_ObjSetRepr( p0, pNext0, NULL ); + Aig_ObjSetRepr( p1, pNext1, NULL ); + } + Vec_PtrForEachEntry( vNodes1, pNext1, k ) + { + pNext0 = Aig_ObjRepr( p1, pNext1 ); + if ( pNext0 == NULL ) + continue; + assert( pNext1 == Aig_ObjRepr( p0, pNext0 ) ); + if ( Saig_ObjIsPi(p0, pNext0) ) + continue; + Aig_ObjSetRepr( p0, pNext0, NULL ); + Aig_ObjSetRepr( p1, pNext1, NULL ); + } + if ( fVerbose ) + { + int nUnmached = Ssw_StrSimMatchingCountUnmached(p0); + printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", + d+1, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0), + nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) ); + } + } + Vec_PtrFree( vNodes0 ); + Vec_PtrFree( vNodes1 ); +} + + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ) +{ + extern Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 ); + + Vec_Int_t * vPairs; + Aig_Man_t * pPart0, * pPart1; + Aig_Obj_t * pObj0, * pObj1; + int i, nMatches, clk, clkTotal = clock(); + Aig_ManRandom( 1 ); + // consider the case when a miter is given + if ( p1 == NULL ) + { + if ( fVerbose ) + { + Aig_ManPrintStats( p0 ); + } + // demiter the miter + if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) + { + printf( "Demitering has failed.\n" ); + return NULL; + } + } + else + { + pPart0 = Aig_ManDupSimple( p0 ); + pPart1 = Aig_ManDupSimple( p1 ); + } + if ( fVerbose ) + { + Aig_ManPrintStats( pPart0 ); + Aig_ManPrintStats( pPart1 ); + } + // start simulation + Saig_StrSimPrepareAig( pPart0 ); + Saig_StrSimPrepareAig( pPart1 ); + Saig_StrSimSetInitMatching( pPart0, pPart1 ); + if ( fVerbose ) + { + printf( "Allocated %6.2f Mb to simulate the first AIG.\n", + 1.0 * Aig_ManObjNumMax(pPart0) * SAIG_WORDS * sizeof(unsigned) / (1<<20) ); + printf( "Allocated %6.2f Mb to simulate the second AIG.\n", + 1.0 * Aig_ManObjNumMax(pPart1) * SAIG_WORDS * sizeof(unsigned) / (1<<20) ); + } + // iterate matching + nMatches = 1; + for ( i = 0; nMatches > 0; i++ ) + { + clk = clock(); + Saig_StrSimulateRound( pPart0, pPart1 ); + nMatches = Saig_StrSimDetectUnique( pPart0, pPart1 ); + if ( fVerbose ) + { + int nFlops = Saig_StrSimCountMatchedFlops(pPart0); + int nNodes = Saig_StrSimCountMatchedNodes(pPart0); + printf( "%3d : Match =%6d. FF =%6d. (%6.2f %%) Node =%6d. (%6.2f %%) ", + i, nMatches, + nFlops, 100.0*nFlops/Aig_ManRegNum(pPart0), + nNodes, 100.0*nNodes/Aig_ManNodeNum(pPart0) ); + PRT( "Time", clock() - clk ); + } + if ( i == 20 ) + break; + } + // cleanup + Vec_PtrFree( pPart0->pData2 ); pPart0->pData2 = NULL; + Vec_PtrFree( pPart1->pData2 ); pPart1->pData2 = NULL; + // extend the islands + Aig_ManFanoutStart( pPart0 ); + Aig_ManFanoutStart( pPart1 ); + if ( nDist ) + Ssw_StrSimMatchingExtend( pPart0, pPart1, nDist, fVerbose ); + Saig_StrSimSetFinalMatching( pPart0, pPart1 ); +// Saig_StrSimSetContiguousMatching( pPart0, pPart1 ); + // copy the results into array + vPairs = Vec_IntAlloc( 2*Aig_ManObjNumMax(pPart0) ); + Aig_ManForEachObj( pPart0, pObj0, i ) + { + pObj1 = Aig_ObjRepr(pPart0, pObj0); + if ( pObj1 == NULL ) + continue; + assert( pObj0 == Aig_ObjRepr(pPart1, pObj1) ); + Vec_IntPush( vPairs, pObj0->Id ); + Vec_IntPush( vPairs, pObj1->Id ); + } + // this procedure adds matching of PO and LI + if ( ppMiter ) + *ppMiter = Saig_ManWindowExtractMiter( pPart0, pPart1 ); + Aig_ManFanoutStop( pPart0 ); + Aig_ManFanoutStop( pPart1 ); + Aig_ManStop( pPart0 ); + Aig_ManStop( pPart1 ); + PRT( "Total runtime", clock() - clkTotal ); + return vPairs; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/saig/saigSwitch.c b/src/aig/saig/saigSwitch.c new file mode 100644 index 00000000..684551be --- /dev/null +++ b/src/aig/saig/saigSwitch.c @@ -0,0 +1,582 @@ +/**CFile**************************************************************** + + FileName [saigSwitch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Returns switching propabilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Saig_SimObj_t_ Saig_SimObj_t; +struct Saig_SimObj_t_ +{ + int iFan0; + int iFan1; + unsigned Type : 8; + unsigned Number : 24; + unsigned pData[1]; +}; + +static inline int Saig_SimObjFaninC0( Saig_SimObj_t * pObj ) { return pObj->iFan0 & 1; } +static inline int Saig_SimObjFaninC1( Saig_SimObj_t * pObj ) { return pObj->iFan1 & 1; } +static inline int Saig_SimObjFanin0( Saig_SimObj_t * pObj ) { return pObj->iFan0 >> 1; } +static inline int Saig_SimObjFanin1( Saig_SimObj_t * pObj ) { return pObj->iFan1 >> 1; } + +//typedef struct Aig_CMan_t_ Aig_CMan_t; + +//static Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_SimObj_t * Saig_ManCreateMan( Aig_Man_t * p ) +{ + Saig_SimObj_t * pAig, * pEntry; + Aig_Obj_t * pObj; + int i; + pAig = CALLOC( Saig_SimObj_t, Aig_ManObjNumMax(p)+1 ); +// printf( "Allocating %7.2f Mb.\n", 1.0 * sizeof(Saig_SimObj_t) * (Aig_ManObjNumMax(p)+1)/(1<<20) ); + Aig_ManForEachObj( p, pObj, i ) + { + pEntry = pAig + i; + pEntry->Type = pObj->Type; + if ( Aig_ObjIsPi(pObj) || i == 0 ) + { + if ( Saig_ObjIsLo(p, pObj) ) + { + pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1); + pEntry->iFan1 = -1; + } + continue; + } + pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); + if ( Aig_ObjIsPo(pObj) ) + continue; + assert( Aig_ObjIsNode(pObj) ); + pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); + } + pEntry = pAig + Aig_ManObjNumMax(p); + pEntry->Type = AIG_OBJ_VOID; + return pAig; +} + +/**Function************************************************************* + + Synopsis [Simulated one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Saig_ManSimulateNode2( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) +{ + Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); + Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj ); + if ( Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) ) + pObj->pData[0] = ~(pObj0->pData[0] | pObj1->pData[0]); + else if ( Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) ) + pObj->pData[0] = (~pObj0->pData[0] & pObj1->pData[0]); + else if ( !Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) ) + pObj->pData[0] = (pObj0->pData[0] & ~pObj1->pData[0]); + else // if ( !Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) ) + pObj->pData[0] = (pObj0->pData[0] & pObj1->pData[0]); +} + +/**Function************************************************************* + + Synopsis [Simulated one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Saig_ManSimulateNode( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) +{ + Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); + Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj ); + pObj->pData[0] = (Saig_SimObjFaninC0(pObj)? ~pObj0->pData[0] : pObj0->pData[0]) + & (Saig_SimObjFaninC1(pObj)? ~pObj1->pData[0] : pObj1->pData[0]); +} + +/**Function************************************************************* + + Synopsis [Simulated buffer/inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Saig_ManSimulateOneInput( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) +{ + Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); + if ( Saig_SimObjFaninC0(pObj) ) + pObj->pData[0] = ~pObj0->pData[0]; + else // if ( !Saig_SimObjFaninC0(pObj) ) + pObj->pData[0] = pObj0->pData[0]; +} + +/**Function************************************************************* + + Synopsis [Simulates the timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManSimulateFrames( Saig_SimObj_t * pAig, int nFrames, int nPref ) +{ + Saig_SimObj_t * pEntry; + int f; + for ( f = 0; f < nFrames; f++ ) + { + for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) + { + if ( pEntry->Type == AIG_OBJ_AND ) + Saig_ManSimulateNode( pAig, pEntry ); + else if ( pEntry->Type == AIG_OBJ_PO ) + Saig_ManSimulateOneInput( pAig, pEntry ); + else if ( pEntry->Type == AIG_OBJ_PI ) + { + if ( pEntry->iFan0 == 0 ) // true PI + pEntry->pData[0] = Aig_ManRandom( 0 ); + else if ( f > 0 ) // register output + Saig_ManSimulateOneInput( pAig, pEntry ); + } + else if ( pEntry->Type == AIG_OBJ_CONST1 ) + pEntry->pData[0] = ~0; + else if ( pEntry->Type != AIG_OBJ_NONE ) + assert( 0 ); + if ( f >= nPref ) + pEntry->Number += Aig_WordCountOnes( pEntry->pData[0] ); + } + } +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Saig_ManComputeSwitching( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Saig_ManComputeProbOne( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)nOnes / nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Saig_ManComputeProbOnePlus( int nOnes, int nSimWords, int fCompl ) +{ + int nTotal = 32 * nSimWords; + if ( fCompl ) + return (float)(nTotal-nOnes) / nTotal; + else + return (float)nOnes / nTotal; +} + +/**Function************************************************************* + + Synopsis [Compute switching probabilities of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManComputeSwitchProbs_old( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + extern char * Abc_FrameReadFlag( char * pFlag ); + Saig_SimObj_t * pAig, * pEntry; + Vec_Int_t * vSwitching; + float * pSwitching; + int nFramesReal, clk, clkTotal = clock(); + vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) ); + pSwitching = (float *)vSwitching->pArray; +clk = clock(); + pAig = Saig_ManCreateMan( p ); +//PRT( "\nCreation ", clock() - clk ); + + Aig_ManRandom( 1 ); + // get the number of frames to simulate + // if the parameter "seqsimframes" is defined, use it + // otherwise, use the given number of frames "nFrames" + nFramesReal = nFrames; + if ( Abc_FrameReadFlag("seqsimframes") ) + nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") ); + if ( nFramesReal <= nPref ) + { + printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref );\ + printf( "Setting the total number of frames to be %d.\n", nFrames ); + nFramesReal = nFrames; + } +//printf( "Simulating %d frames.\n", nFramesReal ); +clk = clock(); + Saig_ManSimulateFrames( pAig, nFramesReal, nPref ); +//PRT( "Simulation", clock() - clk ); +clk = clock(); + for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) + { +/* + if ( pEntry->Type == AIG_OBJ_AND ) + { + Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pEntry ); + Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pEntry ); + printf( "%5.2f = %5.2f * %5.2f (%7.4f)\n", + Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ), + Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ), + Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ), + Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ) - + Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ) * + Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ) + ); + } +*/ + if ( fProbOne ) + pSwitching[pEntry-pAig] = Saig_ManComputeProbOne( pEntry->Number, nFramesReal - nPref ); + else + pSwitching[pEntry-pAig] = Saig_ManComputeSwitching( pEntry->Number, nFramesReal - nPref ); +//printf( "%3d : %7.2f\n", pEntry-pAig, pSwitching[pEntry-pAig] ); + } + free( pAig ); +//PRT( "Switch ", clock() - clk ); +//PRT( "TOTAL ", clock() - clkTotal ); + +// Aig_CManCreate( p ); + return vSwitching; +} + + + + +typedef struct Aig_CMan_t_ Aig_CMan_t; +struct Aig_CMan_t_ +{ + // parameters + int nIns; + int nNodes; + int nOuts; + // current state + int iNode; + int iDiff0; + int iDiff1; + unsigned char * pCur; + // stored data + int iPrev; + int nBytes; + unsigned char Data[0]; +}; + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_CMan_t * Aig_CManStart( int nIns, int nNodes, int nOuts ) +{ + Aig_CMan_t * p; + p = (Aig_CMan_t *)ALLOC( char, sizeof(Aig_CMan_t) + 2*(2*nNodes + nOuts) ); + memset( p, 0, sizeof(Aig_CMan_t) ); + // set parameters + p->nIns = nIns; + p->nOuts = nOuts; + p->nNodes = nNodes; + p->nBytes = 2*(2*nNodes + nOuts); + // prepare the manager + p->iNode = 1 + p->nIns; + p->iPrev = -1; + p->pCur = p->Data; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManStop( Aig_CMan_t * p ) +{ + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManRestart( Aig_CMan_t * p ) +{ + assert( p->iNode == 1 + p->nIns + p->nNodes + p->nOuts ); + p->iNode = 1 + p->nIns; + p->iPrev = -1; + p->pCur = p->Data; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManStoreNum( Aig_CMan_t * p, unsigned x ) +{ + while ( x & ~0x7f ) + { + *p->pCur++ = (x & 0x7f) | 0x80; + x >>= 7; + } + *p->pCur++ = x; + assert( p->pCur - p->Data < p->nBytes - 10 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CManRestoreNum( Aig_CMan_t * p ) +{ + int ch, i, x = 0; + for ( i = 0; (ch = *p->pCur++) & 0x80; i++ ) + x |= (ch & 0x7f) << (7 * i); + return x | (ch << (7 * i)); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManAddNode( Aig_CMan_t * p, int iFan0, int iFan1 ) +{ + assert( iFan0 < iFan1 ); + assert( iFan1 < (p->iNode << 1) ); + Aig_CManStoreNum( p, (p->iNode++ << 1) - iFan1 ); + Aig_CManStoreNum( p, iFan1 - iFan0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManAddPo( Aig_CMan_t * p, int iFan0 ) +{ + if ( p->iPrev == -1 ) + Aig_CManStoreNum( p, p->iNode - iFan0 ); + else if ( p->iPrev <= iFan0 ) + Aig_CManStoreNum( p, (iFan0 - p->iPrev) << 1 ); + else + Aig_CManStoreNum( p,((p->iPrev - iFan0) << 1) | 1 ); + p->iPrev = iFan0; + p->iNode++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManGetNode( Aig_CMan_t * p, int * piFan0, int * piFan1 ) +{ + *piFan1 = (p->iNode++ << 1) - Aig_CManRestoreNum( p ); + *piFan0 = *piFan1 - Aig_CManRestoreNum( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CManGetPo( Aig_CMan_t * p ) +{ + int Num = Aig_CManRestoreNum( p ); + if ( p->iPrev == -1 ) + p->iPrev = p->iNode; + p->iNode++; + if ( Num & 1 ) + return p->iPrev = p->iPrev + (Num >> 1); + return p->iPrev = p->iPrev - (Num >> 1); +} + +/**Function************************************************************* + + Synopsis [Compute switching probabilities of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p ) +{ + Aig_CMan_t * pCMan; + Aig_Obj_t * pObj; + int i; + pCMan = Aig_CManStart( Aig_ManPiNum(p), Aig_ManNodeNum(p), Aig_ManPoNum(p) ); + Aig_ManForEachNode( p, pObj, i ) + Aig_CManAddNode( pCMan, + (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj), + (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj) ); + Aig_ManForEachPo( p, pObj, i ) + Aig_CManAddPo( pCMan, + (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj) ); + printf( "\nBytes alloc = %5d. Bytes used = %7d. Ave per node = %4.2f. \n", + pCMan->nBytes, pCMan->pCur - pCMan->Data, + 1.0 * (pCMan->pCur - pCMan->Data) / (pCMan->nNodes + pCMan->nOuts ) ); +// Aig_CManStop( pCMan ); + return pCMan; +} + +/**Function************************************************************* + + Synopsis [Compute switching probabilities of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManComputeSwitchProbs2( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/saig/saigWnd.c b/src/aig/saig/saigWnd.c new file mode 100644 index 00000000..5524e19f --- /dev/null +++ b/src/aig/saig/saigWnd.c @@ -0,0 +1,809 @@ +/**CFile**************************************************************** + + FileName [saigWnd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Sequential windowing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigWnd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of PI/internal nodes.] + + Description [Marks all the visited nodes with the current ID. + Does not collect constant node and PO/LI nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowOutline_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Vec_Ptr_t * vNodes, int * pDists ) +{ + Aig_Obj_t * pMatch, * pFanout; + int fCollected, iFanout = -1, i; + if ( nDist == 0 ) + return; + if ( pDists[pObj->Id] >= nDist ) + return; + pDists[pObj->Id] = nDist; + fCollected = Aig_ObjIsTravIdCurrent( p, pObj ); + Aig_ObjSetTravIdCurrent( p, pObj ); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Saig_ObjIsPo(p, pObj) ) + return; + if ( Saig_ObjIsLi(p, pObj) ) + { + pMatch = Saig_ObjLiToLo( p, pObj ); + if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) ) + Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists ); + Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists ); + return; + } + if ( !fCollected ) + Vec_PtrPush( vNodes, pObj ); + if ( Saig_ObjIsPi(p, pObj) ) + return; + if ( Saig_ObjIsLo(p, pObj) ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) ) + Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists ); + Saig_ManWindowOutline_rec( p, Aig_ObjFanin1(pObj), nDist-1, vNodes, pDists ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of PI/internal nodes.] + + Description [Marks all the visited nodes with the current ID.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManWindowOutline( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObjLi, * pObjLo; + int * pDists, i; + pDists = CALLOC( int, Aig_ManObjNumMax(p) ); + vNodes = Vec_PtrAlloc( 1000 ); + Aig_ManIncrementTravId( p ); + Saig_ManWindowOutline_rec( p, pObj, nDist, vNodes, pDists ); + Vec_PtrSort( vNodes, Aig_ObjCompareIdIncrease ); + // make sure LI/LO are labeled/unlabeled mutually + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + assert( Aig_ObjIsTravIdCurrent(p, pObjLi) == + Aig_ObjIsTravIdCurrent(p, pObjLo) ); + free( pDists ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has unlabeled fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ObjHasUnlabeledFanout( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int iFanout = -1, i; + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + if ( Saig_ObjIsPo(p, pFanout) || !Aig_ObjIsTravIdCurrent(p, pFanout) ) + return pFanout; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Collects primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManWindowCollectPis( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Vec_Ptr_t * vNodesPi; + Aig_Obj_t * pObj, * pMatch, * pFanin; + int i; + vNodesPi = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( Saig_ObjIsPi(p, pObj) ) + { + assert( pObj->pData == NULL ); + Vec_PtrPush( vNodesPi, pObj ); + } + else if ( Saig_ObjIsLo(p, pObj) ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + pFanin = Aig_ObjFanin0(pMatch); + if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) + Vec_PtrPush( vNodesPi, pFanin ); + } + else + { + assert( Aig_ObjIsNode(pObj) ); + pFanin = Aig_ObjFanin0(pObj); + if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) + Vec_PtrPush( vNodesPi, pFanin ); + pFanin = Aig_ObjFanin1(pObj); + if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) + Vec_PtrPush( vNodesPi, pFanin ); + } + } + return vNodesPi; +} + +/**Function************************************************************* + + Synopsis [Collects primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManWindowCollectPos( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Ptr_t ** pvPointers ) +{ + Vec_Ptr_t * vNodesPo; + Aig_Obj_t * pObj, * pPointer; + int i; + vNodesPo = Vec_PtrAlloc( 1000 ); + if ( pvPointers ) + *pvPointers = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( (pPointer = Saig_ObjHasUnlabeledFanout(p, pObj)) ) + { + Vec_PtrPush( vNodesPo, pObj ); + if ( pvPointers ) + Vec_PtrPush( *pvPointers, pPointer ); + } + } + return vNodesPo; +} + +/**Function************************************************************* + + Synopsis [Extracts the window AIG from the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowExtractNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pMatch; + Vec_Ptr_t * vNodesPi, * vNodesPo; + int i, nRegCount; + Aig_ManCleanData( p ); + // create the new manager + pNew = Aig_ManStart( Vec_PtrSize(vNodes) ); + pNew->pName = Aig_UtilStrsav( "wnd" ); + pNew->pSpec = NULL; + // map constant nodes + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + // create real PIs + vNodesPi = Saig_ManWindowCollectPis( p, vNodes ); + Vec_PtrForEachEntry( vNodesPi, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pNew); + Vec_PtrFree( vNodesPi ); + // create register outputs + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( Saig_ObjIsLo(p, pObj) ) + pObj->pData = Aig_ObjCreatePi(pNew); + } + // create internal nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + // create POs + vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL ); + Vec_PtrForEachEntry( vNodesPo, pObj, i ) + Aig_ObjCreatePo( pNew, pObj->pData ); + Vec_PtrFree( vNodesPo ); + // create register inputs + nRegCount = 0; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( Saig_ObjIsLo(p, pObj) ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) ); + nRegCount++; + } + } + Aig_ManSetRegNum( pNew, nRegCount ); + Aig_ManCleanup( pNew ); + return pNew; +} + +static void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall, + Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ); + +/**Function************************************************************* + + Synopsis [Adds nodes for the big manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowInsertBig_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjBig, + Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ) +{ + Aig_Obj_t * pMatch; + if ( pObjBig->pData ) + return; + if ( (pMatch = Vec_PtrEntry( vBigNode2SmallPo, pObjBig->Id )) ) + { + Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pMatch), vBigNode2SmallPo, vSmallPi2BigNode ); + pObjBig->pData = Aig_ObjChild0Copy(pMatch); + return; + } + assert( Aig_ObjIsNode(pObjBig) ); + Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode ); + Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin1(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode ); + pObjBig->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjBig), Aig_ObjChild1Copy(pObjBig) ); +} + +/**Function************************************************************* + + Synopsis [Adds nodes for the small manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall, + Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ) +{ + Aig_Obj_t * pMatch; + if ( pObjSmall->pData ) + return; + if ( (pMatch = Vec_PtrEntry( vSmallPi2BigNode, pObjSmall->Id )) ) + { + Saig_ManWindowInsertBig_rec( pNew, pMatch, vBigNode2SmallPo, vSmallPi2BigNode ); + pObjSmall->pData = pMatch->pData; + return; + } + assert( Aig_ObjIsNode(pObjSmall) ); + Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode ); + Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin1(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode ); + pObjSmall->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjSmall), Aig_ObjChild1Copy(pObjSmall) ); +} + +/**Function************************************************************* + + Synopsis [Extracts the network from the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowInsertNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes, Aig_Man_t * pWnd ) +{ + Aig_Man_t * pNew; + Vec_Ptr_t * vBigNode2SmallPo, * vSmallPi2BigNode; + Vec_Ptr_t * vNodesPi, * vNodesPo; + Aig_Obj_t * pObj; + int i; + + // set mapping of small PIs into big nodes + vSmallPi2BigNode = Vec_PtrStart( Aig_ManObjNumMax(pWnd) ); + vNodesPi = Saig_ManWindowCollectPis( p, vNodes ); + Vec_PtrForEachEntry( vNodesPi, pObj, i ) + Vec_PtrWriteEntry( vSmallPi2BigNode, Aig_ManPi(pWnd, i)->Id, pObj ); + assert( i == Saig_ManPiNum(pWnd) ); + Vec_PtrFree( vNodesPi ); + + // set mapping of big nodes into small POs + vBigNode2SmallPo = Vec_PtrStart( Aig_ManObjNumMax(p) ); + vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL ); + Vec_PtrForEachEntry( vNodesPo, pObj, i ) + Vec_PtrWriteEntry( vBigNode2SmallPo, pObj->Id, Aig_ManPo(pWnd, i) ); + assert( i == Saig_ManPoNum(pWnd) ); + Vec_PtrFree( vNodesPo ); + + // create the new manager + Aig_ManCleanData( p ); + Aig_ManCleanData( pWnd ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->pSpec = Aig_UtilStrsav( p->pSpec ); + // map constant nodes + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + pObj = Aig_ManConst1( pWnd ); + pObj->pData = Aig_ManConst1( pNew ); + + // create real PIs + Aig_ManForEachPi( p, pObj, i ) + if ( Saig_ObjIsPi(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) ) + pObj->pData = Aig_ObjCreatePi(pNew); + // create additional latch outputs + Saig_ManForEachLo( pWnd, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pNew); + + // create internal nodes starting from the big + Aig_ManForEachPo( p, pObj, i ) + if ( Saig_ObjIsPo(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) ) + { + Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode ); + pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + } + // create internal nodes starting from the small + Saig_ManForEachLi( pWnd, pObj, i ) + { + Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode ); + pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Vec_PtrFree( vBigNode2SmallPo ); + Vec_PtrFree( vSmallPi2BigNode ); + // set the new number of registers + assert( Aig_ManPiNum(pNew) - Aig_ManPiNum(p) == Aig_ManPoNum(pNew) - Aig_ManPoNum(p) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) + (Aig_ManPiNum(pNew) - Aig_ManPiNum(p)) ); + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Find a good object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter; + if ( Aig_ManRegNum(p) > 0 ) + { + if ( Aig_ManRegNum(p) == 1 ) + return Saig_ManLo( p, 0 ); + Saig_ManForEachLo( p, pObj, i ) + { + if ( i == Aig_ManRegNum(p)/2 ) + return pObj; + } + } + else + { + Counter = 0; + assert( Aig_ManNodeNum(p) > 1 ); + Aig_ManForEachNode( p, pObj, i ) + { + if ( Counter++ == Aig_ManNodeNum(p)/2 ) + return pObj; + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Computes sequential window of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ) +{ + Aig_Man_t * pWnd; + Vec_Ptr_t * vNodes; + Aig_ManFanoutStart( p ); + vNodes = Saig_ManWindowOutline( p, pObj, nDist ); + pWnd = Saig_ManWindowExtractNodes( p, vNodes ); + Vec_PtrFree( vNodes ); + Aig_ManFanoutStop( p ); + return pWnd; +} + +/**Function************************************************************* + + Synopsis [Computes sequential window of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd ) +{ + Aig_Man_t * pNew, * pWndTest; + Vec_Ptr_t * vNodes; + Aig_ManFanoutStart( p ); + + vNodes = Saig_ManWindowOutline( p, pObj, nDist ); + pWndTest = Saig_ManWindowExtractNodes( p, vNodes ); + if ( Saig_ManPiNum(pWndTest) != Saig_ManPiNum(pWnd) || + Saig_ManPoNum(pWndTest) != Saig_ManPoNum(pWnd) ) + { + printf( "The window cannot be reinserted because PI/PO counts do not match.\n" ); + Aig_ManStop( pWndTest ); + Vec_PtrFree( vNodes ); + Aig_ManFanoutStop( p ); + return NULL; + } + Aig_ManStop( pWndTest ); + Vec_PtrFree( vNodes ); + + // insert the nodes + Aig_ManCleanData( p ); + vNodes = Saig_ManWindowOutline( p, pObj, nDist ); + pNew = Saig_ManWindowInsertNodes( p, vNodes, pWnd ); + Vec_PtrFree( vNodes ); + Aig_ManFanoutStop( p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Tests the above computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowTest( Aig_Man_t * p ) +{ + int nDist = 3; + Aig_Man_t * pWnd, * pNew; + Aig_Obj_t * pPivot; + pPivot = Saig_ManFindPivot( p ); + assert( pPivot != NULL ); + pWnd = Saig_ManWindowExtract( p, pPivot, nDist ); + pNew = Saig_ManWindowInsert( p, pPivot, nDist, pWnd ); + Aig_ManStop( pWnd ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes that are not linked to each other.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManCollectedDiffNodes( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj0, * pObj1; + int i; + // collect nodes that are not linked + Aig_ManIncrementTravId( p0 ); + vNodes = Vec_PtrAlloc( 1000 ); + Aig_ManForEachObj( p0, pObj0, i ) + { + pObj1 = Aig_ObjRepr( p0, pObj0 ); + if ( pObj1 != NULL ) + { + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + continue; + } + // mark and collect unmatched objects + Aig_ObjSetTravIdCurrent( p0, pObj0 ); + if ( Aig_ObjIsNode(pObj0) || Aig_ObjIsPi(pObj0) ) + Vec_PtrPush( vNodes, pObj0 ); + } + // make sure LI/LO are labeled/unlabeled mutually + Saig_ManForEachLiLo( p0, pObj0, pObj1, i ) + assert( Aig_ObjIsTravIdCurrent(p0, pObj0) == + Aig_ObjIsTravIdCurrent(p0, pObj1) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Creates PIs of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowCreatePis( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Ptr_t * vNodes0 ) +{ + Aig_Obj_t * pObj, * pMatch, * pFanin; + int i, Counter = 0; + Vec_PtrForEachEntry( vNodes0, pObj, i ) + { + if ( Saig_ObjIsLo(p0, pObj) ) + { + pMatch = Saig_ObjLoToLi( p0, pObj ); + pFanin = Aig_ObjFanin0(pMatch); + if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) + { + pFanin->pData = Aig_ObjCreatePi(pNew); + pMatch = Aig_ObjRepr( p0, pFanin ); + assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); + assert( pMatch != NULL ); + pMatch->pData = pFanin->pData; + Counter++; + } + } + else + { + assert( Aig_ObjIsNode(pObj) ); + pFanin = Aig_ObjFanin0(pObj); + if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) + { + pFanin->pData = Aig_ObjCreatePi(pNew); + pMatch = Aig_ObjRepr( p0, pFanin ); + assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); + assert( pMatch != NULL ); + pMatch->pData = pFanin->pData; + Counter++; + } + pFanin = Aig_ObjFanin1(pObj); + if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) + { + pFanin->pData = Aig_ObjCreatePi(pNew); + pMatch = Aig_ObjRepr( p0, pFanin ); + assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); + assert( pMatch != NULL ); + pMatch->pData = pFanin->pData; + Counter++; + } + } + } +// printf( "Added %d primary inputs.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Creates POs of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowCreatePos( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1, * pMiter; + Aig_Obj_t * pFanin0, * pFanin1; + int i; + Aig_ManForEachObj( p0, pObj0, i ) + { + if ( Aig_ObjIsTravIdCurrent(p0, pObj0) ) + continue; + if ( Aig_ObjIsConst1(pObj0) ) + continue; + if ( Aig_ObjIsPi(pObj0) ) + continue; + pObj1 = Aig_ObjRepr( p0, pObj0 ); + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + if ( Aig_ObjIsPo(pObj0) ) + { + pFanin0 = Aig_ObjFanin0(pObj0); + pFanin1 = Aig_ObjFanin0(pObj1); + assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == + Aig_ObjIsTravIdCurrent(p1, pFanin1) ); + if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) + { + pMiter = Aig_Exor( pNew, pFanin0->pData, pFanin1->pData ); + Aig_ObjCreatePo( pNew, pMiter ); + } + } + else + { + assert( Aig_ObjIsNode(pObj0) ); + + pFanin0 = Aig_ObjFanin0(pObj0); + pFanin1 = Aig_ObjFanin0(pObj1); + assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == + Aig_ObjIsTravIdCurrent(p1, pFanin1) ); + if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) + { + pMiter = Aig_Exor( pNew, pFanin0->pData, pFanin1->pData ); + Aig_ObjCreatePo( pNew, pMiter ); + } + + pFanin0 = Aig_ObjFanin1(pObj0); + pFanin1 = Aig_ObjFanin1(pObj1); + assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == + Aig_ObjIsTravIdCurrent(p1, pFanin1) ); + if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) + { + pMiter = Aig_Exor( pNew, pFanin0->pData, pFanin1->pData ); + Aig_ObjCreatePo( pNew, pMiter ); + } + } + } +} + + +/**Function************************************************************* + + Synopsis [Extracts the window AIG from the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj0, * pObj1, * pMatch0, * pMatch1; + Vec_Ptr_t * vNodes0, * vNodes1; + int i, nRegCount; + // add matching of POs and LIs + Saig_ManForEachPo( p0, pObj0, i ) + { + pObj1 = Aig_ManPo( p1, i ); + Aig_ObjSetRepr( p0, pObj0, pObj1 ); + Aig_ObjSetRepr( p1, pObj1, pObj0 ); + } + Saig_ManForEachLi( p0, pObj0, i ) + { + pMatch0 = Saig_ObjLiToLo( p0, pObj0 ); + pMatch1 = Aig_ObjRepr( p0, pMatch0 ); + if ( pMatch1 == NULL ) + continue; + assert( pMatch0 == Aig_ObjRepr( p1, pMatch1 ) ); + pObj1 = Saig_ObjLoToLi( p1, pMatch1 ); + Aig_ObjSetRepr( p0, pObj0, pObj1 ); + Aig_ObjSetRepr( p1, pObj1, pObj0 ); + } + // clean the markings + Aig_ManCleanData( p0 ); + Aig_ManCleanData( p1 ); + // collect nodes that are not linked + vNodes0 = Saig_ManCollectedDiffNodes( p0, p1 ); + vNodes1 = Saig_ManCollectedDiffNodes( p1, p0 ); + // create the new manager + pNew = Aig_ManStart( Vec_PtrSize(vNodes0) + Vec_PtrSize(vNodes1) ); + pNew->pName = Aig_UtilStrsav( "wnd" ); + pNew->pSpec = NULL; + // map constant nodes + pObj0 = Aig_ManConst1( p0 ); + pObj0->pData = Aig_ManConst1( pNew ); + pObj1 = Aig_ManConst1( p1 ); + pObj1->pData = Aig_ManConst1( pNew ); + // create real PIs + Saig_ManWindowCreatePis( pNew, p0, p1, vNodes0 ); + Saig_ManWindowCreatePis( pNew, p1, p0, vNodes1 ); + // create register outputs + Vec_PtrForEachEntry( vNodes0, pObj0, i ) + { + if ( Saig_ObjIsLo(p0, pObj0) ) + pObj0->pData = Aig_ObjCreatePi(pNew); + } + Vec_PtrForEachEntry( vNodes1, pObj1, i ) + { + if ( Saig_ObjIsLo(p1, pObj1) ) + pObj1->pData = Aig_ObjCreatePi(pNew); + } + // create internal nodes + Vec_PtrForEachEntry( vNodes0, pObj0, i ) + { + if ( Aig_ObjIsNode(pObj0) ) + pObj0->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) ); + } + Vec_PtrForEachEntry( vNodes1, pObj1, i ) + { + if ( Aig_ObjIsNode(pObj1) ) + pObj1->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj1), Aig_ObjChild1Copy(pObj1) ); + } + // create POs + Saig_ManWindowCreatePos( pNew, p0, p1 ); +// Saig_ManWindowCreatePos( pNew, p1, p0 ); + // create register inputs + nRegCount = 0; + Vec_PtrForEachEntry( vNodes0, pObj0, i ) + { + if ( Saig_ObjIsLo(p0, pObj0) ) + { + pMatch0 = Saig_ObjLoToLi( p0, pObj0 ); + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch0) ); + nRegCount++; + } + } + Vec_PtrForEachEntry( vNodes1, pObj1, i ) + { + if ( Saig_ObjIsLo(p1, pObj1) ) + { + pMatch1 = Saig_ObjLoToLi( p1, pObj1 ); + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch1) ); + nRegCount++; + } + } + Aig_ManSetRegNum( pNew, nRegCount ); + Aig_ManCleanup( pNew ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw/ssw.h b/src/aig/ssw/ssw.h index 5d70812d..b3222fca 100644 --- a/src/aig/ssw/ssw.h +++ b/src/aig/ssw/ssw.h @@ -51,11 +51,16 @@ struct Ssw_Pars_t_ int nBTLimitGlobal;// conflict limit for multiple runs int nMinDomSize; // min clock domain considered for optimization int nItersStop; // stop after the given number of iterations + int fDumpSRInit; // dumps speculative reduction + int nResimDelta; // the number of nodes to resimulate int fPolarFlip; // uses polarity adjustment int fLatchCorr; // perform register correspondence int fSemiFormal; // enable semiformal filtering int fUniqueness; // enable uniqueness constraints int fDynamic; // enable dynamic addition of constraints + int fLocalSim; // enable local simulation simulation + int fPartSigCorr; // uses partial signal correspondence + int nIsleDist; // extends islands by the given distance int fVerbose; // verbose stats int fFlopVerbose; // verbose printout of redundant flops // optimized latch correspondence @@ -82,6 +87,8 @@ struct Ssw_Cex_t_ unsigned pData[0]; // the cex bit data (the number of bits: nRegs + (iFrame+1) * nPis) }; +typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -97,8 +104,11 @@ extern void Ssw_ManSetDefaultParams( Ssw_Pars_t * p ); extern void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p ); extern Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); extern Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); +/*=== sswIslands.c ==========================================================*/ +extern int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ); +extern int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars ); /*=== sswMiter.c ===================================================*/ -extern int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose ); +extern int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose ); /*=== sswPart.c ==========================================================*/ extern Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); /*=== sswPairs.c ===================================================*/ @@ -107,6 +117,14 @@ extern int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec extern int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars ); extern int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars ); /*=== sswSim.c ===================================================*/ +extern Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords ); +extern Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ); +extern void Ssw_SmlUnnormalize( Ssw_Sml_t * p ); +extern void Ssw_SmlStop( Ssw_Sml_t * p ); +extern int Ssw_SmlNumFrames( Ssw_Sml_t * p ); +extern int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p ); +extern unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj ); +extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); extern Ssw_Cex_t * Ssw_SmlAllocCounterExample( int nRegs, int nRealPis, int nFrames ); extern void Ssw_SmlFreeCounterExample( Ssw_Cex_t * pCex ); extern int Ssw_SmlRunCounterExample( Aig_Man_t * pAig, Ssw_Cex_t * p ); diff --git a/src/aig/ssw/sswAig.c b/src/aig/ssw/sswAig.c index fda05941..97f0a755 100644 --- a/src/aig/ssw/sswAig.c +++ b/src/aig/ssw/sswAig.c @@ -211,6 +211,7 @@ Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p ) // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames ); + pFrames->pName = Aig_UtilStrsav( p->pAig->pName ); // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) diff --git a/src/aig/ssw/sswClass.c b/src/aig/ssw/sswClass.c index 771fd530..3528ae27 100644 --- a/src/aig/ssw/sswClass.c +++ b/src/aig/ssw/sswClass.c @@ -585,7 +585,7 @@ int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands ) SeeAlso [] ***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs, int fVerbose ) +Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int nMaxLevs, int fVerbose ) { // int nFrames = 4; // int nWords = 1; @@ -595,7 +595,7 @@ Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs, // int nWords = 4; // int nIters = 0; - int nFrames = 4; + int nFrames = AIG_MAX( nFramesK, 4 ); int nWords = 2; int nIters = 16; Ssw_Cla_t * p; @@ -836,7 +836,7 @@ Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses ) SeeAlso [] ***********************************************************************/ -Ssw_Cla_t * Ssw_ClassesFromIslands( Aig_Man_t * pMiter, Vec_Int_t * vPairs ) +Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs ) { Ssw_Cla_t * p; Aig_Obj_t ** ppClassNew; diff --git a/src/aig/ssw/sswCore.c b/src/aig/ssw/sswCore.c index 68c00a0e..38a36022 100644 --- a/src/aig/ssw/sswCore.c +++ b/src/aig/ssw/sswCore.c @@ -51,10 +51,13 @@ void Ssw_ManSetDefaultParams( Ssw_Pars_t * p ) p->nBTLimitGlobal = 5000000; // conflict limit for all runs p->nMinDomSize = 100; // min clock domain considered for optimization p->nItersStop = 0; // stop after the given number of iterations + p->nResimDelta = 1000; // the internal of nodes to resimulate p->fPolarFlip = 0; // uses polarity adjustment p->fLatchCorr = 0; // performs register correspondence p->fSemiFormal = 0; // enable semiformal filtering p->fUniqueness = 0; // enable uniqueness constraints + p->fDynamic = 0; // dynamic partitioning + p->fLocalSim = 0; // local simulation p->fVerbose = 0; // verbose stats // latch correspondence p->fLatchCorrOpt = 0; // performs optimized register correspondence @@ -260,6 +263,9 @@ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) if ( pPars->fLatchCorrOpt ) { pPars->fLatchCorr = 1; + pPars->nFramesAddSim = 0; + if ( (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) ) + return Ssw_SignalCorrespondencePart( pAig, pPars ); } else { @@ -276,7 +282,7 @@ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) if ( p->pPars->nConstrs == 0 ) { // perform one round of seq simulation and generate candidate equivalence classes - p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->fLatchCorr, pPars->nMaxLevs, pPars->fVerbose ); + p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->nFramesK, pPars->fLatchCorr, pPars->nMaxLevs, pPars->fVerbose ); // p->ppClasses = Ssw_ClassesPrepareTargets( pAig ); if ( pPars->fLatchCorrOpt ) p->pSml = Ssw_SmlStart( pAig, 0, 2, 1 ); @@ -292,6 +298,8 @@ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchCorr, pPars->nMaxLevs ); Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit ); } + if ( p->pPars->fLocalSim ) + p->pVisited = CALLOC( int, Ssw_SmlNumFrames( p->pSml ) * Aig_ManObjNumMax(p->pAig) ); // perform refinement of classes pAigNew = Ssw_SignalCorrespondenceRefine( p ); if ( pPars->fUniqueness ) diff --git a/src/aig/ssw/sswDyn.c b/src/aig/ssw/sswDyn.c index d5559408..d9ac07a9 100644 --- a/src/aig/ssw/sswDyn.c +++ b/src/aig/ssw/sswDyn.c @@ -277,6 +277,83 @@ p->timeSimSat += clock() - clk; return RetValue1 > 0 || RetValue2 > 0; } +/**Function************************************************************* + + Synopsis [Performs one round of simulation with counter-examples.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManSweepResimulateDynLocal( Ssw_Man_t * p, int f ) +{ + Aig_Obj_t * pObj, * pRepr, ** ppClass; + int i, k, nSize, RetValue1, RetValue2, clk = clock(); + p->nSimRounds++; + // transfer PI simulation information from storage +// Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); + Ssw_ManSweepTransferDyn( p ); + // determine const1 cands and classes to be simulated + Vec_PtrClear( p->vResimConsts ); + Vec_PtrClear( p->vResimClasses ); + Aig_ManIncrementTravId( p->pAig ); + for ( i = p->iNodeStart; i < p->iNodeLast + p->pPars->nResimDelta; i++ ) + { + if ( i >= Aig_ManObjNumMax( p->pAig ) ) + break; + pObj = Aig_ManObj( p->pAig, i ); + if ( pObj == NULL ) + continue; + if ( Ssw_ObjIsConst1Cand(p->pAig, pObj) ) + { + Vec_PtrPush( p->vResimConsts, pObj ); + continue; + } + pRepr = Aig_ObjRepr(p->pAig, pObj); + if ( pRepr == NULL ) + continue; + if ( Aig_ObjIsTravIdCurrent(p->pAig, pRepr) ) + continue; + Aig_ObjSetTravIdCurrent(p->pAig, pRepr); + Vec_PtrPush( p->vResimClasses, pRepr ); + } + // simulate internal nodes +// Ssw_SmlSimulateOneFrame( p->pSml ); +// Ssw_SmlSimulateOne( p->pSml ); + // resimulate dynamically +// Aig_ManIncrementTravId( p->pAig ); +// Aig_ObjIsTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) ); + p->nVisCounter++; + Vec_PtrForEachEntry( p->vResimConsts, pObj, i ) + Ssw_SmlSimulateOneDyn_rec( p->pSml, pObj, p->nFrames-1, p->pVisited, p->nVisCounter ); + // resimulate the cone of influence of the cand classes + Vec_PtrForEachEntry( p->vResimClasses, pRepr, i ) + { + ppClass = Ssw_ClassesReadClass( p->ppClasses, pRepr, &nSize ); + for ( k = 0; k < nSize; k++ ) + Ssw_SmlSimulateOneDyn_rec( p->pSml, ppClass[k], p->nFrames-1, p->pVisited, p->nVisCounter ); + } + + // check equivalence classes +// RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); +// RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); + // refine these nodes + RetValue1 = Ssw_ClassesRefineConst1Group( p->ppClasses, p->vResimConsts, 1 ); + RetValue2 = 0; + Vec_PtrForEachEntry( p->vResimClasses, pRepr, i ) + RetValue2 += Ssw_ClassesRefineOneClass( p->ppClasses, pRepr, 1 ); + + // prepare simulation info for the next round + Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); + p->nPatterns = 0; + p->nSimRounds++; +p->timeSimSat += clock() - clk; + return RetValue1 > 0 || RetValue2 > 0; +} + /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] @@ -321,8 +398,11 @@ p->timeReduce += clock() - clk; Ssw_ClassesClearRefined( p->ppClasses ); if ( p->pPars->fVerbose ) pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); + p->iNodeStart = 0; Aig_ManForEachObj( p->pAig, pObj, i ) { + if ( p->iNodeStart == 0 ) + p->iNodeStart = i; if ( p->pPars->fVerbose ) Bar_ProgressUpdate( pProgress, i, NULL ); if ( Saig_ObjIsLo(p->pAig, pObj) ) @@ -341,7 +421,14 @@ p->timeReduce += clock() - clk; { // resimulate if ( p->nPatterns > 0 ) - Ssw_ManSweepResimulateDyn( p, f ); + { + p->iNodeLast = i; + if ( p->pPars->fLocalSim ) + Ssw_ManSweepResimulateDynLocal( p, f ); + else + Ssw_ManSweepResimulateDyn( p, f ); + p->iNodeStart = i+1; + } // printf( "Recycling SAT solver with %d vars and %d calls.\n", // p->pMSat->nSatVars, p->nRecycleCalls ); // Aig_ManCleanMarkAB( p->pAig ); @@ -363,11 +450,24 @@ p->timeReduce += clock() - clk; } // resimulate if ( p->nPatterns == 32 ) - Ssw_ManSweepResimulateDyn( p, f ); + { + p->iNodeLast = i; + if ( p->pPars->fLocalSim ) + Ssw_ManSweepResimulateDynLocal( p, f ); + else + Ssw_ManSweepResimulateDyn( p, f ); + p->iNodeStart = i+1; + } } // resimulate if ( p->nPatterns > 0 ) - Ssw_ManSweepResimulateDyn( p, f ); + { + p->iNodeLast = i; + if ( p->pPars->fLocalSim ) + Ssw_ManSweepResimulateDynLocal( p, f ); + else + Ssw_ManSweepResimulateDyn( p, f ); + } // collect stats if ( p->pPars->fVerbose ) Bar_ProgressStop( pProgress ); diff --git a/src/aig/ssw/sswInt.h b/src/aig/ssw/sswInt.h index 90c1367f..930796fc 100644 --- a/src/aig/ssw/sswInt.h +++ b/src/aig/ssw/sswInt.h @@ -45,7 +45,6 @@ typedef struct Ssw_Man_t_ Ssw_Man_t; // signal correspondence manager typedef struct Ssw_Frm_t_ Ssw_Frm_t; // unrolled frames manager typedef struct Ssw_Sat_t_ Ssw_Sat_t; // SAT solver manager typedef struct Ssw_Cla_t_ Ssw_Cla_t; // equivalence classe manager -typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager struct Ssw_Man_t_ { @@ -86,8 +85,14 @@ struct Ssw_Man_t_ int nSRMiterMaxId; // max ID after which the last frame begins Vec_Ptr_t * vNewLos; // new time frame LOs of to constrain Vec_Int_t * vNewPos; // new time frame POs of to add constraints - // sequential simulator - Ssw_Sml_t * pSml; + int * pVisited; // flags to label visited nodes in each frame + int nVisCounter; // the traversal ID + // sequential simulation + Ssw_Sml_t * pSml; // the simulator + int iNodeStart; // the first node considered + int iNodeLast; // the last node considered + Vec_Ptr_t * vResimConsts; // resimulation constants + Vec_Ptr_t * vResimClasses; // resimulation classes // counter example storage int nPatWords; // the number of words in the counter example unsigned * pPatWords; // the counter example @@ -201,11 +206,11 @@ extern void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, extern void Ssw_ClassesCheck( Ssw_Cla_t * p ); extern void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose ); extern void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj ); -extern Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs, int fVerbose ); +extern Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int nMaxLevs, int fVerbose ); extern Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs ); extern Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig ); extern Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses ); -extern Ssw_Cla_t * Ssw_ClassesFromIslands( Aig_Man_t * pMiter, Vec_Int_t * vPairs ); +extern Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs ); extern int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive ); extern int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive ); extern int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ); @@ -242,13 +247,12 @@ extern void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, extern Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ); extern void Ssw_SmlClean( Ssw_Sml_t * p ); extern void Ssw_SmlStop( Ssw_Sml_t * p ); -extern int Ssw_SmlNumFrames( Ssw_Sml_t * p ); extern void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ); extern void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame ); extern void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat ); extern void Ssw_SmlSimulateOne( Ssw_Sml_t * p ); extern void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p ); -extern Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ); +extern void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter ); extern void Ssw_SmlResimulateSeq( Ssw_Sml_t * p ); /*=== sswSimSat.c ===================================================*/ extern void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); diff --git a/src/aig/ssw/sswIslands.c b/src/aig/ssw/sswIslands.c index 5a5783f7..64515f3e 100644 --- a/src/aig/ssw/sswIslands.c +++ b/src/aig/ssw/sswIslands.c @@ -24,9 +24,6 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static inline Aig_Obj_t * Aig_ObjChild0Copy2( Aig_Obj_t * pObj ) { return Aig_ObjFanin0(pObj)->pData? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Aig_ObjChild1Copy2( Aig_Obj_t * pObj ) { return Aig_ObjFanin1(pObj)->pData? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; } - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -52,7 +49,7 @@ void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) /**Function************************************************************* - Synopsis [Detects islands of common logic and returns them as pairs.] + Synopsis [Establishes relationship between nodes using pairing.] Description [] @@ -61,48 +58,127 @@ void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) SeeAlso [] ***********************************************************************/ -Vec_Int_t * Ssw_DetectIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fVerbose ) +void Ssw_MatchingStart( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs ) { - Vec_Int_t * vPairs; - Aig_Obj_t * pObj0, * pObj1, * pFanin0, * pFanin1; + Aig_Obj_t * pObj0, * pObj1; int i; - assert( Aig_ManRegNum(p0) > 0 ); - assert( Aig_ManRegNum(p1) > 0 ); - assert( Aig_ManRegNum(p0) >= nCommonFlops ); - assert( Aig_ManRegNum(p1) >= nCommonFlops ); - assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) ); - assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) ); + // create matching Aig_ManCleanData( p0 ); Aig_ManCleanData( p1 ); - // start structural equivalence - vPairs = Vec_IntAlloc( 1000 ); - Ssw_CreatePair( vPairs, Aig_ManConst1(p0), Aig_ManConst1(p1) ); + for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) + { + pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) ); + pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) ); + assert( pObj0->pData == NULL ); + assert( pObj1->pData == NULL ); + pObj0->pData = pObj1; + pObj1->pData = pObj0; + } + // make sure constants are matched + pObj0 = Aig_ManConst1( p0 ); + pObj1 = Aig_ManConst1( p1 ); + assert( pObj0->pData == pObj1 ); + assert( pObj1->pData == pObj0 ); + // make sure PIs are matched Saig_ManForEachPi( p0, pObj0, i ) - Ssw_CreatePair( vPairs, pObj0, Aig_ManPi(p1, i) ); + { + pObj1 = Aig_ManPi( p1, i ); + assert( pObj0->pData == pObj1 ); + assert( pObj1->pData == pObj0 ); + } + // make sure the POs are not matched + Aig_ManForEachPo( p0, pObj0, i ) + { + pObj1 = Aig_ManPo( p1, i ); + assert( pObj0->pData == NULL ); + assert( pObj1->pData == NULL ); + } + + // check that LIs/LOs are matched in sync Saig_ManForEachLo( p0, pObj0, i ) { - if ( i == nCommonFlops ) - break; - Ssw_CreatePair( vPairs, pObj0, Saig_ManLo(p1, i) ); + if ( pObj0->pData == NULL ) + continue; + pObj1 = pObj0->pData; + if ( !Saig_ObjIsLo(p1, pObj1) ) + printf( "Mismatch between LO pairs.\n" ); } - // find structurally equivalent nodes - Aig_ManForEachNode( p0, pObj0, i ) + Saig_ManForEachLo( p1, pObj1, i ) + { + if ( pObj1->pData == NULL ) + continue; + pObj0 = pObj1->pData; + if ( !Saig_ObjIsLo(p0, pObj0) ) + printf( "Mismatch between LO pairs.\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_MatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pNext, * pObj; + int i, k, iFan; + Vec_PtrClear( vNodes ); + Aig_ManIncrementTravId( p ); + Aig_ManForEachObj( p, pObj, i ) { - pFanin0 = Aig_ObjChild0Copy2( pObj0 ); - pFanin1 = Aig_ObjChild1Copy2( pObj0 ); - if ( pFanin0 == NULL || pFanin1 == NULL ) + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) continue; - pObj1 = Aig_TableLookupTwo( p1, pFanin0, pFanin1 ); - if ( pObj1 == NULL ) + if ( pObj->pData != NULL ) continue; - Ssw_CreatePair( vPairs, pObj0, pObj1 ); + if ( Saig_ObjIsLo(p, pObj) ) + { + pNext = Saig_ObjLoToLi(p, pObj); + pNext = Aig_ObjFanin0(pNext); + if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + if ( Aig_ObjIsNode(pObj) ) + { + pNext = Aig_ObjFanin0(pObj); + if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + pNext = Aig_ObjFanin1(pObj); + if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + Aig_ObjForEachFanout( p, pObj, pNext, iFan, k ) + { + if ( Saig_ObjIsPo(p, pNext) ) + continue; + if ( Saig_ObjIsLi(p, pNext) ) + pNext = Saig_ObjLiToLo(p, pNext); + if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } } - return vPairs; } /**Function************************************************************* - Synopsis [Collects additional Lis and Los.] + Synopsis [Establishes relationship between nodes using pairing.] Description [] @@ -111,22 +187,24 @@ Vec_Int_t * Ssw_DetectIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, SeeAlso [] ***********************************************************************/ -void Ssw_CollectExtraLiLo( Aig_Man_t * p, int nCommonFlops, Vec_Ptr_t * vLis, Vec_Ptr_t * vLos ) +int Ssw_MatchingCountUnmached( Aig_Man_t * p ) { - Aig_Obj_t * pObjLo, * pObjLi; - int i; - Saig_ManForEachLiLo( p, pObjLo, pObjLi, i ) + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachObj( p, pObj, i ) { - if ( i < nCommonFlops ) + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + if ( pObj->pData != NULL ) continue; - Vec_PtrPush( vLis, pObjLi ); - Vec_PtrPush( vLos, pObjLo ); + Counter++; } + return Counter; } /**Function************************************************************* - Synopsis [Overlays and extends the pairs.] + Synopsis [Establishes relationship between nodes using pairing.] Description [] @@ -135,80 +213,195 @@ void Ssw_CollectExtraLiLo( Aig_Man_t * p, int nCommonFlops, Vec_Ptr_t * vLis, Ve SeeAlso [] ***********************************************************************/ -void Ssw_OverlayIslands( Aig_Man_t * pTo, Aig_Man_t * pFrom, Vec_Ptr_t * vLisFrom, Vec_Ptr_t * vLosFrom, Vec_Int_t * vPairs, int nCommonFlops, int fToGoesFirst ) +void Ssw_MatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose ) { - Aig_Obj_t * pObjFrom, * pObjTo, * pFanin0To, * pFanin1To; - int i; - // create additional register outputs of From in To - Vec_PtrForEachEntry( vLosFrom, pObjFrom, i ) + Vec_Ptr_t * vNodes0, * vNodes1; + Aig_Obj_t * pNext0, * pNext1; + int d, k; + Aig_ManFanoutStart(p0); + Aig_ManFanoutStart(p1); + vNodes0 = Vec_PtrAlloc( 1000 ); + vNodes1 = Vec_PtrAlloc( 1000 ); + if ( fVerbose ) { - pObjTo = Aig_ObjCreatePi( pTo ); - if( fToGoesFirst ) - Ssw_CreatePair( vPairs, pObjTo, pObjFrom ); - else - Ssw_CreatePair( vPairs, pObjFrom, pObjTo ); + int nUnmached = Ssw_MatchingCountUnmached(p0); + printf( "Extending islands by %d steps:\n", nDist ); + printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", + 0, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0), + nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) ); } - // create additional nodes of From in To - Aig_ManForEachNode( pFrom, pObjFrom, i ) + for ( d = 0; d < nDist; d++ ) { - if ( pObjFrom->pData != NULL ) + Ssw_MatchingExtendOne( p0, vNodes0 ); + Ssw_MatchingExtendOne( p1, vNodes1 ); + Vec_PtrForEachEntry( vNodes0, pNext0, k ) + { + pNext1 = pNext0->pData; + if ( pNext1 == NULL ) + continue; + assert( pNext1->pData == pNext0 ); + if ( Saig_ObjIsPi(p0, pNext1) ) + continue; + pNext0->pData = NULL; + pNext1->pData = NULL; + } + Vec_PtrForEachEntry( vNodes1, pNext0, k ) + { + pNext1 = pNext0->pData; + if ( pNext1 == NULL ) + continue; + assert( pNext1->pData == pNext0 ); + if ( Saig_ObjIsPi(p1, pNext1) ) + continue; + pNext0->pData = NULL; + pNext1->pData = NULL; + } + if ( fVerbose ) + { + int nUnmached = Ssw_MatchingCountUnmached(p0); + printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", + d+1, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0), + nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) ); + } + } + Vec_PtrFree( vNodes0 ); + Vec_PtrFree( vNodes1 ); + Aig_ManFanoutStop(p0); + Aig_ManFanoutStop(p1); +} + +/**Function************************************************************* + + Synopsis [Used differences in p0 to complete p1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_MatchingComplete( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Vec_Ptr_t * vNewLis; + Aig_Obj_t * pObj0, * pObj0Li, * pObj1; + int i; + // create register outputs in p0 that are absent in p1 + vNewLis = Vec_PtrAlloc( 100 ); + Saig_ManForEachLiLo( p0, pObj0Li, pObj0, i ) + { + if ( pObj0->pData != NULL ) continue; - pFanin0To = Aig_ObjChild0Copy2( pObjFrom ); - pFanin1To = Aig_ObjChild1Copy2( pObjFrom ); - assert( pFanin0To != NULL && pFanin1To != NULL ); - pObjTo = Aig_And( pTo, pFanin0To, pFanin1To ); - if( fToGoesFirst ) - Ssw_CreatePair( vPairs, pObjTo, pObjFrom ); - else - Ssw_CreatePair( vPairs, pObjFrom, pObjTo ); + pObj1 = Aig_ObjCreatePi( p1 ); + pObj0->pData = pObj1; + pObj1->pData = pObj0; + Vec_PtrPush( vNewLis, pObj0Li ); } - // finally recreate additional register inputs - Vec_PtrForEachEntry( vLisFrom, pObjFrom, i ) + // add missing nodes in the topological order + Aig_ManForEachNode( p0, pObj0, i ) { - pFanin0To = Aig_ObjChild0Copy2( pObjFrom ); - Aig_ObjCreatePo( pTo, pFanin0To ); + if ( pObj0->pData != NULL ) + continue; + pObj1 = Aig_And( p1, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) ); + pObj0->pData = pObj1; + pObj1->pData = pObj0; } - // update the number of registers - Aig_ManSetRegNum( pTo, Aig_ManRegNum(pTo) + Vec_PtrSize(vLisFrom) ); + // create register outputs in p0 that are absent in p1 + Vec_PtrForEachEntry( vNewLis, pObj0Li, i ) + Aig_ObjCreatePo( p1, Aig_ObjChild0Copy(pObj0Li) ); + // increment the number of registers + Aig_ManSetRegNum( p1, Aig_ManRegNum(p1) + Vec_PtrSize(vNewLis) ); + Vec_PtrFree( vNewLis ); } + /**Function************************************************************* - Synopsis [Overlays and extends the pairs.] + Synopsis [Derives matching for all pairs.] - Description [] + Description [Modifies both AIGs.] SideEffects [] SeeAlso [] ***********************************************************************/ -Vec_Int_t * Saig_ManMiterWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, Aig_Man_t ** ppMiter, Vec_Int_t * vPairs ) +Vec_Int_t * Ssw_MatchingPairs( Aig_Man_t * p0, Aig_Man_t * p1 ) { - Aig_Man_t * pMiter; Vec_Int_t * vPairsNew; Aig_Obj_t * pObj0, * pObj1; int i; - vPairsNew = Vec_IntAlloc( 1000 ); - pMiter = Saig_ManCreateMiter( p0, p1, 0 ); - for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) + // check correctness + assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) ); + assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) ); + assert( Aig_ManRegNum(p0) == Aig_ManRegNum(p1) ); + assert( Aig_ManObjNum(p0) == Aig_ManObjNum(p1) ); + // create complete pairs + vPairsNew = Vec_IntAlloc( 2*Aig_ManObjNum(p0) ); + Aig_ManForEachObj( p0, pObj0, i ) { - pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) ); - pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) ); + if ( Aig_ObjIsPo(pObj0) ) + continue; + pObj1 = pObj0->pData; + Vec_IntPush( vPairsNew, pObj0->Id ); + Vec_IntPush( vPairsNew, pObj1->Id ); + } + return vPairsNew; +} + + + + + +/**Function************************************************************* + + Synopsis [Transfers the result of matching to miter.] + + Description [The array of pairs should be complete.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ssw_MatchingMiter( Aig_Man_t * pMiter, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairsAll ) +{ + Vec_Int_t * vPairsMiter; + Aig_Obj_t * pObj0, * pObj1; + int i; + // create matching of nodes in the miter + vPairsMiter = Vec_IntAlloc( 2*Aig_ManObjNum(p0) ); + for ( i = 0; i < Vec_IntSize(vPairsAll); i += 2 ) + { + pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairsAll, i) ); + pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairsAll, i+1) ); + assert( pObj0->pData != NULL ); + assert( pObj1->pData != NULL ); + if ( pObj0->pData == pObj1->pData ) + continue; + if ( Aig_ObjIsNone(pObj0->pData) || Aig_ObjIsNone(pObj1->pData) ) + continue; + // get the miter nodes pObj0 = pObj0->pData; pObj1 = pObj1->pData; assert( !Aig_IsComplement(pObj0) ); assert( !Aig_IsComplement(pObj1) ); - if ( pObj0 == pObj1 ) + assert( Aig_ObjType(pObj0) == Aig_ObjType(pObj1) ); + if ( Aig_ObjIsPo(pObj0) ) continue; + assert( Aig_ObjIsNode(pObj0) || Saig_ObjIsLo(pMiter, pObj0) ); + assert( Aig_ObjIsNode(pObj1) || Saig_ObjIsLo(pMiter, pObj1) ); assert( pObj0->Id < pObj1->Id ); - Vec_IntPush( vPairsNew, pObj0->Id ); - Vec_IntPush( vPairsNew, pObj1->Id ); + Vec_IntPush( vPairsMiter, pObj0->Id ); + Vec_IntPush( vPairsMiter, pObj1->Id ); } - *ppMiter = pMiter; - return vPairsNew; + return vPairsMiter; } + + + + /**Function************************************************************* Synopsis [Solves SEC using structural similarity.] @@ -220,72 +413,41 @@ Vec_Int_t * Saig_ManMiterWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, Aig_Man_t SeeAlso [] ***********************************************************************/ -Aig_Man_t * Ssw_SecWithIslandsInternal( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fVerbose, Ssw_Pars_t * pPars ) +Aig_Man_t * Ssw_SecWithSimilaritySweep( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ) { Ssw_Man_t * p; - Ssw_Pars_t Pars; - Vec_Int_t * vPairs, * vPairsMiter; + Vec_Int_t * vPairsAll, * vPairsMiter; Aig_Man_t * pMiter, * pAigNew; - Vec_Ptr_t * vLis0, * vLos0, * vLis1, * vLos1; - int nNodes, nRegs; - assert( Aig_ManRegNum(p0) > 0 ); - assert( Aig_ManRegNum(p1) > 0 ); - assert( Aig_ManRegNum(p0) >= nCommonFlops ); - assert( Aig_ManRegNum(p1) >= nCommonFlops ); - assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) ); - assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) ); - // derive pairs - vPairs = Ssw_DetectIslands( p0, p1, nCommonFlops, fVerbose ); - if ( fVerbose ) - { - printf( "Original managers:\n" ); - Aig_ManPrintStats( p0 ); - Aig_ManPrintStats( p1 ); - printf( "Detected %d PI pairs, %d LO pairs, and %d node pairs.\n", - Saig_ManPiNum(p0), nCommonFlops, Vec_IntSize(vPairs)/2 - Saig_ManPiNum(p0) - nCommonFlops - 1 ); - } - // complete the manager with islands - vLis0 = Vec_PtrAlloc( 100 ); - vLos0 = Vec_PtrAlloc( 100 ); - vLis1 = Vec_PtrAlloc( 100 ); - vLos1 = Vec_PtrAlloc( 100 ); - Ssw_CollectExtraLiLo( p0, nCommonFlops, vLis0, vLos0 ); - Ssw_CollectExtraLiLo( p1, nCommonFlops, vLis1, vLos1 ); - - nRegs = Saig_ManRegNum(p0); - nNodes = Aig_ManNodeNum(p0); - Ssw_OverlayIslands( p0, p1, vLis1, vLos1, vPairs, nCommonFlops, 1 ); - if ( fVerbose ) - printf( "Completed p0 with %d registers and %d nodes.\n", - Saig_ManRegNum(p0) - nRegs, Aig_ManNodeNum(p0) - nNodes ); - - nRegs = Saig_ManRegNum(p1); - nNodes = Aig_ManNodeNum(p1); - Ssw_OverlayIslands( p1, p0, vLis0, vLos0, vPairs, nCommonFlops, 0 ); - if ( fVerbose ) - printf( "Completed p1 with %d registers and %d nodes.\n", - Saig_ManRegNum(p1) - nRegs, Aig_ManNodeNum(p1) - nNodes ); - if ( fVerbose ) - { - printf( "Modified managers:\n" ); - Aig_ManPrintStats( p0 ); - Aig_ManPrintStats( p1 ); - } - - Vec_PtrFree( vLis0 ); - Vec_PtrFree( vLos0 ); - Vec_PtrFree( vLis1 ); - Vec_PtrFree( vLos1 ); - // create sequential miter - vPairsMiter = Saig_ManMiterWithIslands( p0, p1, &pMiter, vPairs ); - Vec_IntFree( vPairs ); - // if parameters are not given, create them - if ( pPars == NULL ) - Ssw_ManSetDefaultParams( pPars = &Pars ); + // derive full matching + Ssw_MatchingStart( p0, p1, vPairs ); + if ( pPars->nIsleDist ) + Ssw_MatchingExtend( p0, p1, pPars->nIsleDist, pPars->fVerbose ); + Ssw_MatchingComplete( p0, p1 ); + Ssw_MatchingComplete( p1, p0 ); + vPairsAll = Ssw_MatchingPairs( p0, p1 ); + // create miter and transfer matching + pMiter = Saig_ManCreateMiter( p0, p1, 0 ); + vPairsMiter = Ssw_MatchingMiter( pMiter, p0, p1, vPairsAll ); + Vec_IntFree( vPairsAll ); // start the induction manager p = Ssw_ManCreate( pMiter, pPars ); // create equivalence classes using these IDs - p->ppClasses = Ssw_ClassesFromIslands( pMiter, vPairsMiter ); + if ( p->pPars->fPartSigCorr ) + p->ppClasses = Ssw_ClassesPreparePairsSimple( pMiter, vPairsMiter ); + else + p->ppClasses = Ssw_ClassesPrepare( pMiter, pPars->nFramesK, pPars->fLatchCorr, pPars->nMaxLevs, pPars->fVerbose ); + if ( p->pPars->fDumpSRInit ) + { + if ( p->pPars->fPartSigCorr ) + { + Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p ); + Aig_ManDumpBlif( pSRed, "srm_part.blif", NULL, NULL ); + Aig_ManStop( pSRed ); + printf( "Speculatively reduced miter is saved in file \"%s\".\n", "srm_part.blif" ); + } + else + printf( "Dumping speculative miter is possible only for partial signal correspondence (switch \"-c\").\n" ); + } p->pSml = Ssw_SmlStart( pMiter, 0, 1 + p->pPars->nFramesAddSim, 1 ); Ssw_ClassesSetData( p->ppClasses, p->pSml, Ssw_SmlObjHashWord, Ssw_SmlObjIsConstWord, Ssw_SmlObjsAreEqualWord ); // perform refinement of classes @@ -299,28 +461,28 @@ Aig_Man_t * Ssw_SecWithIslandsInternal( Aig_Man_t * p0, Aig_Man_t * p1, int nCom /**Function************************************************************* - Synopsis [Solves SEC using structural similarity.] + Synopsis [Solves SEC with structural similarity.] - Description [] + Description [The first two arguments are pointers to the AIG managers. + The third argument is the array of pairs of IDs of structurally equivalent + nodes from the first and second managers, respectively.] - SideEffects [] + SideEffects [The managers will be updated by adding "islands of difference".] SeeAlso [] ***********************************************************************/ -int Ssw_SecWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fVerbose, Ssw_Pars_t * pPars ) +int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ) { + Ssw_Pars_t Pars; Aig_Man_t * pAigRes; - Aig_Man_t * p0New, * p1New; int RetValue, clk = clock(); - // try the new AIGs -// printf( "Performing verification using structural similarity.\n" ); - p0New = Aig_ManDupSimple( p0 ); - p1New = Aig_ManDupSimple( p1 ); - pAigRes = Ssw_SecWithIslandsInternal( p0New, p1New, nCommonFlops, fVerbose, pPars ); - Aig_ManStop( p0New ); - Aig_ManStop( p1New ); - // report the results + // derive parameters if not given + if ( pPars == NULL ) + Ssw_ManSetDefaultParams( pPars = &Pars ); + // reduce the AIG with pairs + pAigRes = Ssw_SecWithSimilaritySweep( p0, p1, vPairs, pPars ); + // report the result of verification RetValue = Ssw_MiterStatus( pAigRes, 1 ); if ( RetValue == 1 ) printf( "Verification successful. " ); @@ -328,17 +490,43 @@ int Ssw_SecWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fV printf( "Verification failed with a counter-example. " ); else printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", - Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0New)+Aig_ManRegNum(p1New) ); + Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0)+Aig_ManRegNum(p1) ); PRT( "Time", clock() - clk ); - // cleanup Aig_ManStop( pAigRes ); return RetValue; } +/**Function************************************************************* + + Synopsis [Dummy procedure to detect structural similarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_StrSimPerformMatching_hack( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Vec_Int_t * vPairs; + Aig_Obj_t * pObj; + int i; + // create array of pairs + vPairs = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( p0, pObj, i ) + { + if ( !Aig_ObjIsConst1(pObj) && !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + Vec_IntPush( vPairs, i ); + Vec_IntPush( vPairs, i ); + } + return vPairs; +} /**Function************************************************************* - Synopsis [Solves SEC using structural similarity for the miter.] + Synopsis [Solves SEC with structural similarity.] Description [] @@ -347,34 +535,57 @@ int Ssw_SecWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fV SeeAlso [] ***********************************************************************/ -int Ssw_SecWithIslandsMiter( Aig_Man_t * pMiter, int nCommonFlops, int fVerbose ) +int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars ) { + Vec_Int_t * vPairs; Aig_Man_t * pPart0, * pPart1; int RetValue; - if ( fVerbose ) - Aig_ManPrintStats( pMiter ); - // demiter the miter - if ( !Saig_ManDemiterSimpleDiff( pMiter, &pPart0, &pPart1 ) ) + if ( pPars->fVerbose ) + printf( "Performing sequential verification using structural similarity.\n" ); + // consider the case when a miter is given + if ( p1 == NULL ) { - printf( "Demitering has failed.\n" ); - return -1; + if ( pPars->fVerbose ) + { + Aig_ManPrintStats( p0 ); + } + // demiter the miter + if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) + { + printf( "Demitering has failed.\n" ); + return -1; + } } - if ( fVerbose ) + else + { + pPart0 = Aig_ManDupSimple( p0 ); + pPart1 = Aig_ManDupSimple( p1 ); + } + if ( pPars->fVerbose ) { // Aig_ManPrintStats( pPart0 ); // Aig_ManPrintStats( pPart1 ); + if ( p1 == NULL ) + { // Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL ); // Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); // printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" ); + } } - RetValue = Ssw_SecWithIslands( pPart0, pPart1, nCommonFlops, fVerbose, NULL ); + assert( Aig_ManRegNum(pPart0) > 0 ); + assert( Aig_ManRegNum(pPart1) > 0 ); + assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) ); + assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) ); + // derive pairs +// vPairs = Saig_StrSimPerformMatching_hack( pPart0, pPart1 ); + vPairs = Saig_StrSimPerformMatching( pPart0, pPart1, 0, pPars->fVerbose, NULL ); + RetValue = Ssw_SecWithSimilarityPairs( pPart0, pPart1, vPairs, pPars ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); + Vec_IntFree( vPairs ); return RetValue; } - - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/ssw/sswMan.c b/src/aig/ssw/sswMan.c index 913f7518..7e6e4473 100644 --- a/src/aig/ssw/sswMan.c +++ b/src/aig/ssw/sswMan.c @@ -61,6 +61,8 @@ Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) // other p->vNewLos = Vec_PtrAlloc( 100 ); p->vNewPos = Vec_IntAlloc( 100 ); + p->vResimConsts = Vec_PtrAlloc( 100 ); + p->vResimClasses = Vec_PtrAlloc( 100 ); // p->pPars->fVerbose = 1; return p; @@ -171,6 +173,7 @@ void Ssw_ManCleanup( Ssw_Man_t * p ) ***********************************************************************/ void Ssw_ManStop( Ssw_Man_t * p ) { + FREE( p->pVisited ); if ( p->pPars->fVerbose ) Ssw_ManPrintStats( p ); if ( p->ppClasses ) @@ -179,6 +182,8 @@ void Ssw_ManStop( Ssw_Man_t * p ) Ssw_SmlStop( p->pSml ); if ( p->vDiffPairs ) Vec_IntFree( p->vDiffPairs ); + Vec_PtrFree( p->vResimConsts ); + Vec_PtrFree( p->vResimClasses ); Vec_PtrFree( p->vNewLos ); Vec_IntFree( p->vNewPos ); Vec_PtrFree( p->vCommon ); diff --git a/src/aig/ssw/sswPart.c b/src/aig/ssw/sswPart.c index 983a2022..9d2ec34e 100644 --- a/src/aig/ssw/sswPart.c +++ b/src/aig/ssw/sswPart.c @@ -30,7 +30,7 @@ /**Function************************************************************* - Synopsis [Performs partitioned sequential SAT sweepingG.] + Synopsis [Performs partitioned sequential SAT sweeping.] Description [] diff --git a/src/aig/ssw/sswSim.c b/src/aig/ssw/sswSim.c index 836b75e3..a860199e 100644 --- a/src/aig/ssw/sswSim.c +++ b/src/aig/ssw/sswSim.c @@ -200,19 +200,21 @@ int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * p { unsigned * pSimLi, * pSimLo, * pSimCand; int k; + assert( pObjLo->fPhase == 0 ); + // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id ); pSimLi = Ssw_ObjSim( p, pObjLi->Id ); pSimLo = Ssw_ObjSim( p, pObjLo->Id ); - if ( !Aig_IsComplement(pCand) ) + if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) ) { for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) + if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) return 0; } else { for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) + if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) return 0; } return 1; @@ -233,22 +235,48 @@ int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * p { unsigned * pSimLi, * pSimLo, * pSimCand; int k, Counter = 0; + assert( pObjLo->fPhase == 0 ); + // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id ); pSimLi = Ssw_ObjSim( p, pObjLi->Id ); pSimLo = Ssw_ObjSim( p, pObjLo->Id ); - if ( !Aig_IsComplement(pCand) ) + if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) ) { for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); + Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); } else { for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); + Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); } return Counter; } +/**Function************************************************************* + + Synopsis [Counts the number of 1s in the implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ) +{ + unsigned * pSimLi, * pSimLo; + int k, Counter = 0; + assert( pObjLo->fPhase == 0 ); + // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! + pSimLi = Ssw_ObjSim( p, pObjLi->Id ); + pSimLo = Ssw_ObjSim( p, pObjLo->Id ); + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + Counter += Aig_WordCountOnes( ~(pSimLi[k] ^ pSimLo[k]) ); + return Counter; +} + /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] @@ -273,7 +301,7 @@ int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj ) /**Function************************************************************* - Synopsis [Counts the number of one's in the patten of the output.] + Synopsis [Counts the number of one's in the patten the object.] Description [] @@ -282,13 +310,55 @@ int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -int Ssw_SmlNodeCountOnes( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ) { unsigned * pSims; int i, Counter = 0; - pSims = Ssw_ObjSim(p, pObj->Id); + pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id); + if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ) + { + for ( i = 0; i < p->nWordsTotal; i++ ) + Counter += Aig_WordCountOnes( ~pSims[i] ); + } + else + { + for ( i = 0; i < p->nWordsTotal; i++ ) + Counter += Aig_WordCountOnes( pSims[i] ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of one's in the patten the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ) +{ + Aig_Obj_t * pObj; + unsigned * pSims, uWord; + int i, k, Counter = 0; + if ( Vec_PtrSize(vObjs) == 0 ) + return 0; for ( i = 0; i < p->nWordsTotal; i++ ) - Counter += Aig_WordCountOnes( pSims[i] ); + { + uWord = 0; + Vec_PtrForEachEntry( vObjs, pObj, k ) + { + pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id); + if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ) + uWord |= ~pSims[i]; + else + uWord |= pSims[i]; + } + Counter += Aig_WordCountOnes( uWord ); + } return Counter; } @@ -887,6 +957,79 @@ p->timeSim += clock() - clk; p->nSimRounds++; } +/**Function************************************************************* + + Synopsis [Converts simulation information to be not normallized.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlUnnormalize( Ssw_Sml_t * p ) +{ + Aig_Obj_t * pObj; + unsigned * pSims; + int i, k; + // convert constant 1 + pSims = Ssw_ObjSim( p, 0 ); + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = ~pSims[i]; + // convert internal nodes + Aig_ManForEachNode( p->pAig, pObj, k ) + { + if ( pObj->fPhase == 0 ) + continue; + pSims = Ssw_ObjSim( p, pObj->Id ); + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = ~pSims[i]; + } + // PIs/POs are always stored in their natural state +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter ) +{ +// if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) ) +// return; +// Aig_ObjSetTravIdCurrent(p->pAig, pObj); + if ( pVisited[p->nFrames*pObj->Id+f] == nVisCounter ) + return; + pVisited[p->nFrames*pObj->Id+f] = nVisCounter; + if ( Saig_ObjIsPi( p->pAig, pObj ) || Aig_ObjIsConst1(pObj) ) + return; + if ( Saig_ObjIsLo( p->pAig, pObj ) ) + { + if ( f == 0 ) + return; + Ssw_SmlSimulateOneDyn_rec( p, Saig_ObjLoToLi(p->pAig, pObj), f-1, pVisited, nVisCounter ); + Ssw_SmlNodeTransferNext( p, Saig_ObjLoToLi(p->pAig, pObj), pObj, f-1 ); + return; + } + if ( Saig_ObjIsLi( p->pAig, pObj ) ) + { + Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter ); + Ssw_SmlNodeCopyFanin( p, pObj, f ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter ); + Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin1(pObj), f, pVisited, nVisCounter ); + Ssw_SmlNodeSimulate( p, pObj, f ); +} + /**Function************************************************************* Synopsis [Simulates AIG manager.] @@ -974,22 +1117,6 @@ void Ssw_SmlStop( Ssw_Sml_t * p ) free( p ); } -/**Function************************************************************* - - Synopsis [Deallocates simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ssw_SmlNumFrames( Ssw_Sml_t * p ) -{ - return p->nFrames; -} - /**Function************************************************************* @@ -1051,6 +1178,56 @@ void Ssw_SmlResimulateSeq( Ssw_Sml_t * p ) } +/**Function************************************************************* + + Synopsis [Returns the number of frames simulated in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNumFrames( Ssw_Sml_t * p ) +{ + return p->nFrames; +} + +/**Function************************************************************* + + Synopsis [Returns the total number of simulation words.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p ) +{ + return p->nWordsTotal; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the simulation info of the node.] + + Description [The simulation info is normalized unless procedure + Ssw_SmlUnnormalize() is called in advance.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + return Ssw_ObjSim( p, pObj->Id ); +} + /**Function************************************************************* diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index e4b0ad69..987adaad 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -154,7 +154,12 @@ struct Abc_Obj_t_ // 12 words // miscellaneous void * pData; // the network specific data (SOP, BDD, gate, equiv class, etc) Abc_Obj_t * pNext; // the next pointer in the hash table - Abc_Obj_t * pCopy; // the copy of this object + union { // temporary store for user's data + Abc_Obj_t * pCopy; // the copy of this object + void * pTemp; + int iTemp; + float dTemp; + }; Hop_Obj_t * pEquiv; // pointer to the HAIG node }; @@ -227,14 +232,14 @@ struct Abc_Lib_t_ //#pragma warning( disable : 4273 ) #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif // maximum/minimum operators @@ -748,7 +753,8 @@ extern ABC_DLL bool Abc_NodeIsBuf( Abc_Obj_t * pNode ); extern ABC_DLL bool Abc_NodeIsInv( Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NodeComplement( Abc_Obj_t * pNode ); /*=== abcPrint.c ==========================================================*/ -extern ABC_DLL void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes ); +extern ABC_DLL float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower ); extern ABC_DLL void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcHie.c b/src/base/abc/abcHie.c index 56333a36..19bdc47e 100644 --- a/src/base/abc/abcHie.c +++ b/src/base/abc/abcHie.c @@ -472,9 +472,6 @@ Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ) Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew ); pNtkNew->pDesign = pDesign; -//Abc_NtkPrintStats( stdout, pNtkH, 0 ); -//Abc_NtkPrintStats( stdout, pNtkNew, 0 ); - // check integrity if ( !Abc_NtkCheck( pNtkNew ) ) { diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 2ad8dc75..7aad2eb2 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -38,6 +38,8 @@ #include "dch.h" #include "ssw.h" #include "cgt.h" +#include "amap.h" +#include "cec.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -82,6 +84,8 @@ static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandMfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSpeedup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPowerdown ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMerge ( 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 ); @@ -136,7 +140,7 @@ static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDCompress2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDC2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -147,6 +151,9 @@ static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSimSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMini ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -170,6 +177,7 @@ static int Abc_CommandRecPs ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -202,8 +210,11 @@ static int Abc_CommandSim ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandDarPhase ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSynch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandClockGate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExtWin ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandInsWin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCec2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -314,8 +325,9 @@ void Abc_FrameClearDesign() ***********************************************************************/ void Abc_Init( Abc_Frame_t * pAbc ) { -// Abc_NtkBddImplicationTest(); -// Ply_LutPairTest(); +// Amap_LibParseTest( "at\\syn\\libraries\\LIBS\\BRDCM\\tsmc13_5.ff.genlib" ); +// Amap_LibParseTest( "at\\syn\\libraries\\LIBS\\GS60\\GS60_W_30_1.7_CORE.genlib" ); +// Amap_LibParseTest( "at\\syn\\libraries\\LIBS\\TYPICAL\\typical.genlib" ); Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 ); @@ -356,6 +368,8 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "mfs", Abc_CommandMfs, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "trace", Abc_CommandTrace, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "speedup", Abc_CommandSpeedup, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "powerdown", Abc_CommandPowerdown, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "merge", Abc_CommandMerge, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); @@ -410,7 +424,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "dcompress2", Abc_CommandDCompress2, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dc2", Abc_CommandDC2, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "dch", Abc_CommandDch, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 ); @@ -443,6 +457,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Choicing", "rec_use", Abc_CommandRecUse, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "amap", Abc_CommandAmap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "sc", Abc_CommandSuperChoice, 1 ); @@ -473,12 +488,18 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Sequential", "phase", Abc_CommandDarPhase, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "synch", Abc_CommandSynch, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "clockgate", Abc_CommandClockGate, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "extwin", Abc_CommandExtWin, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "inswin", Abc_CommandInsWin, 1 ); Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "cec2", Abc_CommandCec2, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "absec", Abc_CommandAbSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "simsec", Abc_CommandSimSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "match", Abc_CommandMatch, 0 ); Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 ); Cmd_CommandAdd( pAbc, "Verification", "psat", Abc_CommandPSat, 0 ); @@ -553,6 +574,12 @@ void Abc_Init( Abc_Frame_t * pAbc ) // extern void Aig_ManRandomTest1(); // Aig_ManRandomTest1(); } +// malloc(1001); + { + extern void Extra_MemTest(); +// Extra_MemTest(); + } + } /**Function************************************************************* @@ -589,6 +616,10 @@ void Abc_End() extern void Dar_LibStop(); Dar_LibStop(); } + { + extern void Aig_RManQuit(); + Aig_RManQuit(); + } Abc_NtkFraigStoreClean(); // Rwt_Man4ExplorePrint(); @@ -616,6 +647,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) int fUseLutLib; int fPrintTime; int fPrintMuxes; + int fPower; int c; pNtk = Abc_FrameReadNtk(pAbc); @@ -629,8 +661,9 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) fUseLutLib = 0; fPrintTime = 0; fPrintMuxes = 0; + fPower = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmph" ) ) != EOF ) { switch ( c ) { @@ -652,6 +685,9 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fPrintMuxes ^= 1; break; + case 'p': + fPower ^= 1; + break; case 'h': goto usage; default: @@ -669,7 +705,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( Abc_FrameReadErr(pAbc), "Cannot print LUT delay for a non-logic network.\n" ); return 1; } - Abc_NtkPrintStats( pOut, pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes ); + Abc_NtkPrintStats( pOut, pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower ); if ( fPrintTime ) { pAbc->TimeTotal += pAbc->TimeCommand; @@ -680,7 +716,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: print_stats [-fbdltmh]\n" ); + fprintf( pErr, "usage: print_stats [-fbdltmph]\n" ); fprintf( pErr, "\t prints the network statistics\n" ); fprintf( pErr, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); fprintf( pErr, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); @@ -688,6 +724,7 @@ usage: fprintf( pErr, "\t-l : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fSaveBest? "yes": "no" ); fprintf( pErr, "\t-t : toggles printing runtime statistics [default = %s]\n", fPrintTime? "yes": "no" ); fprintf( pErr, "\t-m : toggles printing MUX statistics [default = %s]\n", fPrintMuxes? "yes": "no" ); + fprintf( pErr, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -773,7 +810,7 @@ int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv ) } else printf( "EXDC network statistics: \n" ); - Abc_NtkPrintStats( pOut, pNtk->pExdc, 0, 0, 0, 0, 0 ); + Abc_NtkPrintStats( pOut, pNtk->pExdc, 0, 0, 0, 0, 0, 0 ); return 0; usage: @@ -3683,7 +3720,7 @@ int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Abc_NtkMfsParsDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraestvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraestpvwh" ) ) != EOF ) { switch ( c ) { @@ -3768,6 +3805,9 @@ int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv ) case 't': pPars->fOneHotness ^= 1; break; + case 'p': + pPars->fPower ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -3801,7 +3841,7 @@ int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: mfs [-WFDMLC ] [-raestvh]\n" ); + fprintf( pErr, "usage: mfs [-WFDMLC ] [-raestpvh]\n" ); fprintf( pErr, "\t performs don't-care-based optimization of logic networks\n" ); fprintf( pErr, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nWinTfoLevs ); fprintf( pErr, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutsMax ); @@ -3814,6 +3854,7 @@ usage: fprintf( pErr, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); fprintf( pErr, "\t-s : toggle evaluation of edge swapping [default = %s]\n", pPars->fSwapEdge? "yes": "no" ); fprintf( pErr, "\t-t : toggle using artificial one-hotness conditions [default = %s]\n", pPars->fOneHotness? "yes": "no" ); + fprintf( pErr, "\t-p : toggle power-aware optimization [default = %s]\n", pPars->fPower? "yes": "no" ); fprintf( pErr, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( pErr, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); @@ -4001,6 +4042,252 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPowerdown( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fUseLutLib; + int Percentage; + int Degree; + int fVerbose; + int fVeryVerbose; + extern Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseLutLib = 0; + Percentage =10; + Degree = 2; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + Percentage = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Percentage < 1 || Percentage > 100 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + Degree = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Degree < 1 || Degree > 5 ) + goto usage; + break; + case 'l': + fUseLutLib ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + pNtkRes = Abc_NtkPowerdown( pNtk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: powerdown [-P num] [-N num] [-vwh]\n" ); + fprintf( pErr, "\t transforms LUT-mapped network into an AIG with choices;\n" ); + fprintf( pErr, "\t the choices are added to power down the next round of mapping\n" ); + fprintf( pErr, "\t-P : switching propability delta defining power critical edges [default = %d%%]\n", Percentage ); + fprintf( pErr, "\t (e.g. 5% means hot wires switch with probability: 0.45 <= p <= 0.50 (max)\n" ); + fprintf( pErr, "\t-N : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree ); +// fprintf( pErr, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" ); + fprintf( pErr, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle printing detailed stats for each node [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMerge( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + Nwk_LMPars_t Pars, * pPars = &Pars; + Vec_Int_t * vResult; + int c; + extern Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars ); + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + memset( pPars, 0, sizeof(Nwk_LMPars_t) ); + pPars->nMaxLutSize = 5; // the max LUT size for merging (N=5) + pPars->nMaxSuppSize = 5; // the max total support size after merging (S=5) + pPars->nMaxDistance = 3; // the max number of nodes separating LUTs + pPars->nMaxLevelDiff = 2; // the max difference in levels + pPars->nMaxFanout = 100; // the max number of fanouts to traverse + pPars->fUseDiffSupp = 0; // enables the use of nodes with different support + pPars->fUseTfiTfo = 0; // enables the use of TFO/TFO nodes as candidates + pPars->fVeryVerbose = 0; // enables additional verbose output + pPars->fVerbose = 1; // enables verbose output + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NSDLFscvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( stdout, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxLutSize < 2 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + fprintf( stdout, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxSuppSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxSuppSize < 2 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( stdout, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxDistance = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxDistance < 2 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( stdout, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxLevelDiff = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxLevelDiff < 2 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( stdout, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxFanout = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxFanout < 2 ) + goto usage; + break; + case 's': + pPars->fUseDiffSupp ^= 1; + break; + case 'c': + pPars->fUseTfiTfo ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL || !Abc_NtkIsLogic(pNtk) ) + { + printf( "Abc_CommandSpeedup(): There is no mapped network to merge LUTs.\n" ); + return 1; + } + + vResult = Abc_NtkLutMerge( pNtk, pPars ); + Vec_IntFree( vResult ); + return 0; + +usage: + fprintf( stdout, "usage: merge [-NSDLF num] [-scwvh]\n" ); + fprintf( stdout, "\t creates pairs of topologically-related LUTs\n" ); + fprintf( stdout, "\t-N : the max LUT size for merging (1 < num) [default = %d]\n", pPars->nMaxLutSize ); + fprintf( stdout, "\t-S : the max total support size after merging (1 < num) [default = %d]\n", pPars->nMaxSuppSize ); + fprintf( stdout, "\t-D : the max distance in terms of LUTs (0 < num) [default = %d]\n", pPars->nMaxDistance ); + fprintf( stdout, "\t-L : the max difference in levels (0 <= num) [default = %d]\n", pPars->nMaxLevelDiff ); + fprintf( stdout, "\t-F : the max number of fanouts to stop traversal (0 < num) [default = %d]\n", pPars->nMaxFanout ); + fprintf( stdout, "\t-s : toggle the use of nodes without support overlap [default = %s]\n", pPars->fUseDiffSupp? "yes" : "no" ); + fprintf( stdout, "\t-c : toggle the use of TFI/TFO nodes as candidates [default = %s]\n", pPars->fUseTfiTfo? "yes" : "no" ); + fprintf( stdout, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( stdout, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( stdout, "\t-h : print the command usage\n"); + return 1; +} /**Function************************************************************* @@ -4905,7 +5192,7 @@ usage: fprintf( pErr, "\t-P num : output partition size [default = %s]\n", Buffer ); fprintf( pErr, "\t-c : toggles deriving combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); fprintf( pErr, "\t-i : toggles deriving implication miter (file1 => file2) [default = %s]\n", fImplic? "yes": "no" ); - fprintf( pErr, "\t-m : toggles creating multi-output miters [default = %s]\n", fMulti? "yes": "no" ); + fprintf( pErr, "\t-m : toggles creating multi-output miter [default = %s]\n", fMulti? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); @@ -6943,18 +7230,20 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 1000; // the max number of cuts kept at a node - pParams->fTruth = 0; // compute truth tables + pParams->fTruth = 1; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fDrop = 0; // drop cuts on the fly - pParams->fDag = 0; // compute DAG cuts + pParams->fDag = 1; // compute DAG cuts pParams->fTree = 0; // compute tree cuts pParams->fGlobal = 0; // compute global cuts pParams->fLocal = 0; // compute local cuts pParams->fFancy = 0; // compute something fancy + pParams->fRecordAig= 1; // compute something fancy pParams->fMap = 0; // compute mapping delay + pParams->fAdjust = 1; // removes useless fanouts pParams->fVerbose = 0; // the verbosiness flag Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzmvoh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzamjvoh" ) ) != EOF ) { switch ( c ) { @@ -7004,9 +7293,15 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'z': pParams->fFancy ^= 1; break; + case 'a': + pParams->fRecordAig ^= 1; + break; case 'm': pParams->fMap ^= 1; break; + case 'j': + pParams->fAdjust ^= 1; + break; case 'v': pParams->fVerbose ^= 1; break; @@ -7056,7 +7351,7 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzmvh]\n" ); + fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzamjvh]\n" ); fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" ); fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); @@ -7068,7 +7363,9 @@ usage: fprintf( pErr, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" ); fprintf( pErr, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" ); fprintf( pErr, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" ); + fprintf( pErr, "\t-a : toggle recording cut functions [default = %s]\n", pParams->fRecordAig?"yes": "no" ); fprintf( pErr, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" ); + fprintf( pErr, "\t-j : toggle removing fanouts due to XOR/MUX [default = %s]\n", pParams->fAdjust? "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; @@ -7742,7 +8039,6 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) // extern void Aig_ProcedureTest(); extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk ); - extern int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); @@ -8804,13 +9100,13 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandDC2( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkRes; - int fBalance, fVerbose, fUpdateLevel, fFanout, c; + int fBalance, fVerbose, fUpdateLevel, fFanout, fPower, c; - extern Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); @@ -8821,8 +9117,9 @@ int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv ) fVerbose = 0; fUpdateLevel = 0; fFanout = 1; + fPower = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "blfvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "blfpvh" ) ) != EOF ) { switch ( c ) { @@ -8835,6 +9132,9 @@ int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'f': fFanout ^= 1; break; + case 'p': + fPower ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -8854,7 +9154,7 @@ int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "This command works only for strashed networks.\n" ); return 1; } - pNtkRes = Abc_NtkDCompress2( pNtk, fBalance, fUpdateLevel, fFanout, fVerbose ); + pNtkRes = Abc_NtkDC2( pNtk, fBalance, fUpdateLevel, fFanout, fPower, fVerbose ); if ( pNtkRes == NULL ) { fprintf( pErr, "Command has failed.\n" ); @@ -8865,11 +9165,12 @@ int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: dcompress2 [-blfvh]\n" ); + fprintf( pErr, "usage: dc2 [-blfpvh]\n" ); fprintf( pErr, "\t performs combinational AIG optimization\n" ); fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); fprintf( pErr, "\t-f : toggle representing fanouts [default = %s]\n", fFanout? "yes": "no" ); + fprintf( pErr, "\t-p : toggle power-aware rewriting [default = %s]\n", fPower? "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; @@ -9053,7 +9354,7 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fSynthesis ^= 1; break; case 'p': - pPars->fPolarFlip ^= 1; + pPars->fPower ^= 1; break; case 't': pPars->fSimulateTfo ^= 1; @@ -9094,7 +9395,7 @@ usage: fprintf( pErr, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); fprintf( pErr, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax ); fprintf( pErr, "\t-s : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" ); - fprintf( pErr, "\t-p : toggle alighning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" ); + fprintf( pErr, "\t-p : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" ); fprintf( pErr, "\t-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" ); fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); @@ -11166,6 +11467,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk, * pNtkRes; char Buffer[100]; double DelayTarget; + int fAreaOnly; int fRecovery; int fSweep; int fSwitching; @@ -11180,12 +11482,13 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults DelayTarget =-1; + fAreaOnly = 0; fRecovery = 1; fSweep = 1; fSwitching = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Darspvh" ) ) != EOF ) { switch ( c ) { @@ -11201,6 +11504,9 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; break; case 'a': + fAreaOnly ^= 1; + break; + case 'r': fRecovery ^= 1; break; case 's': @@ -11225,6 +11531,9 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } + if ( fAreaOnly ) + DelayTarget = 100000.0; + if ( !Abc_NtkIsStrash(pNtk) ) { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); @@ -11274,10 +11583,11 @@ usage: sprintf( Buffer, "not used" ); else sprintf( Buffer, "%.3f", DelayTarget ); - fprintf( pErr, "usage: map [-D float] [-aspvh]\n" ); + fprintf( pErr, "usage: map [-D float] [-arspvh]\n" ); fprintf( pErr, "\t performs standard cell mapping of the current network\n" ); fprintf( pErr, "\t-D float : sets the global required times [default = %s]\n", Buffer ); - fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); + fprintf( pErr, "\t-a : toggles area-only mapping [default = %s]\n", fAreaOnly? "yes": "no" ); + fprintf( pErr, "\t-r : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); fprintf( pErr, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" ); fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); @@ -11285,7 +11595,6 @@ usage: return 1; } - /**Function************************************************************* Synopsis [] @@ -11297,10 +11606,164 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAmap( Abc_Frame_t * pAbc, int argc, char ** argv ) { + Amap_Par_t Pars, * pPars = &Pars; FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; + Abc_Ntk_t * pNtk, * pNtkRes; + int fSweep; + int c; + extern Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars ); + extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fSweep = 0; + Amap_ManSetDefaultParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "FAEmxisvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->nIterFlow = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIterFlow < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-A\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->nIterArea = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIterArea < 0 ) + goto usage; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-E\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->fEpsilon = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->fEpsilon < 0.0 || pPars->fEpsilon > 1.0 ) + goto usage; + break; + case 'm': + pPars->fUseMuxes ^= 1; + break; + case 'x': + pPars->fUseXors ^= 1; + break; + case 'i': + pPars->fFreeInvs ^= 1; + break; + case 's': + fSweep ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkDarAmap( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "Mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkDarAmap( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Mapping has failed.\n" ); + return 1; + } + } + + if ( fSweep ) + Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 ); + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: amap [-FA ] [-E ] [-mxisvh]\n" ); + fprintf( pErr, "\t performs standard cell mapping of the current network\n" ); + fprintf( pErr, "\t-F num : the number of iterations of area flow [default = %d]\n", pPars->nIterFlow ); + fprintf( pErr, "\t-A num : the number of iterations of exact area [default = %d]\n", pPars->nIterArea ); + fprintf( pErr, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->fEpsilon ); + fprintf( pErr, "\t-m : toggles using MUX matching [default = %s]\n", pPars->fUseMuxes? "yes": "no" ); + fprintf( pErr, "\t-x : toggles using XOR matching [default = %s]\n", pPars->fUseXors? "yes": "no" ); + fprintf( pErr, "\t-i : toggles assuming inverters are free [default = %s]\n", pPars->fFreeInvs? "yes": "no" ); + fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; int c; pNtk = Abc_FrameReadNtk(pAbc); @@ -11916,6 +12379,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fExpRed = 1; pPars->fLatchPaths = 0; pPars->fEdge = 1; + pPars->fPower = 0; pPars->fCutMin = 0; pPars->fSeqMap = 0; pPars->fBidec = 0; @@ -11930,7 +12394,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pFuncCost = NULL; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEpaflemrstbvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEqaflepmrstbvh" ) ) != EOF ) { switch ( c ) { @@ -12001,7 +12465,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 ) goto usage; break; - case 'p': + case 'q': pPars->fPreprocess ^= 1; break; case 'a': @@ -12019,6 +12483,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'e': pPars->fEdge ^= 1; break; + case 'p': + pPars->fPower ^= 1; + break; case 'm': pPars->fCutMin ^= 1; break; @@ -12159,7 +12626,7 @@ usage: sprintf( LutSize, "library" ); else sprintf( LutSize, "%d", pPars->nLutSize ); - fprintf( pErr, "usage: if [-KCFA num] [-DE float] [-parlemsbvh]\n" ); + fprintf( pErr, "usage: if [-KCFA num] [-DE float] [-qarlepmsbvh]\n" ); fprintf( pErr, "\t performs FPGA technology mapping of the network\n" ); fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); fprintf( pErr, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -12167,12 +12634,13 @@ usage: fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); fprintf( pErr, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); - fprintf( pErr, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); + fprintf( pErr, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); // fprintf( pErr, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" ); fprintf( pErr, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); fprintf( pErr, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" ); + fprintf( pErr, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); fprintf( pErr, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" ); fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" ); // fprintf( pErr, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" ); @@ -12957,10 +13425,12 @@ int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) int fFastButConservative; int maxDelay; - extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, - int fComputeInit, int fGuaranteeInit, int fBlockConst, - int fForward, int fBackward, int nMaxIters, - int maxDelay, int fFastButConservative); + printf( "This command is temporarily disabled.\n" ); + return 0; +// extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, +// int fComputeInit, int fGuaranteeInit, int fBlockConst, +// int fForward, int fBackward, int nMaxIters, +// int maxDelay, int fFastButConservative); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); @@ -13042,7 +13512,7 @@ int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" ); return 1; } - + if ( fGuaranteeInit && !fComputeInit ) { fprintf( pErr, "Initial state guarantee (-g) requires initial state computation (-i).\n" ); @@ -13062,10 +13532,10 @@ int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) } // perform the retiming - pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit, - fGuaranteeInit, fBlockConst, - fForward, fBackward, - nMaxIters, maxDelay, fFastButConservative ); +// pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit, +// fGuaranteeInit, fBlockConst, +// fForward, fBackward, +// nMaxIters, maxDelay, fFastButConservative ); if (pNtkRes != pNtk) Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); @@ -13567,7 +14037,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Ssw_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSIVMplfudvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSIVMplfudsvwh" ) ) != EOF ) { switch ( c ) { @@ -13696,6 +14166,9 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': pPars->fDynamic ^= 1; break; + case 's': + pPars->fLocalSim ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -13739,7 +14212,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: scorr [-PQFCLNSIVM ] [-pludvwh]\n" ); + fprintf( pErr, "usage: scorr [-PQFCLNSIVM ] [-pludsvwh]\n" ); fprintf( pErr, "\t performs sequential sweep using K-step induction\n" ); fprintf( pErr, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); fprintf( pErr, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); @@ -13756,6 +14229,7 @@ usage: // fprintf( pErr, "\t-f : toggle filtering using iterative BMC [default = %s]\n", pPars->fSemiFormal? "yes": "no" ); fprintf( pErr, "\t-u : toggle using uniqueness constraints [default = %s]\n", pPars->fUniqueness? "yes": "no" ); fprintf( pErr, "\t-d : toggle dynamic addition of constraints [default = %s]\n", pPars->fDynamic? "yes": "no" ); + fprintf( pErr, "\t-s : toggle local simulation in the cone of influence [default = %s]\n", pPars->fLocalSim? "yes": "no" ); fprintf( pErr, "\t-w : toggle printout of flop equivalences [default = %s]\n", pPars->fFlopVerbose? "yes": "no" ); fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); @@ -14336,21 +14810,29 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) FILE * pOut, * pErr; Abc_Ntk_t * pNtk; int c; + int fNew; + int fComb; int nFrames; int nWords; + int TimeOut; + int fMiter; int fVerbose; - extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose ); + extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fComb, int fMiter, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults + fNew = 1; + fComb = 0; nFrames = 32; nWords = 8; + TimeOut = 30; + fMiter = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FWvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FWTncmvh" ) ) != EOF ) { switch ( c ) { @@ -14376,6 +14858,26 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nWords < 0 ) goto usage; break; + case 'T': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + TimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeOut < 0 ) + goto usage; + break; + case 'n': + fNew ^= 1; + break; + case 'c': + fComb ^= 1; + break; + case 'm': + fMiter ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -14390,27 +14892,24 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsStrash(pNtk) ) { fprintf( pErr, "Only works for strashed networks.\n" ); return 1; } - if ( !Abc_NtkLatchNum(pNtk) ) - { - fprintf( pErr, "The network is combinational.\n" ); - return 0; - } - FREE( pNtk->pSeqModel ); - Abc_NtkDarSeqSim( pNtk, nFrames, nWords, fVerbose ); + Abc_NtkDarSeqSim( pNtk, nFrames, nWords, TimeOut, fNew, fComb, fMiter, fVerbose ); return 0; usage: - fprintf( pErr, "usage: sim [-F num] [-W num] [-vh]\n" ); + fprintf( pErr, "usage: sim [-FWT num] [-ncmvh]\n" ); fprintf( pErr, "\t performs random simulation of the sequentail miter\n" ); fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); fprintf( pErr, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); + fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", TimeOut ); + fprintf( pErr, "\t-n : toggle new vs. old implementation [default = %s]\n", fNew? "new": "old" ); + fprintf( pErr, "\t-c : toggle comb vs. seq simulaton [default = %s]\n", fComb? "comb": "seq" ); + fprintf( pErr, "\t-m : toggle miter vs. any circuit [default = %s]\n", fMiter? "miter": "not miter" ); fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -14664,7 +15163,7 @@ int Abc_CommandClockGate( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Cgt_SetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "LNDCVKvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "LNDCVKavwh" ) ) != EOF ) { switch ( c ) { @@ -14734,9 +15233,15 @@ int Abc_CommandClockGate( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nFlopsMin <= 0 ) goto usage; break; + case 'a': + pPars->fAreaOnly ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; case 'h': goto usage; default: @@ -14780,7 +15285,7 @@ int Abc_CommandClockGate( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: clockgate [-LNDCVK ] [-vh] \n" ); + fprintf( pErr, "usage: clockgate [-LNDCVK ] [-avwh] \n" ); fprintf( pErr, "\t sequential clock gating with observability don't-cares\n" ); fprintf( pErr, "\t-L num : max level number of a clock gate [default = %d]\n", pPars->nLevelMax ); fprintf( pErr, "\t-N num : max number of candidates for a flop [default = %d]\n", pPars->nCandMax ); @@ -14788,7 +15293,9 @@ usage: fprintf( pErr, "\t-C num : max number of conflicts at a node [default = %d]\n", pPars->nConfMax ); fprintf( pErr, "\t-V num : min number of vars to recycle SAT solver [default = %d]\n", pPars->nVarsMin ); fprintf( pErr, "\t-K num : min number of flops to recycle SAT solver [default = %d]\n", pPars->nFlopsMin ); + fprintf( pErr, "\t-a : toggle minimizing area-only [default = %s]\n", pPars->fAreaOnly? "yes": "no" ); fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle even more detailed output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\tfile : (optional) constraints for primary inputs and register outputs\n"); return 1; @@ -14805,115 +15312,335 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandExtWin( Abc_Frame_t * pAbc, int argc, char ** argv ) { - char Buffer[16]; FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; - int fDelete1, fDelete2; - char ** pArgvNew; - int nArgcNew; + Abc_Ntk_t * pNtkRes, * pNtk; int c; - int fSat; + int nObjId; + int nDist; int fVerbose; - int nSeconds; - int nPartSize; - int nConfLimit; - int nInsLimit; - int fPartition; - extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); - extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); - extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ); - extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkDarExtWin( Abc_Ntk_t * pNtk, int nObjId, int nDist, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fSat = 0; + nObjId = -1; + nDist = 5; fVerbose = 0; - nSeconds = 20; - nPartSize = 0; - nConfLimit = 10000; - nInsLimit = 0; - fPartition = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NDvh" ) ) != EOF ) { switch ( c ) { - case 'T': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); - goto usage; - } - nSeconds = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nSeconds < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - 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': + case 'N': if ( globalUtilOptind >= argc ) { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } - nInsLimit = atoi(argv[globalUtilOptind]); + nObjId = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nInsLimit < 0 ) + if ( nObjId <= 0 ) goto usage; break; - case 'P': + case 'D': if ( globalUtilOptind >= argc ) { - fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } - nPartSize = atoi(argv[globalUtilOptind]); + nDist = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nPartSize < 0 ) + if ( nDist <= 0 ) goto usage; break; - case 'p': - fPartition ^= 1; - break; - case 's': - fSat ^= 1; - break; case 'v': fVerbose ^= 1; break; + case 'h': + goto usage; default: goto usage; } } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for structrally hashed networks.\n" ); return 1; + } - // perform equivalence checking - if ( fPartition ) - Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose ); - else if ( nPartSize ) - Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose ); - else if ( fSat ) - Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit ); + if ( argc != globalUtilOptind ) + { + fprintf( pErr, "Not enough command-line arguments.\n" ); + return 1; + } + // modify the current network + pNtkRes = Abc_NtkDarExtWin( pNtk, nObjId, nDist, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Extracting sequential window has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: extwin [-ND ] [-vh]\n" ); + fprintf( pErr, "\t extracts sequential window from the AIG\n" ); + fprintf( pErr, "\t-N num : the ID of the object to use as the center [default = %d]\n", nObjId ); + fprintf( pErr, "\t-D num : the \"radius\" of the window [default = %d]\n", nDist ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandInsWin( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtkRes, * pNtk, * pNtkCare; + int c; + int nObjId; + int nDist; + int fVerbose; + + extern Abc_Ntk_t * Abc_NtkDarInsWin( Abc_Ntk_t * pNtk, Abc_Ntk_t * pWnd, int nObjId, int nDist, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nObjId = -1; + nDist = 5; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NDvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nObjId = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nObjId <= 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + nDist = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nDist <= 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for structrally hashed networks.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 1 ) + { + fprintf( pErr, "Not enough command-line arguments.\n" ); + return 1; + } + pNtkCare = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1 ); + if ( pNtkCare == NULL ) + { + printf( "Reading care network has failed.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtkCare) ) + { + Abc_Ntk_t * pNtkTemp; + pNtkCare = Abc_NtkStrash( pNtkTemp = pNtkCare, 0, 1, 0 ); + Abc_NtkDelete( pNtkTemp ); + } + // modify the current network + pNtkRes = Abc_NtkDarInsWin( pNtk, pNtkCare, nObjId, nDist, fVerbose ); + Abc_NtkDelete( pNtkCare ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Inserting sequential window has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: inswin [-ND ] [-vh] \n" ); + fprintf( pErr, "\t inserts sequential window into the AIG\n" ); + fprintf( pErr, "\t-N num : the ID of the object to use as the center [default = %d]\n", nObjId ); + fprintf( pErr, "\t-D num : the \"radius\" of the window [default = %d]\n", nDist ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tfile : file with the AIG to be inserted\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[16]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fSat; + int fVerbose; + int nSeconds; + int nPartSize; + int nConfLimit; + int nInsLimit; + int fPartition; + + extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); + extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); + extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ); + extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fSat = 0; + fVerbose = 0; + nSeconds = 20; + nPartSize = 0; + nConfLimit = 10000; + nInsLimit = 0; + fPartition = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nSeconds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSeconds < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + 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; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPartSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPartSize < 0 ) + goto usage; + break; + case 'p': + fPartition ^= 1; + break; + case 's': + fSat ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + // perform equivalence checking + if ( fPartition ) + Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose ); + else if ( nPartSize ) + Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose ); + else if ( fSat ) + Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit ); else Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose ); @@ -15108,47 +15835,190 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandCec2( Abc_Frame_t * pAbc, int argc, char ** argv ) { + Cec_ParCec_t Pars, * pPars = &Pars; FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; int fDelete1, fDelete2; char ** pArgvNew; int nArgcNew; + int fMiter; int c; - int fRetime; - int fSat; - int fVerbose; - int nFrames; - int nSeconds; - int nConfLimit; - int nInsLimit; - - extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ); - extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); - + + extern int Abc_NtkDarCec2( Abc_Ntk_t * pNtk0, Abc_Ntk_t * pNtk1, Cec_ParCec_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fRetime = 0; // verification after retiming - fSat = 0; - fVerbose = 0; - nFrames = 5; - nSeconds = 20; - nConfLimit = 10000; - nInsLimit = 0; + fMiter = 0; + Cec_ManCecSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "BMImfrsvh" ) ) != EOF ) { switch ( c ) { - case 'F': + case 'B': if ( globalUtilOptind >= argc ) { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTLimitBeg = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimitBeg < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTlimitMulti = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTlimitMulti < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIters < 0 ) + goto usage; + break; + case 'm': + fMiter ^= 1; + break; + case 'f': + pPars->fFirstStop ^= 1; + break; + case 'r': + pPars->fRewriting ^= 1; + break; + case 's': + pPars->fSatSweeping ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( fMiter ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + pNtk1 = pNtk; + fDelete1 = 0; + } + else + { + pNtk1 = Abc_NtkStrash( pNtk, 0, 1, 0 ); + fDelete1 = 1; + } + pNtk2 = NULL; + fDelete2 = 0; + } + else + { + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + } + + // perform equivalence checking + Abc_NtkDarCec2( pNtk1, pNtk2, pPars ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + fprintf( pErr, "usage: cec2 [-BMI num] [-frsvh] \n" ); + fprintf( pErr, "\t performs combinational equivalence checking\n" ); + fprintf( pErr, "\t-B num : staring limit on the number of conflicts [default = %d]\n", pPars->nBTLimitBeg ); + fprintf( pErr, "\t-M num : multiple of the above limit [default = %d]\n", pPars->nBTlimitMulti ); + fprintf( pErr, "\t-I num : the number of iterations [default = %d]\n", pPars->nIters ); + fprintf( pErr, "\t-m : toggle working on two networks or a miter [default = %s]\n", fMiter? "miter": "two networks" ); + fprintf( pErr, "\t-f : toggle stopping after first mismatch [default = %s]\n", pPars->fFirstStop? "yes": "no" ); + fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", pPars->fRewriting? "yes": "no" ); + fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", pPars->fSatSweeping? "SAT only": "FRAIG + SAT" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + 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"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fRetime; + int fSat; + int fVerbose; + int nFrames; + int nSeconds; + int nConfLimit; + int nInsLimit; + + extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ); + extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); + + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fRetime = 0; // verification after retiming + fSat = 0; + fVerbose = 0; + nFrames = 5; + nSeconds = 20; + nConfLimit = 10000; + nInsLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsrvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFrames = atoi(argv[globalUtilOptind]); @@ -15325,38 +16195,449 @@ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) - return 1; - if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + { + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + + // perform verification + Abc_NtkDarSec( pNtk1, pNtk2, pSecPar ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + fprintf( pErr, "usage: dsec [-F num] [-T num] [-armfwvh] \n" ); + fprintf( pErr, "\t performs inductive sequential equivalence checking\n" ); + fprintf( pErr, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax ); + fprintf( pErr, "\t-T num : the approximate runtime limit (in seconds) [default = %d]\n", pSecPar->TimeLimit ); + fprintf( pErr, "\t-a : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" ); + fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" ); + fprintf( pErr, "\t-m : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" ); + fprintf( pErr, "\t-f : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + 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"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Fra_Sec_t SecPar, * pSecPar = &SecPar; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + extern void Fra_SecSetDefaultParams( Fra_Sec_t * p ); + extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, Fra_Sec_t * pSecPar ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Fra_SecSetDefaultParams( pSecPar ); +// pSecPar->TimeLimit = 300; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "cbFCGDVBRarmfijwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + pSecPar->fTryComb ^= 1; + break; + case 'b': + pSecPar->fTryBmc ^= 1; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pSecPar->nFramesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pSecPar->nFramesMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pSecPar->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pSecPar->nBTLimit < 0 ) + goto usage; + break; + case 'G': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-G\" should be followed by an integer.\n" ); + goto usage; + } + pSecPar->nBTLimitGlobal = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pSecPar->nBTLimitGlobal < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pSecPar->nBTLimitInter = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pSecPar->nBTLimitInter < 0 ) + goto usage; + break; + case 'V': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-V\" should be followed by an integer.\n" ); + goto usage; + } + pSecPar->nBddVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pSecPar->nBddVarsMax < 0 ) + goto usage; + break; + case 'B': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + pSecPar->nBddMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pSecPar->nBddMax < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + pSecPar->nBddIterMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pSecPar->nBddIterMax < 0 ) + goto usage; + break; + case 'a': + pSecPar->fPhaseAbstract ^= 1; + break; + case 'r': + pSecPar->fRetimeFirst ^= 1; + break; + case 'm': + pSecPar->fRetimeRegs ^= 1; + break; + case 'f': + pSecPar->fFraiging ^= 1; + break; + case 'i': + pSecPar->fInduction ^= 1; + break; + case 'j': + pSecPar->fInterpolation ^= 1; + break; + case 'w': + pSecPar->fVeryVerbose ^= 1; + break; + case 'v': + pSecPar->fVerbose ^= 1; + break; + default: + goto usage; + } + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + + // perform verification + Abc_NtkDarProve( pNtk, pSecPar ); + + // Fra_SmlWriteCounterExample( stdout, Aig_Man_t * pAig, Fra_Cex_t * p ) + + return 0; + +usage: + fprintf( pErr, "usage: dprove [-FCGDVBR num] [-cbarmfijwvh]\n" ); + fprintf( pErr, "\t performs SEC on the sequential miter\n" ); + fprintf( pErr, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax ); + fprintf( pErr, "\t-C num : the conflict limit at a node during induction [default = %d]\n", pSecPar->nBTLimit ); + fprintf( pErr, "\t-G num : the global conflict limit during induction [default = %d]\n", pSecPar->nBTLimitGlobal ); + fprintf( pErr, "\t-D num : the conflict limit during interpolation [default = %d]\n", pSecPar->nBTLimitInter ); + fprintf( pErr, "\t-V num : the flop count limit for BDD-based reachablity [default = %d]\n", pSecPar->nBddVarsMax ); + fprintf( pErr, "\t-B num : the BDD size limit in BDD-based reachablity [default = %d]\n", pSecPar->nBddMax ); + fprintf( pErr, "\t-R num : the max number of reachability iterations [default = %d]\n", pSecPar->nBddIterMax ); + fprintf( pErr, "\t-c : toggles using CEC before attempting SEC [default = %s]\n", pSecPar->fTryComb? "yes": "no" ); + fprintf( pErr, "\t-b : toggles using BMC before attempting SEC [default = %s]\n", pSecPar->fTryBmc? "yes": "no" ); + fprintf( pErr, "\t-a : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" ); + fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" ); + fprintf( pErr, "\t-m : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" ); + fprintf( pErr, "\t-f : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" ); + fprintf( pErr, "\t-i : toggles the use of induction [default = %s]\n", pSecPar->fInduction? "yes": "no" ); + fprintf( pErr, "\t-j : toggles the use of interpolation [default = %s]\n", pSecPar->fInterpolation? "yes": "no" ); +// fprintf( pErr, "\t-n : toggles the use of different induction prover [default = %s]\n", pSecPar->fUseNewProver? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int fMiter, nFrames, fVerbose, c; + + extern int Abc_NtkDarAbSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fMiter = 1; + nFrames = 2; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fmvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'm': + fMiter ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + if ( fMiter ) + { + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + Abc_NtkDarAbSec( pNtk, NULL, nFrames, fVerbose ); + } + else + { + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + { + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + // perform verification + Abc_NtkDarAbSec( pNtk1, pNtk2, nFrames, fVerbose ); + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + } + return 0; + +usage: + fprintf( pErr, "usage: absec [-F num] [-mv] \n" ); + fprintf( pErr, "\t performs SEC by applying CEC to several timeframes\n" ); + fprintf( pErr, "\t-F num : the total number of timeframes to use [default = %d]\n", nFrames ); + fprintf( pErr, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + 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"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSimSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Ssw_Pars_t Pars, * pPars = &Pars; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew, c; + int fMiter; + + extern int Abc_NtkDarSimSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Ssw_Pars_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fMiter = 1; + Ssw_ManSetDefaultParams( pPars ); + pPars->fPartSigCorr = 1; + pPars->fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "FDcymvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nFramesK = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFramesK < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nIsleDist = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIsleDist < 0 ) + goto usage; + break; + case 'm': + fMiter ^= 1; + break; + case 'c': + pPars->fPartSigCorr ^= 1; + break; + case 'y': + pPars->fDumpSRInit ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + default: + goto usage; + } + } + + if ( fMiter ) + { +// Abc_Ntk_t * pNtkA, * pNtkB; + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + Abc_NtkDarSimSec( pNtk, NULL, pPars ); +/* + pNtkA = Abc_NtkDup( pNtk ); + pNtkB = Abc_NtkDup( pNtk ); + Abc_NtkDarSimSec( pNtkA, pNtkB, pPars ); + Abc_NtkDelete( pNtkA ); + Abc_NtkDelete( pNtkB ); +*/ + } + else { + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + { + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + // perform verification + Abc_NtkDarSimSec( pNtk1, pNtk2, pPars ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); - printf( "The network has no latches. Used combinational command \"cec\".\n" ); - return 0; } - - // perform verification - Abc_NtkDarSec( pNtk1, pNtk2, pSecPar ); - - if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); - if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 0; usage: - fprintf( pErr, "usage: dsec [-F num] [-T num] [-armfwvh] \n" ); - fprintf( pErr, "\t performs inductive sequential equivalence checking\n" ); - fprintf( pErr, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax ); - fprintf( pErr, "\t-T num : the approximate runtime limit (in seconds) [default = %d]\n", pSecPar->TimeLimit ); - fprintf( pErr, "\t-a : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" ); - fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" ); - fprintf( pErr, "\t-m : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" ); - fprintf( pErr, "\t-f : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "usage: simsec [-FD num] [-mcyv] \n" ); + fprintf( pErr, "\t performs SEC using structural similarity\n" ); + fprintf( pErr, "\t-F num : the limit on the depth of induction [default = %d]\n", pPars->nFramesK ); + fprintf( pErr, "\t-D num : the distance for extending islands [default = %d]\n", pPars->nIsleDist ); + fprintf( pErr, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" ); + fprintf( pErr, "\t-c : uses partial vs. full signal correspondence [default = %s]\n", pPars->fPartSigCorr? "partial": "full" ); + fprintf( pErr, "\t-y : dumps speculatively reduced miter of the classes [default = %s]\n", pPars->fDumpSRInit? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); 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"); @@ -15375,175 +16656,109 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandMatch( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Fra_Sec_t SecPar, * pSecPar = &SecPar; FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew, c; + int fMiter; + int nDist; + int fVerbose; - extern void Fra_SecSetDefaultParams( Fra_Sec_t * p ); - extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, Fra_Sec_t * pSecPar ); + extern Abc_Ntk_t * Abc_NtkDarMatch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nDist, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - Fra_SecSetDefaultParams( pSecPar ); -// pSecPar->TimeLimit = 300; + fMiter = 0; + nDist = 0; + fVerbose = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "cbFCGDVBRarmfijwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Dmvh" ) ) != EOF ) { switch ( c ) { - case 'c': - pSecPar->fTryComb ^= 1; - break; - case 'b': - pSecPar->fTryBmc ^= 1; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - pSecPar->nFramesMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pSecPar->nFramesMax < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pSecPar->nBTLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pSecPar->nBTLimit < 0 ) - goto usage; - break; - case 'G': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-G\" should be followed by an integer.\n" ); - goto usage; - } - pSecPar->nBTLimitGlobal = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pSecPar->nBTLimitGlobal < 0 ) - goto usage; - break; case 'D': if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } - pSecPar->nBTLimitInter = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pSecPar->nBTLimitInter < 0 ) - goto usage; - break; - case 'V': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-V\" should be followed by an integer.\n" ); - goto usage; - } - pSecPar->nBddVarsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pSecPar->nBddVarsMax < 0 ) - goto usage; - break; - case 'B': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); - goto usage; - } - pSecPar->nBddMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pSecPar->nBddMax < 0 ) - goto usage; - break; - case 'R': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); - goto usage; - } - pSecPar->nBddIterMax = atoi(argv[globalUtilOptind]); + nDist = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( pSecPar->nBddIterMax < 0 ) + if ( nDist < 0 ) goto usage; break; - case 'a': - pSecPar->fPhaseAbstract ^= 1; - break; - case 'r': - pSecPar->fRetimeFirst ^= 1; - break; case 'm': - pSecPar->fRetimeRegs ^= 1; - break; - case 'f': - pSecPar->fFraiging ^= 1; - break; - case 'i': - pSecPar->fInduction ^= 1; - break; - case 'j': - pSecPar->fInterpolation ^= 1; - break; - case 'w': - pSecPar->fVeryVerbose ^= 1; + fMiter ^= 1; break; case 'v': - pSecPar->fVerbose ^= 1; + fVerbose ^= 1; break; default: goto usage; } } - if ( !Abc_NtkIsStrash(pNtk) ) + if ( fMiter ) { - printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); - return 0; +// Abc_Ntk_t * pNtkA, * pNtkB; + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + pNtkRes = Abc_NtkDarMatch( pNtk, NULL, nDist, fVerbose ); +/* + pNtkA = Abc_NtkDup( pNtk ); + pNtkB = Abc_NtkDup( pNtk ); + Abc_NtkDarSimSec( pNtkA, pNtkB, pPars ); + Abc_NtkDelete( pNtkA ); + Abc_NtkDelete( pNtkB ); +*/ } - - // perform verification - Abc_NtkDarProve( pNtk, pSecPar ); - - // Fra_SmlWriteCounterExample( stdout, Aig_Man_t * pAig, Fra_Cex_t * p ) - + else + { + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + { + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + // perform verification + pNtkRes = Abc_NtkDarMatch( pNtk1, pNtk2, nDist, fVerbose ); + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + } + if ( pNtkRes == NULL ) + { + printf( "Matching has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: - fprintf( pErr, "usage: dprove [-FCGDVBR num] [-cbarmfijwvh]\n" ); - fprintf( pErr, "\t performs SEC on the sequential miter\n" ); - fprintf( pErr, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax ); - fprintf( pErr, "\t-C num : the conflict limit at a node during induction [default = %d]\n", pSecPar->nBTLimit ); - fprintf( pErr, "\t-G num : the global conflict limit during induction [default = %d]\n", pSecPar->nBTLimitGlobal ); - fprintf( pErr, "\t-D num : the conflict limit during interpolation [default = %d]\n", pSecPar->nBTLimitInter ); - fprintf( pErr, "\t-V num : the flop count limit for BDD-based reachablity [default = %d]\n", pSecPar->nBddVarsMax ); - fprintf( pErr, "\t-B num : the BDD size limit in BDD-based reachablity [default = %d]\n", pSecPar->nBddMax ); - fprintf( pErr, "\t-R num : the max number of reachability iterations [default = %d]\n", pSecPar->nBddIterMax ); - fprintf( pErr, "\t-c : toggles using CEC before attempting SEC [default = %s]\n", pSecPar->fTryComb? "yes": "no" ); - fprintf( pErr, "\t-b : toggles using BMC before attempting SEC [default = %s]\n", pSecPar->fTryBmc? "yes": "no" ); - fprintf( pErr, "\t-a : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" ); - fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" ); - fprintf( pErr, "\t-m : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" ); - fprintf( pErr, "\t-f : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" ); - fprintf( pErr, "\t-i : toggles the use of induction [default = %s]\n", pSecPar->fInduction? "yes": "no" ); - fprintf( pErr, "\t-j : toggles the use of interpolation [default = %s]\n", pSecPar->fInterpolation? "yes": "no" ); -// fprintf( pErr, "\t-n : toggles the use of different induction prover [default = %s]\n", pSecPar->fUseNewProver? "yes": "no" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "usage: match [-D num] [-mv] \n" ); + fprintf( pErr, "\t detects structural similarity using simulation\n" ); + fprintf( pErr, "\t replaces the current network by the miter of differences\n" ); + fprintf( pErr, "\t-D num : the distance for extending differences [default = %d]\n", nDist ); + fprintf( pErr, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + 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"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); return 1; } @@ -17133,8 +18348,9 @@ int Abc_CommandPBAbstraction( Abc_Frame_t * pAbc, int argc, char ** argv ) pNtkRes = Abc_NtkDarPBAbstraction( pNtk, nFramesMax, nConfMax, fDynamic, fExtend, fVerbose ); if ( pNtkRes == NULL ) { - fprintf( pErr, "Target enlargement has failed.\n" ); - return 1; + if ( pNtk->pSeqModel == NULL ) + printf( "Proof-based abstraction has failed.\n" ); + return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); @@ -17297,16 +18513,19 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; int fMapped; int fTest; + int fAlter; extern void * Ioa_ReadBlif( char * pFileName, int fCheck ); extern void Ioa_WriteBlif( void * p, char * pFileName ); extern Aig_Man_t * Ntl_ManExtract( void * p ); extern void * Ntl_ManExtractNwk( void * p, Aig_Man_t * pAig, Tim_Man_t * pManTime ); + extern void Ntl_ManPrintStats( void * p ); // set defaults fMapped = 0; fTest = 0; + fAlter = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mth" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "mtah" ) ) != EOF ) { switch ( c ) { @@ -17316,6 +18535,9 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv ) case 't': fTest ^= 1; break; + case 'a': + fAlter ^= 1; + break; case 'h': goto usage; default: @@ -17334,11 +18556,9 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } fclose( pFile ); - if ( fTest ) { extern void Ntl_ManFree( void * p ); - extern void Ntl_ManPrintStats( void * p ); void * pTemp = Ioa_ReadBlif( pFileName, 1 ); if ( pTemp ) { @@ -17350,11 +18570,26 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv ) } Abc_FrameClearDesign(); - pAbc->pAbc8Ntl = Ioa_ReadBlif( pFileName, 1 ); - if ( pAbc->pAbc8Ntl == NULL ) + if ( !fAlter ) { - printf( "Abc_CommandAbc8Read(): Reading BLIF has failed.\n" ); - return 1; + pAbc->pAbc8Ntl = Ioa_ReadBlif( pFileName, 1 ); + if ( pAbc->pAbc8Ntl == NULL ) + { + printf( "Abc_CommandAbc8Read(): Reading BLIF has failed.\n" ); + return 1; + } + } + else + { + extern void * Nal_ManRead( char * pFileName ); + pAbc->pAbc8Ntl = NULL; +// pAbc->pAbc8Ntl = Nal_ManRead( pFileName ); +// Ioa_WriteBlif( pAbc->pAbc8Ntl, "test_boxes.blif" ); + if ( pAbc->pAbc8Ntl == NULL ) + { + printf( "Abc_CommandAbc8Read(): Reading design has failed.\n" ); + return 1; + } } pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl ); if ( pAbc->pAbc8Aig == NULL ) @@ -17371,10 +18606,11 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( stdout, "usage: *r [-mth]\n" ); + fprintf( stdout, "usage: *r [-mtah]\n" ); fprintf( stdout, "\t reads the design with whiteboxes\n" ); fprintf( stdout, "\t-m : toggle extracting mapped network [default = %s]\n", fMapped? "yes": "no" ); fprintf( stdout, "\t-t : toggle reading in the test mode [default = %s]\n", fTest? "yes": "no" ); + fprintf( stdout, "\t-a : toggle reading another file type [default = %s]\n", fAlter? "yes": "no" ); fprintf( stdout, "\t-h : print the command usage\n"); return 1; } @@ -17468,6 +18704,7 @@ int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv ) char * pFileName; void * pTemp; int fAig; + int fBlif; int fCollapsed; int c; extern void Ioa_WriteBlif( void * p, char * pFileName ); @@ -17479,15 +18716,19 @@ int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fAig = 0; + fBlif = 1; fCollapsed = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "abch" ) ) != EOF ) { switch ( c ) { case 'a': fAig ^= 1; break; + case 'b': + fBlif ^= 1; + break; case 'c': fCollapsed ^= 1; break; @@ -17501,29 +18742,38 @@ int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv ) { printf( "Abc_CommandAbc8Write(): There is no design to write.\n" ); return 1; - } + } // create the design to write pFileName = argv[globalUtilOptind]; if ( fAig ) { if ( fCollapsed ) { + extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); pTemp = Ntl_ManCollapseSeq( pAbc->pAbc8Ntl, 0 ); - Saig_ManDumpBlif( pTemp, pFileName ); + if ( fBlif ) + Saig_ManDumpBlif( pTemp, pFileName ); + else + Ioa_WriteAiger( pTemp, pFileName, 0, 0 ); Aig_ManStop( pTemp ); } else { if ( pAbc->pAbc8Aig != NULL ) { - pTemp = Ntl_ManInsertAig( pAbc->pAbc8Ntl, pAbc->pAbc8Aig ); - if ( pTemp == NULL ) + if ( fBlif ) { - printf( "Abc_CommandAbc8Write(): Inserting AIG has failed.\n" ); - return 1; + pTemp = Ntl_ManInsertAig( pAbc->pAbc8Ntl, pAbc->pAbc8Aig ); + if ( pTemp == NULL ) + { + printf( "Abc_CommandAbc8Write(): Inserting AIG has failed.\n" ); + return 1; + } + Ioa_WriteBlif( pTemp, pFileName ); + Ntl_ManFree( pTemp ); } - Ioa_WriteBlif( pTemp, pFileName ); - Ntl_ManFree( pTemp ); + else + Ioa_WriteAiger( pAbc->pAbc8Aig, pFileName, 0, 0 ); } else { @@ -17547,17 +18797,18 @@ int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - pTemp = pAbc->pAbc8Ntl; printf( "Writing the unmapped netlist.\n" ); + pTemp = pAbc->pAbc8Ntl; Ioa_WriteBlif( pTemp, pFileName ); } } return 0; usage: - fprintf( stdout, "usage: *w [-ach]\n" ); + fprintf( stdout, "usage: *w [-abch]\n" ); fprintf( stdout, "\t write the design with whiteboxes\n" ); fprintf( stdout, "\t-a : toggle writing mapped network or AIG [default = %s]\n", fAig? "AIG": "mapped" ); + fprintf( stdout, "\t-b : toggle writing AIG as BLIF or AIGER [default = %s]\n", fBlif? "BLIF": "AIGER" ); fprintf( stdout, "\t-c : toggle writing collapsed sequential AIG [default = %s]\n", fCollapsed? "yes": "no" ); fprintf( stdout, "\t-h : print the command usage\n"); return 1; @@ -17841,14 +19092,19 @@ int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; int fSaveBest; int fDumpResult; + int fPower; + int fShort; extern void Ntl_ManPrintStats( void * p ); - extern void Nwk_ManPrintStats( void * p, void * pLutLib, int fSaveBest, int fDumpResult, void * pNtl ); + extern void Nwk_ManPrintStats( void * p, void * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl ); + extern void Nwk_ManPrintStatsShort( void * p, void * pAig, void * pNtk ); // set defaults fSaveBest = 0; fDumpResult = 0; + fPower = 0; + fShort = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "bdh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "bdpsh" ) ) != EOF ) { switch ( c ) { @@ -17858,6 +19114,12 @@ int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': fDumpResult ^= 1; break; + case 'p': + fPower ^= 1; + break; + case 's': + fShort ^= 1; + break; case 'h': goto usage; default: @@ -17870,6 +19132,11 @@ int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } + if ( fShort ) + { + Nwk_ManPrintStatsShort( pAbc->pAbc8Ntl, pAbc->pAbc8Aig, pAbc->pAbc8Nwk ); + return 0; + } // get the input file name if ( pAbc->pAbc8Ntl ) { @@ -17889,15 +19156,17 @@ int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) pAbc->pAbc8Lib = If_SetSimpleLutLib( 6 ); } printf( "MAPPED: " ); - Nwk_ManPrintStats( pAbc->pAbc8Nwk, pAbc->pAbc8Lib, fSaveBest, fDumpResult, pAbc->pAbc8Ntl ); + Nwk_ManPrintStats( pAbc->pAbc8Nwk, pAbc->pAbc8Lib, fSaveBest, fDumpResult, fPower, pAbc->pAbc8Ntl ); } return 0; usage: - fprintf( stdout, "usage: *ps [-bdh]\n" ); + fprintf( stdout, "usage: *ps [-bdpsh]\n" ); fprintf( stdout, "\t prints design statistics\n" ); fprintf( stdout, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); fprintf( stdout, "\t-d : toggles dumping network into file \"_dump.blif\" [default = %s]\n", fDumpResult? "yes": "no" ); + fprintf( stdout, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" ); + fprintf( stdout, "\t-s : toggles short printing mode [default = %s]\n", fShort? "yes": "no" ); fprintf( stdout, "\t-h : print the command usage\n"); return 1; } @@ -17979,7 +19248,7 @@ int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv ) Nwk_ManSetIfParsDefault( pPars ); pPars->pLutLib = pAbc->pAbc8Lib; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEpaflemrstbvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEqaflepmrstbvh" ) ) != EOF ) { switch ( c ) { @@ -18039,6 +19308,7 @@ int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv ) globalUtilOptind++; if ( pPars->DelayTarget <= 0.0 ) goto usage; + break; case 'E': if ( globalUtilOptind >= argc ) { @@ -18050,7 +19320,7 @@ int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 ) goto usage; break; - case 'p': + case 'q': pPars->fPreprocess ^= 1; break; case 'a': @@ -18068,6 +19338,9 @@ int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'e': pPars->fEdge ^= 1; break; + case 'p': + pPars->fPower ^= 1; + break; case 'm': pPars->fCutMin ^= 1; break; @@ -18146,7 +19419,7 @@ usage: sprintf( LutSize, "library" ); else sprintf( LutSize, "%d", pPars->nLutSize ); - fprintf( stdout, "usage: *if [-KCFA num] [-DE float] [-parlembvh]\n" ); + fprintf( stdout, "usage: *if [-KCFA num] [-DE float] [-qarlepmbvh]\n" ); fprintf( stdout, "\t performs FPGA technology mapping of the network\n" ); fprintf( stdout, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); fprintf( stdout, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -18154,12 +19427,13 @@ usage: fprintf( stdout, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); fprintf( stdout, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); fprintf( stdout, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); - fprintf( stdout, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); + fprintf( stdout, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); fprintf( stdout, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); // fprintf( stdout, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" ); fprintf( stdout, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); fprintf( stdout, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); fprintf( stdout, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" ); + fprintf( stdout, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); fprintf( stdout, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" ); // fprintf( stdout, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" ); // fprintf( stdout, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" ); @@ -18332,7 +19606,7 @@ int Abc_CommandAbc8Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fSynthesis ^= 1; break; case 'p': - pPars->fPolarFlip ^= 1; + pPars->fPower ^= 1; break; case 't': pPars->fSimulateTfo ^= 1; @@ -18370,7 +19644,7 @@ usage: fprintf( stdout, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); fprintf( stdout, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax ); fprintf( stdout, "\t-s : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" ); - fprintf( stdout, "\t-p : toggle alighning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" ); + fprintf( stdout, "\t-p : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" ); fprintf( stdout, "\t-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" ); fprintf( stdout, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( stdout, "\t-h : print the command usage\n"); @@ -18395,15 +19669,17 @@ int Abc_CommandAbc8DC2( Abc_Frame_t * pAbc, int argc, char ** argv ) int fBalance; int fUpdateLevel; int fVerbose; + int fPower; - extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fVerbose ); + extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); // set defaults fBalance = 1; fUpdateLevel = 1; + fPower = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "blh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "blpvh" ) ) != EOF ) { switch ( c ) { @@ -18413,6 +19689,9 @@ int Abc_CommandAbc8DC2( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'l': fUpdateLevel ^= 1; break; + case 'p': + fPower ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -18429,7 +19708,7 @@ int Abc_CommandAbc8DC2( Abc_Frame_t * pAbc, int argc, char ** argv ) } // get the input file name - pAigNew = Dar_ManCompress2( pAbc->pAbc8Aig, fBalance, fUpdateLevel, 1, fVerbose ); + pAigNew = Dar_ManCompress2( pAbc->pAbc8Aig, fBalance, fUpdateLevel, 1, fPower, fVerbose ); if ( pAigNew == NULL ) { printf( "Abc_CommandAbc8DC2(): Tranformation of the AIG has failed.\n" ); @@ -18440,10 +19719,11 @@ int Abc_CommandAbc8DC2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( stdout, "usage: *dc2 [-blvh]\n" ); + fprintf( stdout, "usage: *dc2 [-blpvh]\n" ); fprintf( stdout, "\t performs AIG-based synthesis without deriving choices\n" ); fprintf( stdout, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); fprintf( stdout, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( stdout, "\t-p : toggle power-aware rewriting [default = %s]\n", fPower? "yes": "no" ); fprintf( stdout, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); fprintf( stdout, "\t-h : print the command usage\n"); return 1; @@ -18526,7 +19806,7 @@ int Abc_CommandAbc8Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) { printf( "Abc_CommandAbc8Strash(): There is no mapped network to strash.\n" ); return 1; - } + } pAigNew = Nwk_ManStrash( pAbc->pAbc8Nwk ); if ( pAigNew == NULL ) @@ -18566,7 +19846,7 @@ int Abc_CommandAbc8Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Mfx_ParsDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraesvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraespvwh" ) ) != EOF ) { switch ( c ) { @@ -18648,6 +19928,9 @@ int Abc_CommandAbc8Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': pPars->fSwapEdge ^= 1; break; + case 'p': + pPars->fPower ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -18687,7 +19970,7 @@ int Abc_CommandAbc8Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( stdout, "usage: *mfs [-WFDMLC ] [-raesvh]\n" ); + fprintf( stdout, "usage: *mfs [-WFDMLC ] [-raespvh]\n" ); fprintf( stdout, "\t performs don't-care-based optimization of logic networks\n" ); fprintf( stdout, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nWinTfoLevs ); fprintf( stdout, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutsMax ); @@ -18699,6 +19982,7 @@ usage: fprintf( stdout, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); fprintf( stdout, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); fprintf( stdout, "\t-s : toggle evaluation of edge swapping [default = %s]\n", pPars->fSwapEdge? "yes": "no" ); + fprintf( stdout, "\t-p : toggle power-aware optimization [default = %s]\n", pPars->fPower? "yes": "no" ); fprintf( stdout, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( stdout, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); fprintf( stdout, "\t-h : print the command usage\n"); @@ -19624,7 +20908,7 @@ int Abc_CommandAbc8Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Ssw_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSDVMpldvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSDVMpldsvh" ) ) != EOF ) { switch ( c ) { @@ -19747,6 +21031,9 @@ int Abc_CommandAbc8Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': pPars->fDynamic ^= 1; break; + case 's': + pPars->fLocalSim ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -19800,7 +21087,7 @@ int Abc_CommandAbc8Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( stdout, "usage: *scorr [-PQFCLNSDVM ] [-pldvh]\n" ); + fprintf( stdout, "usage: *scorr [-PQFCLNSDVM ] [-pldsvh]\n" ); fprintf( stdout, "\t performs sequential sweep using K-step induction\n" ); fprintf( stdout, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); fprintf( stdout, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); @@ -19815,6 +21102,7 @@ usage: fprintf( stdout, "\t-p : toggle alighning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" ); fprintf( stdout, "\t-l : toggle latch correspondence only [default = %s]\n", pPars->fLatchCorr? "yes": "no" ); fprintf( stdout, "\t-d : toggle dynamic addition of constraints [default = %s]\n", pPars->fDynamic? "yes": "no" ); + fprintf( stdout, "\t-s : toggle local simulation in the cone of influence [default = %s]\n", pPars->fLocalSim? "yes": "no" ); fprintf( stdout, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( stdout, "\t-h : print the command usage\n"); return 1; diff --git a/src/base/abci/abc.zip b/src/base/abci/abc.zip deleted file mode 100644 index 34df9a63..00000000 Binary files a/src/base/abci/abc.zip and /dev/null differ diff --git a/src/base/abci/abcBidec.c b/src/base/abci/abcBidec.c index bb114578..01146014 100644 --- a/src/base/abci/abcBidec.c +++ b/src/base/abci/abcBidec.c @@ -42,7 +42,7 @@ static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCo SeeAlso [] ***********************************************************************/ -Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare ) +Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ) { unsigned * pTruth; Bdc_Fun_t * pFunc; @@ -52,8 +52,33 @@ Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pR pTruth = Hop_ManConvertAigToTruth( pHop, Hop_Regular(pRoot), nVars, vTruth, 0 ); if ( Hop_IsComplement(pRoot) ) Extra_TruthNot( pTruth, pTruth, nVars ); - // decompose truth table - Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); + // perform power-aware decomposition + if ( dProb >= 0.0 ) + { + float Prob = (float)2.0 * dProb * (1.0 - dProb); + assert( Prob >= 0.0 && Prob <= 0.5 ); + if ( Prob >= 0.4 ) + { + Extra_TruthNot( puCare, puCare, nVars ); + if ( dProb > 0.5 ) // more 1s than 0s + Extra_TruthOr( pTruth, pTruth, puCare, nVars ); + else + Extra_TruthSharp( pTruth, pTruth, puCare, nVars ); + Extra_TruthNot( puCare, puCare, nVars ); + // decompose truth table + Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 ); + } + else + { + // decompose truth table + Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); + } + } + else + { + // decompose truth table + Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); + } // convert back into HOP Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) ); for ( i = 0; i < nVars; i++ ) @@ -104,7 +129,7 @@ void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ) if ( Abc_ObjFaninNum(pObj) > 15 ) continue; nNodes1 = Hop_DagSize(pObj->pData); - pObj->pData = Abc_NodeIfNodeResyn( p, pNtk->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj), vTruth, NULL ); + pObj->pData = Abc_NodeIfNodeResyn( p, pNtk->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj), vTruth, NULL, -1.0 ); nNodes2 = Hop_DagSize(pObj->pData); nGainTotal += nNodes1 - nNodes2; } diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c index d38f62d0..1c7459eb 100644 --- a/src/base/abci/abcCut.c +++ b/src/base/abci/abcCut.c @@ -37,6 +37,74 @@ static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ); /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCutsSubtractFanunt( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC; + int i, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( !Abc_NodeIsMuxType(pObj) ) + continue; + pFanC = Abc_NodeRecognizeMux( pObj, &pFan1, &pFan0 ); + pFanC = Abc_ObjRegular(pFanC); + pFan0 = Abc_ObjRegular(pFan0); + assert( pFanC->vFanouts.nSize > 1 ); + pFanC->vFanouts.nSize--; + Counter++; + if ( Abc_NodeIsExorType(pObj) ) + { + assert( pFan0->vFanouts.nSize > 1 ); + pFan0->vFanouts.nSize--; + Counter++; + } + } + printf("Substracted %d fanouts\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCutsAddFanunt( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC; + int i, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( !Abc_NodeIsMuxType(pObj) ) + continue; + pFanC = Abc_NodeRecognizeMux( pObj, &pFan1, &pFan0 ); + pFanC = Abc_ObjRegular(pFanC); + pFan0 = Abc_ObjRegular(pFan0); + pFanC->vFanouts.nSize++; + Counter++; + if ( Abc_NodeIsExorType(pObj) ) + { + pFan0->vFanouts.nSize++; + Counter++; + } + } + printf("Added %d fanouts\n", Counter ); +} + /**Function************************************************************* Synopsis [Computes the cuts for the network.] @@ -61,6 +129,9 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); + if ( pParams->fAdjust ) + Abc_NtkCutsSubtractFanunt( pNtk ); + nTotal = nGood = nEqual = 0; assert( Abc_NtkIsStrash(pNtk) ); @@ -118,7 +189,7 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) Vec_PtrFree( vNodes ); Vec_IntFree( vChoices ); Cut_ManPrintStats( p ); -PRT( "TOTAL ", clock() - clk ); +PRT( "TOTAL", clock() - clk ); printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) ); //Abc_NtkPrintCuts( p, pNtk, 0 ); // Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); @@ -126,6 +197,8 @@ PRT( "TOTAL ", clock() - clk ); // temporary printout of stats if ( nTotal ) printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); + if ( pParams->fAdjust ) + Abc_NtkCutsAddFanunt( pNtk ); return p; } diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c index dcc7f4c1..9dc10d84 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -29,6 +29,8 @@ #include "dch.h" #include "ssw.h" #include "cgt.h" +#include "cec.h" +#include "fsim.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -126,7 +128,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ) if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) ) pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0); // remove dangling nodes - nNodes = Aig_ManCleanup( pMan ); + nNodes = (Abc_NtkGetChoiceNum(pNtk) == 0)? Aig_ManCleanup( pMan ) : 0; if ( !fExors && nNodes ) printf( "Abc_NtkToDar(): Unexpected %d dangling nodes when converting to AIG!\n", nNodes ); //Aig_ManDumpVerilog( pMan, "test.v" ); @@ -149,6 +151,63 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ) return pMan; } +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [Assumes that registers are ordered after PIs/POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Abc_NtkToDarChoices( Abc_Ntk_t * pNtk ) +{ + Aig_Man_t * pMan; + Abc_Obj_t * pObj, * pPrev, * pFanin; + Vec_Ptr_t * vNodes; + int i; + vNodes = Abc_AigDfs( pNtk, 0, 0 ); + // create the manager + pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 ); + pMan->pName = Extra_UtilStrsav( pNtk->pName ); + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + pMan->pEquivs = ALLOC( Aig_Obj_t *, Abc_NtkObjNum(pNtk) ); + memset( pMan->pEquivs, 0, sizeof(Aig_Obj_t *) * Abc_NtkObjNum(pNtk) ); + } + // transfer the pointers to the basic nodes + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreatePi(pMan); + // perform the conversion of the internal nodes (assumes DFS ordering) + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) ); +// printf( "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id ); + if ( Abc_AigNodeIsChoice( pObj ) ) + { + for ( pPrev = pObj, pFanin = pObj->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) + Aig_ObjSetEquiv( pMan, (Aig_Obj_t *)pPrev->pCopy, (Aig_Obj_t *)pFanin->pCopy ); +// Aig_ManCreateChoice( pIfMan, (Aig_Obj_t *)pNode->pCopy ); + } + } + Vec_PtrFree( vNodes ); + // create the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Aig_ObjCreatePo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) ); + // complement the 1-valued registers + Aig_ManSetRegNum( pMan, 0 ); + if ( !Aig_ManCheck( pMan ) ) + { + printf( "Abc_NtkToDar: AIG check has failed.\n" ); + Aig_ManStop( pMan ); + return NULL; + } + return pMan; +} + /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] @@ -351,6 +410,9 @@ Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ) assert( pMan->nAsserts == 0 ); // perform strashing pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + // duplicate the name and the spec +// pNtkNew->pName = Extra_UtilStrsav(pMan->pName); +// pNtkNew->pSpec = Extra_UtilStrsav(pMan->pSpec); Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); // create PIs Aig_ManForEachPiSeq( pMan, pObj, i ) @@ -771,7 +833,7 @@ clk = clock(); SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fVerbose ) +Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ) { Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig; @@ -783,7 +845,7 @@ Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, // Aig_ManPrintStats( pMan ); clk = clock(); - pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fFanout, fVerbose ); + pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fFanout, fPower, fVerbose ); Aig_ManStop( pTemp ); //PRT( "time", clock() - clk ); @@ -832,7 +894,7 @@ Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, in ***********************************************************************/ Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars ) { - extern Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); + extern Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ); Vec_Ptr_t * vAigs; Aig_Man_t * pMan, * pTemp; @@ -845,8 +907,8 @@ Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars ) clk = clock(); if ( pPars->fSynthesis ) { -// vAigs = Dar_ManChoiceSynthesis( pMan, 1, 1, pPars->fVerbose ); - vAigs = Dar_ManChoiceSynthesis( pMan, 1, 1, 0 ); +// vAigs = Dar_ManChoiceSynthesis( pMan, 1, 1, pPars->fPower, pPars->fVerbose ); + vAigs = Dar_ManChoiceSynthesis( pMan, 1, 1, pPars->fPower, 0 ); Aig_ManStop( pMan ); } else @@ -1180,6 +1242,81 @@ PRT( "Time", clock() - clkTotal ); return RetValue; } +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDarCec2( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Cec_ParCec_t * pPars ) +{ + Aig_Man_t * pMan1, * pMan2 = NULL; + int RetValue, clkTotal = clock(); + if ( pNtk2 ) + { + if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) ) + { + printf( "Networks have different number of PIs.\n" ); + return -1; + } + if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) ) + { + printf( "Networks have different number of POs.\n" ); + return -1; + } + } + if ( pNtk1 ) + { + pMan1 = Abc_NtkToDar( pNtk1, 0, 0 ); + if ( pMan1 == NULL ) + { + printf( "Converting into AIG has failed.\n" ); + return -1; + } + } + if ( pNtk2 ) + { + pMan2 = Abc_NtkToDar( pNtk2, 0, 0 ); + if ( pMan2 == NULL ) + { + Aig_ManStop( pMan1 ); + printf( "Converting into AIG has failed.\n" ); + return -1; + } + } + // perform verification + RetValue = Cec_Solve( pMan1, pMan2, pPars ); + // transfer model if given + pNtk1->pModel = pMan1->pData, pMan1->pData = NULL; + Aig_ManStop( pMan1 ); + if ( pMan2 ) + Aig_ManStop( pMan2 ); + + // report the miter + if ( RetValue == 1 ) + { + printf( "Networks are equivalent. " ); +PRT( "Time", clock() - clkTotal ); + } + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT. " ); +PRT( "Time", clock() - clkTotal ); + } + else + { + printf( "Networks are UNDECIDED. " ); +PRT( "Time", clock() - clkTotal ); + } + fflush( stdout ); + return RetValue; +} + /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] @@ -1282,7 +1419,7 @@ void Abc_NtkPrintLatchEquivClasses( Abc_Ntk_t * pNtk, Aig_Man_t * pAig ) if ( pRepr == NULL ) { // printf("Nothing equivalent to flop %s\n", pFlopName); - p_irrelevant[i] = true; +// p_irrelevant[i] = true; continue; } @@ -1600,7 +1737,7 @@ PRT( "Time", clock() - clk ); ***********************************************************************/ int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk ) { - Aig_Man_t * pMan, * pPart0, * pPart1, * pMiter; + Aig_Man_t * pMan, * pPart0, * pPart1;//, * pMiter; // derive the AIG manager pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) @@ -1608,7 +1745,8 @@ int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk ) printf( "Converting network into AIG has failed.\n" ); return 0; } - if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) ) +// if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) ) + if ( !Saig_ManDemiterSimpleDiff( pMan, &pPart0, &pPart1 ) ) { printf( "Demitering has failed.\n" ); return 0; @@ -1617,10 +1755,10 @@ int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk ) Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" ); // create two-level miter - pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 ); - Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL ); - Aig_ManStop( pMiter ); - printf( "The new miter is written into file \"%s\".\n", "miter01.blif" ); +// pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 ); +// Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL ); +// Aig_ManStop( pMiter ); +// printf( "The new miter is written into file \"%s\".\n", "miter01.blif" ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); @@ -1761,7 +1899,7 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * pSecPar ) return 1; } - // commented out because something became non-inductive + // commented out because sometimes the problem became non-inductive /* // preprocess the miter by fraiging it // (note that for each functional class, fraiging leaves one representative; @@ -1805,6 +1943,146 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * pSecPar ) return RetValue; } + +/**Function************************************************************* + + Synopsis [Performs BDD-based reachability analysis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDarAbSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fVerbose ) +{ + Aig_Man_t * pMan1, * pMan2 = NULL; + int RetValue; + // derive AIG manager + pMan1 = Abc_NtkToDar( pNtk1, 0, 1 ); + if ( pMan1 == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return -1; + } + assert( Aig_ManRegNum(pMan1) > 0 ); + // derive AIG manager + if ( pNtk2 ) + { + pMan2 = Abc_NtkToDar( pNtk2, 0, 1 ); + if ( pMan2 == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return -1; + } + assert( Aig_ManRegNum(pMan2) > 0 ); + } + + // perform verification + RetValue = Ssw_SecSpecialMiter( pMan1, pMan2, nFrames, fVerbose ); + Aig_ManStop( pMan1 ); + if ( pMan2 ) + Aig_ManStop( pMan2 ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDarSimSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Ssw_Pars_t * pPars ) +{ + Aig_Man_t * pMan1, * pMan2 = NULL; + int RetValue; + // derive AIG manager + pMan1 = Abc_NtkToDar( pNtk1, 0, 1 ); + if ( pMan1 == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return -1; + } + assert( Aig_ManRegNum(pMan1) > 0 ); + // derive AIG manager + if ( pNtk2 ) + { + pMan2 = Abc_NtkToDar( pNtk2, 0, 1 ); + if ( pMan2 == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return -1; + } + assert( Aig_ManRegNum(pMan2) > 0 ); + } + + // perform verification + RetValue = Ssw_SecWithSimilarity( pMan1, pMan2, pPars ); + Aig_ManStop( pMan1 ); + if ( pMan2 ) + Aig_ManStop( pMan2 ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarMatch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nDist, int fVerbose ) +{ + extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ); + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan1, * pMan2 = NULL, * pManRes; + Vec_Int_t * vPairs; + assert( Abc_NtkIsStrash(pNtk1) ); + // derive AIG manager + pMan1 = Abc_NtkToDar( pNtk1, 0, 1 ); + if ( pMan1 == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return NULL; + } + assert( Aig_ManRegNum(pMan1) > 0 ); + // derive AIG manager + if ( pNtk2 ) + { + pMan2 = Abc_NtkToDar( pNtk2, 0, 1 ); + if ( pMan2 == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return NULL; + } + assert( Aig_ManRegNum(pMan2) > 0 ); + } + + // perform verification + vPairs = Saig_StrSimPerformMatching( pMan1, pMan2, nDist, 1, &pManRes ); + pNtkAig = Abc_NtkFromAigPhase( pManRes ); + if ( vPairs ) + Vec_IntFree( vPairs ); + if ( pManRes ) + Aig_ManStop( pManRes ); + Aig_ManStop( pMan1 ); + if ( pMan2 ) + Aig_ManStop( pMan2 ); + return pNtkAig; +} + + /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] @@ -2049,33 +2327,140 @@ Abc_Ntk_t * Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk, int nIters, int nSteps, int SeeAlso [] ***********************************************************************/ -int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose ) +int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fComb, int fMiter, int fVerbose ) { + extern int Cec_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose ); + extern int Raig_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose ); Aig_Man_t * pMan; - Fra_Sml_t * pSml; Fra_Cex_t * pCex; - int RetValue, clk = clock(); + int status, RetValue, clk = clock(); pMan = Abc_NtkToDar( pNtk, 0, 1 ); - pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords ); - if ( pSml->fNonConstOut ) + if ( fComb || Abc_NtkLatchNum(pNtk) == 0 ) { - pCex = Fra_SmlGetCounterExample( pSml ); - if ( pCex ) - printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ", + if ( Cec_ManSimulate( pMan, nWords, nFrames, TimeOut, fMiter, fVerbose ) ) + { + pCex = pMan->pSeqModel; + if ( pCex ) + { + printf( "Simulation iterated %d times with %d words asserted output %d in frame %d. ", nFrames, nWords, pCex->iPo, pCex->iFrame ); - FREE( pNtk->pModel ); - FREE( pNtk->pSeqModel ); - pNtk->pSeqModel = pCex; - RetValue = 1; + status = Ssw_SmlRunCounterExample( pMan, (Ssw_Cex_t *)pCex ); + if ( status == 0 ) + printf( "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" ); + } + FREE( pNtk->pModel ); + FREE( pNtk->pSeqModel ); + pNtk->pSeqModel = pCex; + RetValue = 1; + } + else + { + RetValue = 0; + printf( "Simulation iterated %d times with %d words did not assert the outputs. ", + nFrames, nWords ); + } + } + else if ( fNew ) + { +/* + if ( Raig_ManSimulate( pMan, nWords, nFrames, TimeOut, fVerbose ) ) + { + if ( (pCex = pMan->pSeqModel) ) + { + printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ", + nFrames, nWords, pCex->iPo, pCex->iFrame ); + status = Ssw_SmlRunCounterExample( pMan, (Ssw_Cex_t *)pCex ); + if ( status == 0 ) + printf( "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" ); + } + FREE( pNtk->pModel ); + FREE( pNtk->pSeqModel ); + pNtk->pSeqModel = pCex; pMan->pSeqModel = NULL; + RetValue = 1; + } + else + { + RetValue = 0; + printf( "Simulation of %d frames with %d words did not assert the outputs. ", + nFrames, nWords ); + } +*/ + Fsim_ParSim_t Pars, * pPars = &Pars; + Fsim_ManSetDefaultParamsSim( pPars ); + pPars->nWords = nWords; + pPars->nIters = nFrames; + pPars->TimeLimit = TimeOut; + pPars->fCheckMiter = fMiter; + pPars->fVerbose = fVerbose; + if ( Fsim_ManSimulate( pMan, pPars ) ) + { + if ( (pCex = pMan->pSeqModel) ) + { + printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ", + nFrames, nWords, pCex->iPo, pCex->iFrame ); + status = Ssw_SmlRunCounterExample( pMan, (Ssw_Cex_t *)pCex ); + if ( status == 0 ) + printf( "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" ); + } + FREE( pNtk->pModel ); + FREE( pNtk->pSeqModel ); + pNtk->pSeqModel = pCex; pMan->pSeqModel = NULL; + RetValue = 1; + } + else + { + RetValue = 0; + printf( "Simulation of %d frames with %d words did not assert the outputs. ", + nFrames, nWords ); + } } else { - RetValue = 0; - printf( "Simulation of %d frames with %d words did not assert the outputs. ", - nFrames, nWords ); +/* + Fra_Sml_t * pSml; + pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords ); + if ( pSml->fNonConstOut ) + { + pCex = Fra_SmlGetCounterExample( pSml ); + if ( pCex ) + printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ", + nFrames, nWords, pCex->iPo, pCex->iFrame ); + FREE( pNtk->pModel ); + FREE( pNtk->pSeqModel ); + pNtk->pSeqModel = pCex; + RetValue = 1; + } + else + { + RetValue = 0; + printf( "Simulation of %d frames with %d words did not assert the outputs. ", + nFrames, nWords ); + } + Fra_SmlStop( pSml ); +*/ + if ( Raig_ManSimulate( pMan, nWords, nFrames, TimeOut, fMiter, fVerbose ) ) + { + if ( (pCex = pMan->pSeqModel) ) + { + printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ", + nFrames, nWords, pCex->iPo, pCex->iFrame ); + status = Ssw_SmlRunCounterExample( pMan, (Ssw_Cex_t *)pCex ); + if ( status == 0 ) + printf( "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" ); + } + FREE( pNtk->pModel ); + FREE( pNtk->pSeqModel ); + pNtk->pSeqModel = pCex; pMan->pSeqModel = NULL; + RetValue = 1; + } + else + { + RetValue = 0; + printf( "Simulation of %d frames with %d words did not assert the outputs. ", + nFrames, nWords ); + } } PRT( "Time", clock() - clk ); - Fra_SmlStop( pSml ); Aig_ManStop( pMan ); return RetValue; } @@ -2200,14 +2585,20 @@ Abc_Ntk_t * Abc_NtkDarPBAbstraction( Abc_Ntk_t * pNtk, int nFramesMax, int nConf return NULL; Aig_ManSetRegNum( pMan, pMan->nRegs ); - pMan = Saig_ManProofAbstraction( pTemp = pMan, nFramesMax, nConfMax, fDynamic, fExtend, fVerbose ); + pMan = Saig_ManProofAbstraction( pTemp = pMan, nFramesMax, nConfMax, fDynamic, fExtend, 0, fVerbose ); + if ( pTemp->pSeqModel ) + { + FREE( pNtk->pModel ); + FREE( pNtk->pSeqModel ); + pNtk->pSeqModel = pTemp->pSeqModel; pTemp->pSeqModel = NULL; + } Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); - pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); - pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); +// pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); +// pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Aig_ManStop( pMan ); return pNtkAig; } @@ -2480,8 +2871,8 @@ Abc_Ntk_t * Abc_NtkPhaseAbstract( Abc_Ntk_t * pNtk, int nFrames, int fIgnore, in if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); - pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); - pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); +// pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); +// pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Aig_ManStop( pMan ); return pNtkAig; } @@ -2545,8 +2936,8 @@ Abc_Ntk_t * Abc_NtkDarSynch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nWords, i if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); - pNtkAig->pName = Extra_UtilStrsav("miter"); - pNtkAig->pSpec = NULL; +// pNtkAig->pName = Extra_UtilStrsav("miter"); +// pNtkAig->pSpec = NULL; Aig_ManStop( pMan ); return pNtkAig; } @@ -2589,6 +2980,129 @@ Abc_Ntk_t * Abc_NtkDarClockGate( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, Cgt_Par_t return pNtkAig; } +/**Function************************************************************* + + Synopsis [Performs phase abstraction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarExtWin( Abc_Ntk_t * pNtk, int nObjId, int nDist, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan1, * pMan; + Aig_Obj_t * pObj; + pMan1 = Abc_NtkToDar( pNtk, 0, 1 ); + if ( pMan1 == NULL ) + return NULL; + if ( nObjId == -1 ) + { + pObj = Saig_ManFindPivot( pMan1 ); + printf( "Selected object %d as a window pivot.\n", pObj->Id ); + } + else + { + if ( nObjId >= Aig_ManObjNumMax(pMan1) ) + { + Aig_ManStop( pMan1 ); + printf( "The ID is too large.\n" ); + return NULL; + } + pObj = Aig_ManObj( pMan1, nObjId ); + if ( pObj == NULL ) + { + Aig_ManStop( pMan1 ); + printf( "Object with ID %d does not exist.\n", nObjId ); + return NULL; + } + if ( !Saig_ObjIsLo(pMan1, pObj) && !Aig_ObjIsNode(pObj) ) + { + Aig_ManStop( pMan1 ); + printf( "Object with ID %d is not a node or reg output.\n", nObjId ); + return NULL; + } + } + pMan = Saig_ManWindowExtract( pMan1, pObj, nDist ); + Aig_ManStop( pMan1 ); + if ( pMan == NULL ) + return NULL; + pNtkAig = Abc_NtkFromAigPhase( pMan ); + pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); + pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Performs phase abstraction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarInsWin( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, int nObjId, int nDist, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan1, * pMan2 = NULL, * pMan; + Aig_Obj_t * pObj; + pMan1 = Abc_NtkToDar( pNtk, 0, 1 ); + if ( pMan1 == NULL ) + return NULL; + if ( nObjId == -1 ) + { + pObj = Saig_ManFindPivot( pMan1 ); + printf( "Selected object %d as a window pivot.\n", pObj->Id ); + } + else + { + if ( nObjId >= Aig_ManObjNumMax(pMan1) ) + { + Aig_ManStop( pMan1 ); + printf( "The ID is too large.\n" ); + return NULL; + } + pObj = Aig_ManObj( pMan1, nObjId ); + if ( pObj == NULL ) + { + Aig_ManStop( pMan1 ); + printf( "Object with ID %d does not exist.\n", nObjId ); + return NULL; + } + if ( !Saig_ObjIsLo(pMan1, pObj) && !Aig_ObjIsNode(pObj) ) + { + Aig_ManStop( pMan1 ); + printf( "Object with ID %d is not a node or reg output.\n", nObjId ); + return NULL; + } + } + if ( pCare ) + { + pMan2 = Abc_NtkToDar( pCare, 0, 0 ); + if ( pMan2 == NULL ) + { + Aig_ManStop( pMan1 ); + return NULL; + } + } + pMan = Saig_ManWindowInsert( pMan1, pObj, nDist, pMan2 ); + Aig_ManStop( pMan1 ); + if ( pMan2 ) + Aig_ManStop( pMan2 ); + if ( pMan == NULL ) + return NULL; + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + /**Function************************************************************* Synopsis [Performs phase abstraction.] @@ -2680,6 +3194,112 @@ void Abc_NtkDarReach( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fPartitio Aig_ManStop( pMan ); } +#include "amap.h" +#include "mio.h" + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Amap_ManProduceNetwork( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapping ) +{ + extern void * Abc_FrameReadLibGen(); + Mio_Library_t * pLib = Abc_FrameReadLibGen(); + Amap_Out_t * pRes; + Vec_Ptr_t * vNodesNew; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNodeNew, * pFaninNew; + int i, k, iPis, iPos, nDupGates; + // make sure gates exist in the current library + Vec_PtrForEachEntry( vMapping, pRes, i ) + if ( pRes->pName && Mio_LibraryReadGateByName( pLib, pRes->pName ) == NULL ) + { + printf( "Current library does not contain gate \"%s\".\n", pRes->pName ); + return NULL; + } + // create the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP ); + pNtkNew->pManFunc = pLib; + iPis = iPos = 0; + vNodesNew = Vec_PtrAlloc( Vec_PtrSize(vMapping) ); + Vec_PtrForEachEntry( vMapping, pRes, i ) + { + if ( pRes->Type == -1 ) + pNodeNew = Abc_NtkCi( pNtkNew, iPis++ ); + else if ( pRes->Type == 1 ) + pNodeNew = Abc_NtkCo( pNtkNew, iPos++ ); + else + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Mio_LibraryReadGateByName( pLib, pRes->pName ); + } + for ( k = 0; k < pRes->nFans; k++ ) + { + pFaninNew = Vec_PtrEntry( vNodesNew, pRes->pFans[k] ); + Abc_ObjAddFanin( pNodeNew, pFaninNew ); + } + Vec_PtrPush( vNodesNew, pNodeNew ); + } + Vec_PtrFree( vNodesNew ); + assert( iPis == Abc_NtkCiNum(pNtkNew) ); + assert( iPos == Abc_NtkCoNum(pNtkNew) ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && Map_ManReadVerbose(pMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars ) +{ + Vec_Ptr_t * vMapping; + Abc_Ntk_t * pNtkAig = NULL; + Aig_Man_t * pMan; + Aig_MmFlex_t * pMem; + + assert( Abc_NtkIsStrash(pNtk) ); + // convert to the AIG manager + pMan = Abc_NtkToDarChoices( pNtk ); + if ( pMan == NULL ) + return NULL; + + // perform computation + vMapping = Amap_ManTest( pMan, pPars ); + Aig_ManStop( pMan ); + if ( vMapping == NULL ) + return NULL; + pMem = Vec_PtrPop( vMapping ); + pNtkAig = Amap_ManProduceNetwork( pNtk, vMapping ); + Aig_MmFlexStop( pMem, 0 ); + Vec_PtrFree( vMapping ); + + // make sure everything is okay + if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkDar: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} /**Function************************************************************* @@ -2694,9 +3314,10 @@ void Abc_NtkDarReach( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fPartitio ***********************************************************************/ void Abc_NtkDarTest( Abc_Ntk_t * pNtk ) { -// extern Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig ); - - Aig_Man_t * pMan;//, * pTemp; + extern void Fsim_ManTest( Aig_Man_t * pAig ); + extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ); +// Vec_Int_t * vPairs; + Aig_Man_t * pMan;//, * pMan2;//, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) @@ -2714,9 +3335,21 @@ Aig_ManPrintStats( pMan ); pTemp = Ssw_SignalCorrespondeceTestPairs( pMan ); Aig_ManStop( pTemp ); */ - Ssw_SecSpecialMiter( pMan, 1 ); +/* +// Ssw_SecSpecialMiter( pMan, NULL, 2, 1 ); + pMan2 = Aig_ManDupSimple(pMan); + vPairs = Saig_StrSimPerformMatching( pMan, pMan2, 0, 1, NULL ); + Vec_IntFree( vPairs ); Aig_ManStop( pMan ); + Aig_ManStop( pMan2 ); +*/ + +// Saig_MvManSimulate( pMan, 1 ); + + Fsim_ManTest( pMan ); + Aig_ManStop( pMan ); + } /**Function************************************************************* @@ -2732,6 +3365,8 @@ Aig_ManPrintStats( pMan ); ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk ) { + extern Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ); + /* extern Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig ); @@ -2760,9 +3395,16 @@ Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk ) pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; +/* + Aig_ManSetRegNum( pMan, pMan->nRegs ); + pMan = Saig_ManProofAbstraction( pTemp = pMan, 5, 10000, 0, 0, 0, 1 ); + Aig_ManStop( pTemp ); + if ( pMan == NULL ) + return NULL; +*/ Aig_ManSetRegNum( pMan, pMan->nRegs ); - pMan = Saig_ManProofAbstraction( pTemp = pMan, 5, 10000, 0, 0, 1 ); + pMan = Saig_ManDualRail( pTemp = pMan, 1 ); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; diff --git a/src/base/abci/abcDelay.c b/src/base/abci/abcDelay.c index 91f175fa..847c7f1b 100644 --- a/src/base/abci/abcDelay.c +++ b/src/base/abci/abcDelay.c @@ -20,6 +20,7 @@ #include "abc.h" #include "if.h" +#include "aig.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -652,6 +653,302 @@ Abc_Ntk_t * Abc_NtkSpeedup( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, in return pNtkNew; } +/**Function************************************************************* + + Synopsis [Marks nodes for power-optimization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vProbs; + Vec_Int_t * vSwitching; + float * pProbability; + float * pSwitching; + Abc_Ntk_t * pNtkStr; + Aig_Man_t * pAig; + Aig_Obj_t * pObjAig; + Abc_Obj_t * pObjAbc, * pObjAbc2; + int i; + // start the resulting array + vProbs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + pProbability = (float *)vProbs->pArray; + // strash the network + pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkForEachObj( pNtk, pObjAbc, i ) + if ( Abc_ObjRegular(pObjAbc->pTemp)->Type == ABC_FUNC_NONE ) + pObjAbc->pTemp = NULL; + // map network into an AIG + pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) ); + vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, fProbOne ); + pSwitching = (float *)vSwitching->pArray; + Abc_NtkForEachObj( pNtk, pObjAbc, i ) + { + if ( (pObjAbc2 = Abc_ObjRegular(pObjAbc->pTemp)) && (pObjAig = pObjAbc2->pTemp) ) + pProbability[pObjAbc->Id] = pSwitching[pObjAig->Id]; + } + Vec_IntFree( vSwitching ); + Aig_ManStop( pAig ); + Abc_NtkDelete( pNtkStr ); + return vProbs; +} + +/**Function************************************************************* + + Synopsis [Marks nodes for power-optimization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPowerPrint( Abc_Ntk_t * pNtk, Vec_Int_t * vProbs ) +{ + Abc_Obj_t * pObj; + float * pProb, TotalProb = 0.0, ProbThis, Probs[5] = {0.0}; + int i, nNodes = 0, nEdges = 0, Counter[5] = {0}; + pProb = (float *)vProbs->pArray; + assert( Vec_IntSize(vProbs) >= Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPi(pObj) ) + continue; + nNodes++; + nEdges += Abc_ObjFanoutNum(pObj); + ProbThis = pProb[i] * Abc_ObjFanoutNum(pObj); + TotalProb += ProbThis; + assert( pProb[i] >= 0.0 && pProb[i] <= 0.5 ); + if ( pProb[i] >= 0.4 ) + { + Counter[4]++; + Probs[4] += ProbThis; + } + else if ( pProb[i] >= 0.3 ) + { + Counter[3]++; + Probs[3] += ProbThis; + } + else if ( pProb[i] >= 0.2 ) + { + Counter[2]++; + Probs[2] += ProbThis; + } + else if ( pProb[i] >= 0.1 ) + { + Counter[1]++; + Probs[1] += ProbThis; + } + else + { + Counter[0]++; + Probs[0] += ProbThis; + } + } + printf( "Node distribution: " ); + for ( i = 0; i < 5; i++ ) + printf( "n%d%d = %6.2f%% ", i, i+1, 100.0 * Counter[i]/nNodes ); + printf( "\n" ); + printf( "Power distribution: " ); + for ( i = 0; i < 5; i++ ) + printf( "p%d%d = %6.2f%% ", i, i+1, 100.0 * Probs[i]/TotalProb ); + printf( "\n" ); + printf( "Total probs = %7.2f. ", TotalProb ); + printf( "Total edges = %d. ", nEdges ); + printf( "Average = %7.2f. ", TotalProb / nEdges ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Determines timing-critical edges of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Abc_NtkPowerCriticalEdges( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, float Limit, Vec_Int_t * vProbs ) +{ + Abc_Obj_t * pFanin; + float * pProb = (float *)vProbs->pArray; + unsigned uResult = 0; + int k; + Abc_ObjForEachFanin( pNode, pFanin, k ) + if ( pProb[pFanin->Id] >= Limit ) + uResult |= (1 << k); + return uResult; +} + +/**Function************************************************************* + + Synopsis [Adds choices to speed up the network by the given percentage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Int_t * vProbs; + Vec_Ptr_t * vTimeCries, * vTimeFanins; + Abc_Obj_t * pNode, * pFanin, * pFanin2; + float * pProb, Limit; + int i, k, k2, Counter, CounterRes, nTimeCris; + unsigned * puPCEdges; + // compute the limit + Limit = 0.5 - (1.0 * Percentage / 100); + // perform computation of switching probability + vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); + pProb = (float *)vProbs->pArray; + // compute percentage of wires of each type + if ( fVerbose ) + Abc_NtkPowerPrint( pNtk, vProbs ); + // mark the power critical nodes and edges + puPCEdges = ALLOC( unsigned, Abc_NtkObjNumMax(pNtk) ); + memset( puPCEdges, 0, sizeof(unsigned) * Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( pProb[pNode->Id] < Limit ) + continue; + puPCEdges[pNode->Id] = Abc_NtkPowerCriticalEdges( pNtk, pNode, Limit, vProbs ); + } +/* + if ( fVerbose ) + { + Counter = CounterRes = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Counter += Abc_ObjFaninNum(pNode); + CounterRes += Extra_WordCountOnes( puPCEdges[pNode->Id] ); + } + printf( "Edges: Total = %7d. Critical = %7d. Ratio = %4.2f\n", + Counter, CounterRes, 1.0*CounterRes/Counter ); + } +*/ + // start the resulting network + pNtkNew = Abc_NtkStrash( pNtk, 0, 1, 0 ); + + // collect nodes to be used for resynthesis + Counter = CounterRes = 0; + vTimeCries = Vec_PtrAlloc( 16 ); + vTimeFanins = Vec_PtrAlloc( 16 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { +// if ( pProb[pNode->Id] < Limit ) +// continue; + // count the number of non-PI power-critical nodes + nTimeCris = 0; + Abc_ObjForEachFanin( pNode, pFanin, k ) + if ( !Abc_ObjIsCi(pFanin) && (puPCEdges[pNode->Id] & (1<Id] & (1<Id] & (1< Degree) ) + if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) ) + continue; + CounterRes++; + // collect second generation nodes + Vec_PtrClear( vTimeFanins ); + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + if ( Abc_ObjIsCi(pFanin) ) + Vec_PtrPushUnique( vTimeFanins, pFanin ); + else + Abc_ObjForEachFanin( pFanin, pFanin2, k2 ) + Vec_PtrPushUnique( vTimeFanins, pFanin2 ); + } + // print the results + if ( fVeryVerbose ) + { + printf( "%5d Node %5d : %d %2d %2d ", Counter, pNode->Id, + nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) ); + Abc_ObjForEachFanin( pNode, pFanin, k ) + printf( "%d(%.2f)%s ", pFanin->Id, pProb[pFanin->Id], (puPCEdges[pNode->Id] & (1< Degree ) + continue; + // order the fanins in the increasing order of criticalily + if ( Vec_PtrSize(vTimeCries) > 1 ) + { + pFanin = Vec_PtrEntry( vTimeCries, 0 ); + pFanin2 = Vec_PtrEntry( vTimeCries, 1 ); +// if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) + if ( pProb[pFanin->Id] > pProb[pFanin2->Id] ) + { + Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); + Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); + } + } + if ( Vec_PtrSize(vTimeCries) > 2 ) + { + pFanin = Vec_PtrEntry( vTimeCries, 1 ); + pFanin2 = Vec_PtrEntry( vTimeCries, 2 ); +// if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) + if ( pProb[pFanin->Id] > pProb[pFanin2->Id] ) + { + Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 ); + Vec_PtrWriteEntry( vTimeCries, 2, pFanin ); + } + pFanin = Vec_PtrEntry( vTimeCries, 0 ); + pFanin2 = Vec_PtrEntry( vTimeCries, 1 ); +// if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) + if ( pProb[pFanin->Id] > pProb[pFanin2->Id] ) + { + Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); + Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); + } + } + // add choice + Abc_NtkSpeedupNode( pNtk, pNtkNew, pNode, vTimeFanins, vTimeCries ); + } + Vec_PtrFree( vTimeCries ); + Vec_PtrFree( vTimeFanins ); + free( puPCEdges ); + if ( fVerbose ) + printf( "Nodes: Total = %7d. Power-critical = %7d. Workable = %7d. Ratio = %4.2f\n", + Abc_NtkNodeNum(pNtk), Counter, CounterRes, 1.0*CounterRes/Counter ); + + // remove invalid choice nodes + Abc_AigForEachAnd( pNtkNew, pNode, i ) + if ( pNode->pData ) + { + if ( Abc_ObjFanoutNum(pNode->pData) > 0 ) + pNode->pData = NULL; + } + + // return the result + Vec_IntFree( vProbs ); + return pNtkNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 751e2b2f..c5d9ada7 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -40,6 +40,59 @@ extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkIfComputeSwitching( Abc_Ntk_t * pNtk, If_Man_t * pIfMan ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vSwitching; + float * pSwitching; + Abc_Obj_t * pObjAbc; + Aig_Obj_t * pObjAig; + Aig_Man_t * pAig; + If_Obj_t * pObjIf; + int i, clk = clock(); + // map IF objects into old network + Abc_NtkForEachObj( pNtk, pObjAbc, i ) + if ( (pObjIf = pObjAbc->pTemp) ) + pObjIf->pCopy = pObjAbc; + // map network into an AIG + pAig = Abc_NtkToDar( pNtk, 0, 0 ); + vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 ); + pSwitching = (float *)vSwitching->pArray; + Abc_NtkForEachObj( pNtk, pObjAbc, i ) + if ( (pObjAig = pObjAbc->pTemp) ) + { + pObjAbc->dTemp = pSwitching[pObjAig->Id]; + // J. Anderson and F. N. Najm, “Power-Aware Technology Mapping for LUT-Based FPGAs,” + // IEEE Intl. Conf. on Field-Programmable Technology, 2002. +// pObjAbc->dTemp = (1.55 + 1.05 / (float) Abc_ObjFanoutNum(pObjAbc)) * pSwitching[pObjAig->Id]; + } + Vec_IntFree( vSwitching ); + Aig_ManStop( pAig ); + // compute switching for the IF objects + assert( pIfMan->vSwitching == NULL ); + pIfMan->vSwitching = Vec_IntStart( If_ManObjNum(pIfMan) ); + pSwitching = (float *)pIfMan->vSwitching->pArray; + If_ManForEachObj( pIfMan, pObjIf, i ) + if ( (pObjAbc = pObjIf->pCopy) ) + pSwitching[i] = pObjAbc->dTemp; +if ( pIfMan->pPars->fVerbose ) +{ + PRT( "Computing switching activity", clock() - clk ); +} +} + /**Function************************************************************* Synopsis [Interface with the FPGA mapping package.] @@ -74,6 +127,8 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) pIfMan = Abc_NtkToIf( pNtk, pPars ); if ( pIfMan == NULL ) return NULL; + if ( pPars->fPower ) + Abc_NtkIfComputeSwitching( pNtk, pIfMan ); if ( !If_ManPerformMapping( pIfMan ) ) { If_ManStop( pIfMan ); @@ -133,6 +188,7 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) ); // create PIs and remember them in the old nodes + Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan ); Abc_NtkForEachCi( pNtk, pNode, i ) { @@ -165,7 +221,7 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) // set the primary outputs without copying the phase Abc_NtkForEachCo( pNtk, pNode, i ) - If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); + pNode->pCopy = (Abc_Obj_t *)If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); return pIfMan; } diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c index d0bce990..3a454fc0 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -61,7 +61,7 @@ Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int Map_Man_t * pMan; Vec_Int_t * vSwitching = NULL; float * pSwitching = NULL; - int clk; + int clk, clkTotal = clock(); assert( Abc_NtkIsStrash(pNtk) ); @@ -115,6 +115,10 @@ clk = clock(); if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); +if ( fVerbose ) +{ +PRT( "Total runtime", clock() - clkTotal ); +} // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) diff --git a/src/base/abci/abcMerge.c b/src/base/abci/abcMerge.c new file mode 100644 index 00000000..25a4f02e --- /dev/null +++ b/src/base/abci/abcMerge.c @@ -0,0 +1,352 @@ +/**CFile**************************************************************** + + FileName [abcMerge.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [LUT merging algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "aig.h" +#include "nwkMerge.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Marks the fanins of the node with the current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMarkFanins_rec( Abc_Obj_t * pLut, int nLevMin ) +{ + Abc_Obj_t * pNext; + int i; + if ( !Abc_ObjIsNode(pLut) ) + return; + if ( Abc_NodeIsTravIdCurrent( pLut ) ) + return; + Abc_NodeSetTravIdCurrent( pLut ); + if ( Abc_ObjLevel(pLut) < nLevMin ) + return; + Abc_ObjForEachFanin( pLut, pNext, i ) + Abc_NtkMarkFanins_rec( pNext, nLevMin ); +} + +/**Function************************************************************* + + Synopsis [Marks the fanouts of the node with the current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMarkFanouts_rec( Abc_Obj_t * pLut, int nLevMax, int nFanMax ) +{ + Abc_Obj_t * pNext; + int i; + if ( !Abc_ObjIsNode(pLut) ) + return; + if ( Abc_NodeIsTravIdCurrent( pLut ) ) + return; + Abc_NodeSetTravIdCurrent( pLut ); + if ( Abc_ObjLevel(pLut) > nLevMax ) + return; + if ( Abc_ObjFanoutNum(pLut) > nFanMax ) + return; + Abc_ObjForEachFanout( pLut, pNext, i ) + Abc_NtkMarkFanouts_rec( pNext, nLevMax, nFanMax ); +} + +/**Function************************************************************* + + Synopsis [Collects the circle of nodes around the given set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k; + Vec_PtrClear( vNext ); + Vec_PtrForEachEntry( vStart, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pNext, k ) + { + if ( !Abc_ObjIsNode(pNext) ) + continue; + if ( Abc_NodeIsTravIdCurrent( pNext ) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vNext, pNext ); + } + Abc_ObjForEachFanout( pObj, pNext, k ) + { + if ( !Abc_ObjIsNode(pNext) ) + continue; + if ( Abc_NodeIsTravIdCurrent( pNext ) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + if ( Abc_ObjFanoutNum(pNext) > nFanMax ) + continue; + Vec_PtrPush( vNext, pNext ); + } + } +} + +/**Function************************************************************* + + Synopsis [Collects the circle of nodes removes from the given one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectNonOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) +{ + Vec_Ptr_t * vTemp; + Abc_Obj_t * pObj; + int i, k; + Vec_PtrClear( vCands ); + if ( pPars->nMaxSuppSize - Abc_ObjFaninNum(pLut) <= 1 ) + return; + + // collect nodes removed by this distance + assert( pPars->nMaxDistance > 0 ); + Vec_PtrClear( vStart ); + Vec_PtrPush( vStart, pLut ); + Abc_NtkIncrementTravId( pLut->pNtk ); + Abc_NodeSetTravIdCurrent( pLut ); + for ( i = 1; i <= pPars->nMaxDistance; i++ ) + { + Abc_NtkCollectCircle( vStart, vNext, pPars->nMaxFanout ); + vTemp = vStart; + vStart = vNext; + vNext = vTemp; + // collect the nodes in vStart + Vec_PtrForEachEntry( vStart, pObj, k ) + Vec_PtrPush( vCands, pObj ); + } + + // mark the TFI/TFO nodes + Abc_NtkIncrementTravId( pLut->pNtk ); + if ( pPars->fUseTfiTfo ) + Abc_NodeSetTravIdCurrent( pLut ); + else + { + Abc_NodeSetTravIdPrevious( pLut ); + Abc_NtkMarkFanins_rec( pLut, Abc_ObjLevel(pLut) - pPars->nMaxDistance ); + Abc_NodeSetTravIdPrevious( pLut ); + Abc_NtkMarkFanouts_rec( pLut, Abc_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); + } + + // collect nodes satisfying the following conditions: + // - they are close enough in terms of distance + // - they are not in the TFI/TFO of the LUT + // - they have no more than the given number of fanins + // - they have no more than the given diff in delay + k = 0; + Vec_PtrForEachEntry( vCands, pObj, i ) + { + if ( Abc_NodeIsTravIdCurrent(pObj) ) + continue; + if ( Abc_ObjFaninNum(pLut) + Abc_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) + continue; + if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || + Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) + continue; + Vec_PtrWriteEntry( vCands, k++, pObj ); + } + Vec_PtrShrink( vCands, k ); +} + + +/**Function************************************************************* + + Synopsis [Count the total number of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountTotalFanins( Abc_Obj_t * pLut, Abc_Obj_t * pCand ) +{ + Abc_Obj_t * pFanin; + int i, nCounter = Abc_ObjFaninNum(pLut); + Abc_ObjForEachFanin( pCand, pFanin, i ) + nCounter += !pFanin->fMarkC; + return nCounter; +} + +/**Function************************************************************* + + Synopsis [Collects overlapping candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) +{ + Abc_Obj_t * pFanin, * pObj; + int i, k; + // mark fanins of pLut + Abc_ObjForEachFanin( pLut, pFanin, i ) + pFanin->fMarkC = 1; + // collect the matching fanouts of each fanin of the node + Vec_PtrClear( vCands ); + Abc_NtkIncrementTravId( pLut->pNtk ); + Abc_NodeSetTravIdCurrent( pLut ); + Abc_ObjForEachFanin( pLut, pFanin, i ) + { + if ( !Abc_ObjIsNode(pFanin) ) + continue; + if ( Abc_ObjFanoutNum(pFanin) > pPars->nMaxFanout ) + continue; + Abc_ObjForEachFanout( pFanin, pObj, k ) + { + if ( !Abc_ObjIsNode(pObj) ) + continue; + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + continue; + Abc_NodeSetTravIdCurrent( pObj ); + // check the difference in delay + if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || + Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) + continue; + // check the total number of fanins of the node + if ( Abc_NtkCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) + continue; + Vec_PtrPush( vCands, pObj ); + } + } + // unmark fanins of pLut + Abc_ObjForEachFanin( pLut, pFanin, i ) + pFanin->fMarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Performs LUT merging with parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars ) +{ + Nwk_Grf_t * p; + Vec_Int_t * vResult; + Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; + Abc_Obj_t * pLut, * pCand; + int i, k, nVertsMax, nCands, clk = clock(); + // count the number of vertices + nVertsMax = 0; + Abc_NtkForEachNode( pNtk, pLut, i ) + nVertsMax += (int)(Abc_ObjFaninNum(pLut) <= pPars->nMaxLutSize); + p = Nwk_ManGraphAlloc( nVertsMax ); + // create graph + vStart = Vec_PtrAlloc( 1000 ); + vNext = Vec_PtrAlloc( 1000 ); + vCands1 = Vec_PtrAlloc( 1000 ); + vCands2 = Vec_PtrAlloc( 1000 ); + nCands = 0; + Abc_NtkForEachNode( pNtk, pLut, i ) + { + if ( Abc_ObjFaninNum(pLut) > pPars->nMaxLutSize ) + continue; + Abc_NtkCollectOverlapCands( pLut, vCands1, pPars ); + if ( pPars->fUseDiffSupp ) + Abc_NtkCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); + if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) + continue; + nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2); + // save candidates + Vec_PtrForEachEntry( vCands1, pCand, k ) + Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); + Vec_PtrForEachEntry( vCands2, pCand, k ) + Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); + // print statistics about this node + if ( pPars->fVeryVerbose ) + printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", + Abc_ObjId(pLut), Abc_ObjFaninNum(pLut), Abc_ObjFaninNum(pLut), + Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); + } + Vec_PtrFree( vStart ); + Vec_PtrFree( vNext ); + Vec_PtrFree( vCands1 ); + Vec_PtrFree( vCands2 ); + if ( pPars->fVerbose ) + { + printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands ); + PRT( "Deriving graph", clock() - clk ); + } + // solve the graph problem + clk = clock(); + Nwk_ManGraphSolve( p ); + if ( pPars->fVerbose ) + { + printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", + p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); + PRT( "Solving", clock() - clk ); + Nwk_ManGraphReportMemoryUsage( p ); + } + vResult = p->vPairs; p->vPairs = NULL; +/* + for ( i = 0; i < vResult->nSize; i += 2 ) + printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); + printf( "\n" ); +*/ + Nwk_ManGraphFree( p ); + return vResult; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 23a44eb3..0b1d8fc1 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -22,7 +22,7 @@ #include "dec.h" #include "main.h" #include "mio.h" -//#include "seq.h" +#include "aig.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -100,6 +100,49 @@ int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk ) return 0; } +/**Function************************************************************* + + Synopsis [Marks nodes for power-optimization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vSwitching; + float * pSwitching; + Abc_Ntk_t * pNtkStr; + Aig_Man_t * pAig; + Aig_Obj_t * pObjAig; + Abc_Obj_t * pObjAbc, * pObjAbc2; + float Result = (float)0; + int i; + // strash the network + pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkForEachObj( pNtk, pObjAbc, i ) + if ( Abc_ObjRegular(pObjAbc->pTemp)->Type == ABC_FUNC_NONE ) + pObjAbc->pTemp = NULL; + // map network into an AIG + pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) ); + vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 ); + pSwitching = (float *)vSwitching->pArray; + Abc_NtkForEachObj( pNtk, pObjAbc, i ) + { + if ( (pObjAbc2 = Abc_ObjRegular(pObjAbc->pTemp)) && (pObjAig = pObjAbc2->pTemp) ) + Result += Abc_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id]; + } + Vec_IntFree( vSwitching ); + Aig_ManStop( pAig ); + Abc_NtkDelete( pNtkStr ); + return Result; +} + /**Function************************************************************* Synopsis [Print the vital stats of the network.] @@ -111,7 +154,7 @@ int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes ) +void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower ) { int Num; if ( fSaveBest ) @@ -192,6 +235,8 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSave fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) ); if ( fUseLutLib && Abc_FrameReadLibLut() ) fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTraceLut(pNtk, 1) ); + if ( fPower ) + fprintf( pFile, " power = %7.2f", Abc_NtkMfsTotalSwitching(pNtk) ); fprintf( pFile, "\n" ); // Abc_NtkCrossCut( pNtk ); @@ -898,32 +943,39 @@ void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ) if ( fUseLibrary && Abc_NtkHasMapping(pNtk) ) { - stmm_table * tTable; - stmm_generator * gen; - char * pName; - int * pCounter, Counter; + Mio_Gate_t ** ppGates; double Area, AreaTotal; + int Counter, nGates, i; + + // clean value of all gates + nGates = Mio_LibraryReadGateNum( pNtk->pManFunc ); + ppGates = Mio_LibraryReadGatesByName( pNtk->pManFunc ); + for ( i = 0; i < nGates; i++ ) + Mio_GateSetValue( ppGates[i], 0 ); // count the gates by name CounterTotal = 0; - tTable = stmm_init_table(strcmp, stmm_strhash); Abc_NtkForEachNode( pNtk, pObj, i ) { if ( i == 0 ) continue; - if ( !stmm_find_or_add( tTable, Mio_GateReadName(pObj->pData), (char ***)&pCounter ) ) - *pCounter = 0; - (*pCounter)++; + Mio_GateSetValue( pObj->pData, 1 + Mio_GateReadValue(pObj->pData) ); CounterTotal++; } // print the gates AreaTotal = Abc_NtkGetMappedArea(pNtk); - stmm_foreach_item( tTable, gen, (char **)&pName, (char **)&Counter ) + for ( i = 0; i < nGates; i++ ) { - Area = Counter * Mio_GateReadArea(Mio_LibraryReadGateByName(pNtk->pManFunc,pName)); - printf( "%-12s = %8d %10.2f %6.2f %%\n", pName, Counter, Area, 100.0 * Area / AreaTotal ); + Counter = Mio_GateReadValue( ppGates[i] ); + if ( Counter == 0 ) + continue; + Area = Counter * Mio_GateReadArea( ppGates[i] ); + printf( "%-12s Fanin = %2d Instance = %8d Area = %10.2f %6.2f %%\n", + Mio_GateReadName( ppGates[i] ), + Mio_GateReadInputs( ppGates[i] ), + Counter, Area, 100.0 * Area / AreaTotal ); } - printf( "%-12s = %8d %10.2f %6.2f %%\n", "TOTAL", CounterTotal, AreaTotal, 100.0 ); - stmm_free_table( tTable ); + printf( "%-12s Instance = %8d Area = %10.2f %6.2f %%\n", "TOTAL", + CounterTotal, AreaTotal, 100.0 ); return; } diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c index 463846b9..a7c9f609 100644 --- a/src/base/abci/abcStrash.c +++ b/src/base/abci/abcStrash.c @@ -316,7 +316,7 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ) ***********************************************************************/ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ) { - ProgressBar * pProgress; +// ProgressBar * pProgress; Vec_Ptr_t * vNodes; Abc_Obj_t * pNodeOld; int i; //, clk = clock(); @@ -326,13 +326,13 @@ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNod vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes ); //printf( "Nodes = %d. ", Vec_PtrSize(vNodes) ); //PRT( "Time", clock() - clk ); - pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); +// pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( vNodes, pNodeOld, i ) { - Extra_ProgressBarUpdate( pProgress, i, NULL ); +// Extra_ProgressBarUpdate( pProgress, i, NULL ); pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord ); } - Extra_ProgressBarStop( pProgress ); +// Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); } diff --git a/src/base/abci/module.make b/src/base/abci/module.make index e83785fe..c872d62e 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -25,6 +25,7 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcIvy.c \ src/base/abci/abcLut.c \ src/base/abci/abcMap.c \ + src/base/abci/abcMerge.c \ src/base/abci/abcMini.c \ src/base/abci/abcMiter.c \ src/base/abci/abcMulti.c \ diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 4e0a4c95..459d82c9 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -662,6 +662,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) } } + fflush( pAbc->Out ); status = Cmd_CommandExecute( pAbc, line ); } while ( status == 0 ); diff --git a/src/base/cmd/cmd.h b/src/base/cmd/cmd.h index 9d0b8703..143f57cd 100644 --- a/src/base/cmd/cmd.h +++ b/src/base/cmd/cmd.h @@ -41,14 +41,14 @@ typedef struct MvCommand Abc_Command; // one command typedef struct MvAlias Abc_Alias; // one alias #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/io.c b/src/base/io/io.c index 6f326a27..a8941868 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -48,6 +48,7 @@ static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBook ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ); @@ -102,6 +103,7 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_book", IoCommandWriteBook, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_counter", IoCommandWriteCounter, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 ); @@ -1477,6 +1479,49 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBook( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BOOK ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_book [-h] [-options]\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aux, .nodes, .nets)\n" ); + fprintf( pAbc->Err, "\t\n" ); + fprintf( pAbc->Err, "\tThis command is developed by Myungchul Kim (University of Michigan).\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h index e62cc168..842d8995 100644 --- a/src/base/io/ioAbc.h +++ b/src/base/io/ioAbc.h @@ -47,6 +47,7 @@ typedef enum { IO_FILE_BLIF, IO_FILE_BLIFMV, IO_FILE_BENCH, + IO_FILE_BOOK, IO_FILE_CNF, IO_FILE_DOT, IO_FILE_EDIF, @@ -99,6 +100,8 @@ extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteBench.c =========================================================*/ extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); extern int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteBook.c =========================================================*/ +extern void Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteCnf.c ===========================================================*/ extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes ); /*=== abcWriteDot.c ===========================================================*/ diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c index b8555561..3a6ecd19 100644 --- a/src/base/io/ioReadAiger.c +++ b/src/base/io/ioReadAiger.c @@ -45,7 +45,7 @@ SeeAlso [] ***********************************************************************/ -unsigned Io_ReadAigerDecode( char ** ppPos ) +static inline unsigned Io_ReadAigerDecode( char ** ppPos ) { unsigned x = 0, i = 0; unsigned char ch; diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c index 880c2b5f..87358ed2 100644 --- a/src/base/io/ioReadBlifMv.c +++ b/src/base/io/ioReadBlifMv.c @@ -130,7 +130,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ) FILE * pFile; Io_MvMan_t * p; Abc_Ntk_t * pNtk; - Abc_Lib_t * pDesign = NULL; + Abc_Lib_t * pDesign = NULL; char * pDesignName; int RetValue, i; @@ -951,6 +951,7 @@ static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ) pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") ); // create latch pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) ); +// Abc_LatchSetInit0( pObj ); Abc_LatchSetInit0( pObj ); } return 1; diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index 119b4d75..60e6adc8 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -338,6 +338,8 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ) } else if ( FileType == IO_FILE_BENCH ) Io_WriteBench( pNtkTemp, pFileName ); + else if ( FileType == IO_FILE_BOOK ) + Io_WriteBook( pNtkTemp, pFileName ); else if ( FileType == IO_FILE_PLA ) Io_WritePla( pNtkTemp, pFileName ); else if ( FileType == IO_FILE_EQN ) diff --git a/src/base/io/ioWriteBook.c b/src/base/io/ioWriteBook.c new file mode 100644 index 00000000..95405438 --- /dev/null +++ b/src/base/io/ioWriteBook.c @@ -0,0 +1,985 @@ +/**CFile**************************************************************** + + FileName [ioWriteBook.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write Bookshelf files.] + + Author [Myungchul Kim] + + Affiliation [U of Michigan] + + Date [Ver. 1.0. Started - October 25, 2008.] + + Revision [$Id: ioWriteBook.c,v 1.00 2005/11/10 00:00:00 mckima Exp $] + +***********************************************************************/ + +#include "ioAbc.h" +#include "main.h" +#include "mio.h" +#define NODES 0 +#define PL 1 +#define coreHeight 1 +#define termWidth 1 +#define termHeight 1 + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned Io_NtkWriteNodes( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWritePiPoNodes( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteLatchNode( FILE * pFile, Abc_Obj_t * pLatch, bool NodesOrPl ); +static unsigned Io_NtkWriteIntNode( FILE * pFile, Abc_Obj_t * pNode, bool NodesOrPl ); +static unsigned Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteNets( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteIntNet( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkBuildLayout( FILE * pFile1, FILE *pFile2, Abc_Ntk_t * pNtk, double aspectRatio, double whiteSpace, unsigned coreCellArea ); +static void Io_NtkWriteScl( FILE * pFile, unsigned numCoreRows, double layoutWidth ); +static void Io_NtkWritePl( FILE * pFile, Abc_Ntk_t * pNtk, unsigned numTerms, double layoutHeight, double layoutWidth ); +static Vec_Ptr_t * Io_NtkOrderingPads( Abc_Ntk_t * pNtk, Vec_Ptr_t * vTerms ); +static Abc_Obj_t * Io_NtkBfsPads( Abc_Ntk_t * pNtk, Abc_Obj_t * pCurrEntry, unsigned numTerms, bool * pOrdered ); +static bool Abc_NodeIsNand2( Abc_Obj_t * pNode ); +static bool Abc_NodeIsNor2( Abc_Obj_t * pNode ); +static bool Abc_NodeIsAnd2( Abc_Obj_t * pNode ); +static bool Abc_NodeIsOr2( Abc_Obj_t * pNode ); +static bool Abc_NodeIsXor2( Abc_Obj_t * pNode ); +static bool Abc_NodeIsXnor2( Abc_Obj_t * pNode ); + +static inline double Abc_Rint( double x ) { return (double)(int)x; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the network into a Bookshelf file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBookLogic( Abc_Ntk_t * pNtk, char * FileName ) +{ + Abc_Ntk_t * pNtkTemp; + // derive the netlist + pNtkTemp = Abc_NtkToNetlist(pNtk); + if ( pNtkTemp == NULL ) + { + fprintf( stdout, "Writing BOOK has failed.\n" ); + return; + } + Io_WriteBook( pNtkTemp, FileName ); + Abc_NtkDelete( pNtkTemp ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BOOK file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName ) +{ + + FILE * pFileNodes, * pFileNets, * pFileAux; + FILE * pFileScl, * pFilePl, * pFileWts; + char * FileExt = (char *)calloc(strlen(FileName)+7, sizeof(char)); + unsigned coreCellArea=0; + Abc_Ntk_t * pExdc, * pNtkTemp; + int i; + + assert( Abc_NtkIsNetlist(pNtk) ); + // start writing the files + strcpy(FileExt, FileName); + pFileNodes = fopen( strcat(FileExt,".nodes"), "w" ); + strcpy(FileExt, FileName); + pFileNets = fopen( strcat(FileExt,".nets"), "w" ); + strcpy(FileExt, FileName); + pFileAux = fopen( strcat(FileExt,".aux"), "w" ); + + // write the aux file + if ( (pFileNodes == NULL) || (pFileNets == NULL) || (pFileAux == NULL) ) + { + fprintf( stdout, "Io_WriteBook(): Cannot open the output files.\n" ); + return; + } + fprintf( pFileAux, "RowBasedPlacement : %s.nodes %s.nets %s.scl %s.pl %s.wts", + FileName, FileName, FileName, FileName, FileName ); + fclose( pFileAux ); + + // write the master network + coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtk ); + Io_NtkWriteNets( pFileNets, pNtk ); + + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + { + coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtk ); + Io_NtkWriteNets( pFileNets, pNtk ); + } + + // make sure there is no logic hierarchy + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + + // write the hierarchy if present + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) + { + if ( pNtkTemp == pNtk ) + continue; + coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtkTemp ); + Io_NtkWriteNets( pFileNets, pNtkTemp ); + } + } + fclose( pFileNodes ); + fclose( pFileNets ); + + strcpy(FileExt, FileName); + pFileScl = fopen( strcat(FileExt,".scl"), "w" ); + strcpy(FileExt, FileName); + pFilePl = fopen( strcat(FileExt,".pl"), "w" ); + strcpy(FileExt, FileName); + pFileWts = fopen( strcat(FileExt,".wts"), "w" ); + free(FileExt); + + Io_NtkBuildLayout( pFileScl, pFilePl, pNtk, 1.0, 10, coreCellArea ); + fclose( pFileScl ); + fclose( pFilePl ); + fclose( pFileWts ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BOOK file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Io_NtkWriteNodes( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pLatch, * pNode; + unsigned numTerms, numNodes, coreCellArea=0; + int i; + + assert( Abc_NtkIsNetlist(pNtk) ); + // write the forehead + numTerms=Abc_NtkPiNum(pNtk)+Abc_NtkPoNum(pNtk); + numNodes=numTerms+Abc_NtkNodeNum(pNtk)+Abc_NtkLatchNum(pNtk); + printf("NumNodes : %d\t", numNodes ); + printf("NumTerminals : %d\n", numTerms ); + fprintf( pFile, "UCLA nodes 1.0\n"); + fprintf( pFile, "NumNodes : %d\n", numNodes ); + fprintf( pFile, "NumTerminals : %d\n", numTerms ); + // write the PI/POs + Io_NtkWritePiPoNodes( pFile, pNtk ); + // write the latches + if ( !Abc_NtkIsComb(pNtk) ) + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + Io_NtkWriteLatchNode( pFile, pLatch, NODES ); + coreCellArea+=6*coreHeight; + } + // write each internal node + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + coreCellArea+=Io_NtkWriteIntNode( pFile, pNode, NODES ); + } + Extra_ProgressBarStop( pProgress ); + return coreCellArea; +} + +/**Function************************************************************* + + Synopsis [Writes the primary input nodes into a file] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWritePiPoNodes( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int i; + + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + fprintf( pFile, "i%s_input\t", Abc_ObjName(pNet) ); + fprintf( pFile, "terminal "); + fprintf( pFile, " %d %d\n", termWidth, termHeight ); + } + + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + fprintf( pFile, "o%s_output\t", Abc_ObjName(pNet) ); + fprintf( pFile, "terminal "); + fprintf( pFile, " %d %d\n", termWidth, termHeight ); + } +} + +/**Function************************************************************* + + Synopsis [Write the latch nodes into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteLatchNode( FILE * pFile, Abc_Obj_t * pLatch, bool NodesOrPl ) +{ + Abc_Obj_t * pNetLi, * pNetLo; + + pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); + pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); + /// write the latch line + fprintf( pFile, "%s_%s_latch\t", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) ); + if (NodesOrPl == NODES) + fprintf( pFile, " %d %d\n", 6, 1 ); +} + +/**Function************************************************************* + + Synopsis [Write the internal node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Io_NtkWriteIntNode( FILE * pFile, Abc_Obj_t * pNode, bool NodesOrPl ) +{ + unsigned sizex=0, sizey=coreHeight, isize=0; + //double nx, ny, xstep, ystep; + Abc_Obj_t * pNeti, *pNeto; + int i; + + // write the network after mapping + if ( Abc_NtkHasMapping(pNode->pNtk) ) + sizex=Io_NtkWriteNodeGate( pFile, pNode ); + else + { + Abc_ObjForEachFanin( pNode, pNeti, i ) + fprintf( pFile, "%s_", Abc_ObjName(pNeti) ); + Abc_ObjForEachFanout( pNode, pNeto, i ) + fprintf( pFile, "%s_", Abc_ObjName(pNeto) ); + fprintf( pFile, "name\t" ); + + if(NodesOrPl == NODES) + { + isize=Abc_ObjFaninNum(pNode); + if ( Abc_NodeIsConst0(pNode) || Abc_NodeIsConst1(pNode) ) + sizex=0; + else if ( Abc_NodeIsInv(pNode) ) + sizex=1; + else if ( Abc_NodeIsBuf(pNode) ) + sizex=2; + else + { + assert( Abc_NtkHasSop(pNode->pNtk) ); + if ( Abc_NodeIsNand2(pNode) || Abc_NodeIsNor2(pNode) ) + sizex=2; + else if ( Abc_NodeIsAnd2(pNode) || Abc_NodeIsOr2(pNode) ) + sizex=3; + else if ( Abc_NodeIsXor2(pNode) || Abc_NodeIsXnor2(pNode) ) + sizex=5; + else + { + assert( isize > 2 ); + sizex=isize+Abc_SopGetCubeNum(pNode->pData); + } + } + } + } + if(NodesOrPl == NODES) + { + fprintf( pFile, " %d %d\n", sizex, sizey ); + + // Equally place pins. Size pins needs / isize+#output+1 + isize= isize + Abc_ObjFanoutNum(pNode) + 1; + } + return sizex*sizey; + /* + xstep = sizex / isize; + ystep = sizey / isize; + nx= -0.5 * sizex; + ny= -0.5 * sizey; + + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + nx+= xstep; + ny+= ystep; + if (fabs(nx) < 0.001) + nx= 0; + if (fabs(ny) < 0.001) + ny= 0; + } + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + nx+= xstep; + ny+= ystep; + if (fabs(nx) < 0.001) + nx= 0; + if (fabs(ny) < 0.001) + ny= 0; + } + */ +} + +/**Function************************************************************* + + Synopsis [Writes the internal node after tech mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode ) +{ + Mio_Gate_t * pGate = pNode->pData; + Mio_Pin_t * pGatePin; + int i; + // write the node gate + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + fprintf( pFile, "%s_", Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); + assert ( i == Abc_ObjFaninNum(pNode) ); + fprintf( pFile, "%s_%s\t", Abc_ObjName( Abc_ObjFanout0(pNode) ), Mio_GateReadName(pGate) ); + return Mio_GateReadArea(pGate); +} + +/**Function************************************************************* + + Synopsis [Write the nets into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNets( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNet; + unsigned numPin=0; + int i; + + assert( Abc_NtkIsNetlist(pNtk) ); + // write the head + Abc_NtkForEachNet( pNtk, pNet, i ) + numPin+=Abc_ObjFaninNum(pNet)+Abc_ObjFanoutNum(pNet); + printf( "NumNets : %d\t", Abc_NtkNetNum(pNtk) ); + printf( "NumPins : %d\n\n", numPin ); + fprintf( pFile, "UCLA nets 1.0\n"); + fprintf( pFile, "NumNets : %d\n", Abc_NtkNetNum(pNtk) ); + fprintf( pFile, "NumPins : %d\n", numPin ); + + // write nets + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNetNum(pNtk) ); + Abc_NtkForEachNet( pNtk, pNet, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_NtkWriteIntNet( pFile, pNet ); + } + Extra_ProgressBarStop( pProgress ); +} + +/**Function************************************************************* + + Synopsis [Write the nets into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteIntNet( FILE * pFile, Abc_Obj_t * pNet ) +{ + Abc_Obj_t * pFanin, * pFanout; + Abc_Obj_t * pNeti, * pNeto; + Abc_Obj_t * pNetLi, * pNetLo, * pLatch; + int i, j; + int NetDegree=Abc_ObjFaninNum(pNet)+Abc_ObjFanoutNum(pNet); + + fprintf( pFile, "NetDegree\t:\t\t%d\t\t%s\n", NetDegree, Abc_ObjName(Abc_ObjFanin0(pNet)) ); + + pFanin=Abc_ObjFanin0(pNet); + if ( Abc_ObjIsPi(pFanin) ) + fprintf( pFile, "i%s_input I\n", Abc_ObjName(pNet) ); + else + { + if(!Abc_NtkIsComb(pNet->pNtk) && Abc_ObjFaninNum(pFanin) && Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) + { + pLatch=Abc_ObjFanin0(pFanin); + pNetLi=Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + pNetLo=Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); + fprintf( pFile, "%s_%s_latch I : ", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) ); + } + else + { + Abc_ObjForEachFanin( pFanin, pNeti, j ) + fprintf( pFile, "%s_", Abc_ObjName(pNeti) ); + Abc_ObjForEachFanout( pFanin, pNeto, j ) + fprintf( pFile, "%s_", Abc_ObjName(pNeto) ); + if ( Abc_NtkHasMapping(pNet->pNtk) ) + fprintf( pFile, "%s : ", Mio_GateReadName(pFanin->pData) ); + else + fprintf( pFile, "name I : " ); + } + // offsets are simlply 0.00 0.00 at the moment + fprintf( pFile, "%.2f %.2f\n", .0, .0 ); + } + + Abc_ObjForEachFanout( pNet, pFanout, i ) + { + if ( Abc_ObjIsPo(pFanout) ) + fprintf( pFile, "o%s_output O\n", Abc_ObjName(pNet) ); + else + { + if(!Abc_NtkIsComb(pNet->pNtk) && Abc_ObjFanoutNum(pFanout) && Abc_ObjIsLatch( Abc_ObjFanout0(pFanout) ) ) + { + pLatch=Abc_ObjFanout0(pFanout); + pNetLi=Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + pNetLo=Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); + fprintf( pFile, "%s_%s_latch O : ", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) ); + } + else + { + Abc_ObjForEachFanin( pFanout, pNeti, j ) + fprintf( pFile, "%s_", Abc_ObjName(pNeti) ); + Abc_ObjForEachFanout( pFanout, pNeto, j ) + fprintf( pFile, "%s_", Abc_ObjName(pNeto) ); + if ( Abc_NtkHasMapping(pNet->pNtk) ) + fprintf( pFile, "%s : ", Mio_GateReadName(pFanout->pData) ); + else + fprintf( pFile, "name O : " ); + } + // offsets are simlply 0.00 0.00 at the moment + fprintf( pFile, "%.2f %.2f\n", .0, .0 ); + } + } +} + +/**Function************************************************************* + + Synopsis [Write the network into a BOOK file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkBuildLayout( FILE * pFileScl, FILE * pFilePl, Abc_Ntk_t * pNtk, double aspectRatio, double whiteSpace, unsigned coreCellArea ) +{ + unsigned numCoreCells=Abc_NtkNodeNum(pNtk)+Abc_NtkLatchNum(pNtk); + double targetLayoutArea = coreCellArea/(1.0-(whiteSpace/100.0)); + unsigned numCoreRows=(aspectRatio>0.0) ? (Abc_Rint(sqrt(targetLayoutArea/aspectRatio)/coreHeight)) : 0; + unsigned numTerms=Abc_NtkPiNum(pNtk)+Abc_NtkPoNum(pNtk); + unsigned totalWidth=coreCellArea/coreHeight; + double layoutHeight = numCoreRows * coreHeight; + double layoutWidth = Abc_Rint(targetLayoutArea/layoutHeight); + double actualLayoutArea = layoutWidth * layoutHeight; + + printf( "Core cell height(==site height) is %d\n", coreHeight ); + printf( "Total core cell width is %d giving an ave width of %f\n", totalWidth, (double)(totalWidth/numCoreCells)); + printf( "Target Dimensions:\n" ); + printf( " Area : %f\n", targetLayoutArea ); + printf( " WS%% : %f\n", whiteSpace ); + printf( " AR : %f\n", aspectRatio ); + printf( "Actual Dimensions:\n" ); + printf( " Width : %f\n", layoutWidth ); + printf( " Height: %f (%d rows)\n", layoutHeight, numCoreRows); + printf( " Area : %f\n", actualLayoutArea ); + printf( " WS%% : %f\n", 100*(actualLayoutArea-coreCellArea)/actualLayoutArea ); + printf( " AR : %f\n\n", layoutWidth/layoutHeight ); + + Io_NtkWriteScl( pFileScl, numCoreRows, layoutWidth ); + Io_NtkWritePl( pFilePl, pNtk, numTerms, layoutHeight, layoutWidth ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BOOK file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteScl( FILE * pFile, unsigned numCoreRows, double layoutWidth ) +{ + int origin_y=0; + char * rowOrients[2] = {"N", "FS"}; + char symmetry='Y'; + double sitewidth=1.0; + double spacing=1.0; + + int rowId; + // write the forehead + fprintf( pFile, "UCLA scl 1.0\n\n" ); + fprintf( pFile, "Numrows : %d\n\n", numCoreRows ); + + for( rowId=0 ; rowId0 ) + { + pNeighbor = Vec_PtrEntry( vNeighbors, 0 ); + assert( Abc_ObjIsNode(pNeighbor) || Abc_ObjIsTerm(pNeighbor) ); + Vec_PtrRemove( vNeighbors, pNeighbor ); + + if( Abc_NodeIsTravIdCurrent( pNeighbor ) ) + continue; + Abc_NodeSetTravIdCurrent( pNeighbor ); + + if( ((Abc_ObjIsPi(pNeighbor) || Abc_ObjIsPo(pNeighbor))) && !pOrdered[Abc_ObjId(pNeighbor)] ) + { + foundNeighbor=1; + break; + } + if( Abc_ObjFanoutNum( pNeighbor ) ) + { + pNet=Abc_ObjFanout0( pNeighbor ); + if( !Abc_NtkIsComb(pNtk) && Abc_ObjIsLatch(pNet) ) + pNet=Abc_ObjFanout0( Abc_ObjFanout0(pNet) ); + Abc_ObjForEachFanout( pNet, pNode, i ) + if( !Abc_NodeIsTravIdCurrent(pNode) ) + Vec_PtrPush( vNeighbors, pNode ); + } + if( Abc_ObjFaninNum( pNeighbor ) ) + { + if( !Abc_NtkIsComb(pNtk) && Abc_ObjIsLatch(Abc_ObjFanin0(pNeighbor)) ) + pNeighbor=Abc_ObjFanin0( Abc_ObjFanin0(pNeighbor) ); + Abc_ObjForEachFanin( pNeighbor, pNet, i ) + if( !Abc_NodeIsTravIdCurrent(pNode=Abc_ObjFanin0(pNet)) ) + Vec_PtrPush( vNeighbors, pNode ); + } + } + return ( foundNeighbor ) ? pNeighbor : pTerm; +} + +/**Function************************************************************* + + Synopsis [Test is the node is nand2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsNand2( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 2 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return ( !strcmp((pNode->pData), "-0 1\n0- 1\n") || + !strcmp((pNode->pData), "0- 1\n-0 1\n") || + !strcmp((pNode->pData), "11 0\n") ); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadNand2(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Test is the node is nand2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsNor2( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 2 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return ( !strcmp((pNode->pData), "00 1\n") ); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Test is the node is and2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsAnd2( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 2 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsAndType((pNode->pData)); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadAnd2(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Test is the node is or2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsOr2( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 2 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return ( Abc_SopIsOrType((pNode->pData)) || + !strcmp((pNode->pData), "01 0\n") || + !strcmp((pNode->pData), "10 0\n") || + !strcmp((pNode->pData), "00 0\n") ); + //off-sets, too + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Test is the node is xor2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsXor2( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 2 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return ( !strcmp((pNode->pData), "01 1\n10 1\n") || !strcmp((pNode->pData), "10 1\n01 1\n") ); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Test is the node is xnor2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsXnor2( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 2 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return ( !strcmp((pNode->pData), "11 1\n00 1\n") || !strcmp((pNode->pData), "00 1\n11 1\n") ); + assert( 0 ); + return 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/io/io_.c b/src/base/io/io_.c deleted file mode 100644 index b24d1299..00000000 --- a/src/base/io/io_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [io_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedure to read network from file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: io_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ioAbc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - diff --git a/src/base/io/module.make b/src/base/io/module.make index bb35a7fc..6f4e2539 100644 --- a/src/base/io/module.make +++ b/src/base/io/module.make @@ -16,6 +16,7 @@ SRC += src/base/io/io.c \ src/base/io/ioWriteBench.c \ src/base/io/ioWriteBlif.c \ src/base/io/ioWriteBlifMv.c \ + src/base/io/ioWriteBook.c \ src/base/io/ioWriteCnf.c \ src/base/io/ioWriteDot.c \ src/base/io/ioWriteEqn.c \ diff --git a/src/base/main/main.c b/src/base/main/main.c index bfa91ddc..a9d610fd 100644 --- a/src/base/main/main.c +++ b/src/base/main/main.c @@ -216,14 +216,14 @@ int main( int argc, char * argv[] ) if ( fStatus == -1 || fStatus == -2 ) break; } - } + } // if the memory should be freed, quit packages if ( fStatus < 0 ) { Abc_Stop(); - } - return 0; + } + return 0; usage: Abc_UtilsPrintHello( pAbc ); diff --git a/src/base/main/main.h b/src/base/main/main.h index af0ed24d..159122d2 100644 --- a/src/base/main/main.h +++ b/src/base/main/main.h @@ -65,15 +65,16 @@ typedef struct Abc_Frame_t_ Abc_Frame_t; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// + #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif /*=== main.c ===========================================================*/ @@ -103,6 +104,7 @@ extern ABC_DLL Vec_Ptr_t * Abc_FrameReadStore(); extern ABC_DLL int Abc_FrameReadStoreSize(); extern ABC_DLL void * Abc_FrameReadLibLut(); extern ABC_DLL void * Abc_FrameReadLibGen(); +extern ABC_DLL void * Abc_FrameReadLibGen2(); extern ABC_DLL void * Abc_FrameReadLibSuper(); extern ABC_DLL void * Abc_FrameReadLibVer(); extern ABC_DLL void * Abc_FrameReadManDd(); @@ -114,6 +116,7 @@ extern ABC_DLL void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_FrameSetNtkStoreSize( int nStored ); extern ABC_DLL void Abc_FrameSetLibLut( void * pLib ); extern ABC_DLL void Abc_FrameSetLibGen( void * pLib ); +extern ABC_DLL void Abc_FrameSetLibGen2( void * pLib ); extern ABC_DLL void Abc_FrameSetLibSuper( void * pLib ); extern ABC_DLL void Abc_FrameSetLibVer( void * pLib ); extern ABC_DLL void Abc_FrameSetFlag( char * pFlag, char * pValue ); diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c index f02ade1c..23e9184e 100644 --- a/src/base/main/mainFrame.c +++ b/src/base/main/mainFrame.c @@ -47,6 +47,7 @@ Vec_Ptr_t * Abc_FrameReadStore() { return s_GlobalFrame->vSt int Abc_FrameReadStoreSize() { return Vec_PtrSize(s_GlobalFrame->vStore); } void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; } void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; } +void * Abc_FrameReadLibGen2() { return s_GlobalFrame->pLibGen2; } void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; } void * Abc_FrameReadLibVer() { return s_GlobalFrame->pLibVer; } 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; } @@ -55,6 +56,7 @@ char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName void Abc_FrameSetLibLut( void * pLib ) { s_GlobalFrame->pLibLut = pLib; } void Abc_FrameSetLibGen( void * pLib ) { s_GlobalFrame->pLibGen = pLib; } +void Abc_FrameSetLibGen2( void * pLib ) { s_GlobalFrame->pLibGen2 = pLib; } void Abc_FrameSetLibSuper( void * pLib ) { s_GlobalFrame->pLibSuper = pLib; } void Abc_FrameSetLibVer( void * pLib ) { s_GlobalFrame->pLibVer = pLib; } void Abc_FrameSetFlag( char * pFlag, char * pValue ) { Cmd_FlagUpdateValue( s_GlobalFrame, pFlag, pValue ); } diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h index becbfd6b..cfd945b7 100644 --- a/src/base/main/mainInt.h +++ b/src/base/main/mainInt.h @@ -71,6 +71,7 @@ struct Abc_Frame_t_ // libraries for mapping void * pLibLut; // the current LUT library void * pLibGen; // the current genlib + void * pLibGen2; // the current genlib void * pLibSuper; // the current supergate library void * pLibVer; // the current Verilog library @@ -97,15 +98,16 @@ struct Abc_Frame_t_ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// + #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif /*=== mvMain.c ===========================================================*/ diff --git a/src/map/amap/amap.h b/src/map/amap/amap.h new file mode 100644 index 00000000..ee845e7f --- /dev/null +++ b/src/map/amap/amap.h @@ -0,0 +1,83 @@ +/**CFile**************************************************************** + + FileName [amap.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amap.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __AMAP_H__ +#define __AMAP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + + +typedef struct Amap_Par_t_ Amap_Par_t; +struct Amap_Par_t_ +{ + int nIterFlow; // iterations of area flow + int nIterArea; // iteratoins of exact area + int fUseMuxes; // enables the use of MUXes + int fUseXors; // enables the use of XORs + int fFreeInvs; // assume inverters are free (area = 0) + float fEpsilon; // used to compare floating point numbers + int fVerbose; // verbosity flag +}; + +typedef struct Amap_Out_t_ Amap_Out_t; +struct Amap_Out_t_ +{ + char * pName; // gate name + short Type; // node type (-1=input; 0=internal; 1=output) + short nFans; // number of fanins + int pFans[0]; // fanin +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== amapCore.c ==========================================================*/ +extern void Amap_ManSetDefaultParams( Amap_Par_t * pPars ); +extern Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/map/amap/amapCore.c b/src/map/amap/amapCore.c new file mode 100644 index 00000000..f1554862 --- /dev/null +++ b/src/map/amap/amapCore.c @@ -0,0 +1,103 @@ +/**CFile**************************************************************** + + FileName [amapCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Core mapping procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManSetDefaultParams( Amap_Par_t * p ) +{ + memset( p, 0, sizeof(Amap_Par_t) ); + p->nIterFlow = 1; // iterations of area flow + p->nIterArea = 4; // iteratoins of exact area + p->fUseMuxes = 0; // enables the use of MUXes + p->fUseXors = 1; // enables the use of XORs + p->fFreeInvs = 0; // assume inverters are free (area = 0) + p->fEpsilon = (float)0.001; // used to compare floating point numbers + p->fVerbose = 0; // verbosity flag +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars ) +{ + extern void * Abc_FrameReadLibGen2(); + Vec_Ptr_t * vRes; + Amap_Man_t * p; + Amap_Lib_t * pLib; + int clkTotal = clock(); + pLib = Abc_FrameReadLibGen2(); + if ( pLib == NULL ) + { + printf( "Library is not available.\n" ); + return NULL; + } + p = Amap_ManStart( Aig_ManNodeNum(pAig) ); + p->pPars = pPars; + p->pLib = pLib; + p->fAreaInv = pPars->fFreeInvs? 0.0 : pLib->pGateInv->dArea; + p->fUseMux = pPars->fUseMuxes && pLib->fHasMux; + p->fUseXor = pPars->fUseXors && pLib->fHasXor; + p->ppCutsTemp = CALLOC( Amap_Cut_t *, 2 * pLib->nNodes ); + p->pMatsTemp = CALLOC( int, 2 * pLib->nNodes ); + Amap_ManCreate( p, pAig ); + Amap_ManMap( p ); + vRes = NULL; + vRes = Amap_ManProduceMapped( p ); + Amap_ManStop( p ); +if ( pPars->fVerbose ) +{ +PRT( "Total runtime", clock() - clkTotal ); +} + return vRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapGraph.c b/src/map/amap/amapGraph.c new file mode 100644 index 00000000..83cadc2c --- /dev/null +++ b/src/map/amap/amapGraph.c @@ -0,0 +1,389 @@ +/**CFile**************************************************************** + + FileName [amapGraph.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Internal AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapGraph.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Obj_t * Amap_ManSetupObj( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + pObj = (Amap_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObj ); + memset( pObj, 0, sizeof(Amap_Obj_t) ); + pObj->nFouts[0] = 1; // needed for flow to work in the first pass + pObj->Id = Vec_PtrSize(p->vObjs); + Vec_PtrPush( p->vObjs, pObj ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Obj_t * Amap_ManCreateConst1( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + pObj = Amap_ManSetupObj( p ); + pObj->Type = AMAP_OBJ_CONST1; + pObj->fPhase = 1; + p->nObjs[AMAP_OBJ_CONST1]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Obj_t * Amap_ManCreatePi( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + pObj = Amap_ManSetupObj( p ); + pObj->Type = AMAP_OBJ_PI; + pObj->IdPio = Vec_PtrSize( p->vPis ); + Vec_PtrPush( p->vPis, pObj ); + p->nObjs[AMAP_OBJ_PI]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary output with the given driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Obj_t * Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 ) +{ + Amap_Obj_t * pObj; + pObj = Amap_ManSetupObj( p ); + pObj->IdPio = Vec_PtrSize( p->vPos ); + Vec_PtrPush( p->vPos, pObj ); + pObj->Type = AMAP_OBJ_PO; + pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; + pObj->Level = Amap_Regular(pFan0)->Level; + if ( p->nLevelMax < (int)pObj->Level ) + p->nLevelMax = (int)pObj->Level; + p->nObjs[AMAP_OBJ_PO]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ) +{ + Amap_Obj_t * pObj; + pObj = Amap_ManSetupObj( p ); + pObj->Type = AMAP_OBJ_AND; + pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; + pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; + assert( Amap_Lit2Var(pObj->Fan[0]) != Amap_Lit2Var(pObj->Fan[1]) ); + pObj->fPhase = Amap_ObjPhaseReal(pFan0) & Amap_ObjPhaseReal(pFan1); + pObj->Level = 1 + AIG_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); + if ( p->nLevelMax < (int)pObj->Level ) + p->nLevelMax = (int)pObj->Level; + p->nObjs[AMAP_OBJ_AND]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ) +{ + Amap_Obj_t * pObj; + pObj = Amap_ManSetupObj( p ); + pObj->Type = AMAP_OBJ_XOR; + pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; + pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; + pObj->fPhase = Amap_ObjPhaseReal(pFan0) ^ Amap_ObjPhaseReal(pFan1); + pObj->Level = 2 + AIG_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); + if ( p->nLevelMax < (int)pObj->Level ) + p->nLevelMax = (int)pObj->Level; + p->nObjs[AMAP_OBJ_XOR]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC ) +{ + Amap_Obj_t * pObj; + pObj = Amap_ManSetupObj( p ); + pObj->Type = AMAP_OBJ_MUX; + pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; + pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; + pObj->Fan[2] = Amap_ObjToLit(pFanC); Amap_Regular(pFanC)->nRefs++; + pObj->fPhase = (Amap_ObjPhaseReal(pFan1) & Amap_ObjPhaseReal(pFanC)) | + (Amap_ObjPhaseReal(pFan0) & ~Amap_ObjPhaseReal(pFanC)); + pObj->Level = AIG_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); + pObj->Level = 2 + AIG_MAX( pObj->Level, Amap_Regular(pFanC)->Level ); + if ( p->nLevelMax < (int)pObj->Level ) + p->nLevelMax = (int)pObj->Level; + p->nObjs[AMAP_OBJ_MUX]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates the choice node.] + + Description [Should be called after the equivalence class nodes are linked.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj ) +{ + Amap_Obj_t * pTemp; + // mark the node as a representative if its class +// assert( pObj->fRepr == 0 ); + pObj->fRepr = 1; + // update the level of this node (needed for correct required time computation) + for ( pTemp = pObj; pTemp; pTemp = Amap_ObjChoice(p, pTemp) ) + { + pObj->Level = AIG_MAX( pObj->Level, pTemp->Level ); +// pTemp->nVisits++; pTemp->nVisitsCopy++; + } + // mark the largest level + if ( p->nLevelMax < (int)pObj->Level ) + p->nLevelMax = (int)pObj->Level; +} + +/**Function************************************************************* + + Synopsis [Creates XOR/MUX choices for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManCreateXorChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pChoices[] ) +{ + pChoices[0] = Amap_ManCreateXor( p, pFan0, pFan1 ); + pChoices[1] = Amap_ManCreateXor( p, Amap_Not(pFan0), pFan1 ); + pChoices[2] = Amap_ManCreateXor( p, pFan0, Amap_Not(pFan1) ); + pChoices[3] = Amap_ManCreateXor( p, Amap_Not(pFan0), Amap_Not(pFan1) ); +} + +/**Function************************************************************* + + Synopsis [Creates XOR/MUX choices for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManCreateMuxChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC, Amap_Obj_t * pChoices[] ) +{ + pChoices[0] = Amap_ManCreateMux( p, pFan0, pFan1, pFanC ); + pChoices[1] = Amap_ManCreateMux( p, Amap_Not(pFan0), Amap_Not(pFan1), pFanC ); + pChoices[2] = Amap_ManCreateMux( p, pFan1, pFan0, Amap_Not(pFanC) ); + pChoices[3] = Amap_ManCreateMux( p, Amap_Not(pFan1), Amap_Not(pFan0), Amap_Not(pFanC) ); +} + +/**Function************************************************************* + + Synopsis [Drags pointer out through the copy.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Amap_Obj_t * Amap_AndToObj( Aig_Obj_t * pObj ) +{ + return Amap_NotCond( (Amap_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Obj_t * Amap_ManGetLast_rec( Amap_Man_t * p, Amap_Obj_t * pObj ) +{ + if ( pObj->Equiv == 0 ) + return pObj; + return Amap_ManGetLast_rec( p, Amap_ObjChoice(p, pObj) ); +} + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig ) +{ + Vec_Ptr_t * vNodes; + Amap_Obj_t * pChoices[4]; + Aig_Obj_t * pObj, * pFanin, * pPrev, * pFan0, * pFan1, * pFanC; + int i, fChoices; + if ( pAig->pEquivs ) + vNodes = Aig_ManDfsChoices( pAig ); + else + vNodes = Aig_ManDfs( pAig, 1 ); + p->pConst1 = Amap_ManCreateConst1( p ); + // print warning about excessive memory usage + if ( p->pPars->fVerbose ) + { + if ( 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30) > 0.1 ) + printf( "Warning: Mapper allocates %.3f Gb for subject graph with %d objects.\n", + 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30), Aig_ManObjNum(pAig) ); + } + // create PIs and remember them in the old nodes + Aig_ManCleanData(pAig); + Aig_ManConst1(pAig)->pData = Amap_ManConst1( p ); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Amap_ManCreatePi( p ); + // load the AIG into the mapper + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + fChoices = 0; + if ( p->fUseXor && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1 ) ) + { + Amap_ManCreateXorChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), pChoices ); + fChoices = 1; + } + else if ( p->fUseMux && Aig_ObjIsMuxType(pObj) ) + { + pFanC = Aig_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); + Amap_ManCreateMuxChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), Amap_AndToObj(pFanC), pChoices ); + fChoices = 1; + } + pObj->pData = Amap_ManCreateAnd( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj), (Amap_Obj_t *)Aig_ObjChild1Copy(pObj) ); + if ( fChoices ) + { + p->nChoicesAdded++; + Amap_ObjSetChoice( (Amap_Obj_t *)pObj->pData, pChoices[0] ); + Amap_ObjSetChoice( pChoices[0], pChoices[1] ); + Amap_ObjSetChoice( pChoices[1], pChoices[2] ); + Amap_ObjSetChoice( pChoices[2], pChoices[3] ); + Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData ); + } + if ( Aig_ObjIsChoice( pAig, pObj ) ) + { +// assert( !fChoices ); + p->nChoicesGiven++; + for ( pPrev = pObj, pFanin = Aig_ObjEquiv(pAig, pObj); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(pAig, pFanin) ) + { + ((Amap_Obj_t *)pFanin->pData)->fRepr = 0; + Amap_ObjSetChoice( Amap_ManGetLast_rec(p, (Amap_Obj_t *)pPrev->pData), + (Amap_Obj_t *)pFanin->pData ); + } + Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData ); + } + } + Vec_PtrFree( vNodes ); + // set the primary outputs without copying the phase + Aig_ManForEachPo( pAig, pObj, i ) + pObj->pData = Amap_ManCreatePo( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj) ); + if ( p->pPars->fVerbose ) + printf( "Performing mapping with %d given and %d created choices.\n", + p->nChoicesGiven, p->nChoicesAdded ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapInt.h b/src/map/amap/amapInt.h new file mode 100644 index 00000000..954790c9 --- /dev/null +++ b/src/map/amap/amapInt.h @@ -0,0 +1,380 @@ +/**CFile**************************************************************** + + FileName [amapInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __AMAP_INT_H__ +#define __AMAP_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig.h" +#include "amap.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// the largest gate size in the library +// (gates above this size will be ignored) +#define AMAP_MAXINS 15 + +#define AMAP_STRING_CONST0 "CONST0" +#define AMAP_STRING_CONST1 "CONST1" + +// object types +typedef enum { + AMAP_OBJ_NONE, // 0: non-existent object + AMAP_OBJ_CONST1, // 1: constant 1 + AMAP_OBJ_PI, // 2: primary input + AMAP_OBJ_PO, // 3: primary output + AMAP_OBJ_AND, // 4: AND node + AMAP_OBJ_XOR, // 5: XOR node + AMAP_OBJ_MUX, // 6: MUX node + AMAP_OBJ_VOID // 7: unused object +} Amap_Type_t; + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Amap_Lib_t_ Amap_Lib_t; +typedef struct Amap_Pin_t_ Amap_Pin_t; +typedef struct Amap_Gat_t_ Amap_Gat_t; +typedef struct Amap_Nod_t_ Amap_Nod_t; +typedef struct Amap_Set_t_ Amap_Set_t; + +typedef struct Amap_Man_t_ Amap_Man_t; +typedef struct Amap_Obj_t_ Amap_Obj_t; +typedef struct Amap_Cut_t_ Amap_Cut_t; +typedef struct Amap_Mat_t_ Amap_Mat_t; + +struct Amap_Man_t_ +{ + // user data + Amap_Par_t * pPars; + Amap_Lib_t * pLib; + // internal parameters + float fEpsilonInternal; + float fAreaInv; + int fUseXor; + int fUseMux; + // internal AIG with choices + Vec_Ptr_t * vPis; + Vec_Ptr_t * vPos; + Vec_Ptr_t * vObjs; + Aig_MmFixed_t * pMemObj; + Aig_MmFlex_t * pMemCuts; + Aig_MmFlex_t * pMemCutBest; + Aig_MmFlex_t * pMemTemp; + Amap_Obj_t * pConst1; + int nObjs[AMAP_OBJ_VOID]; + int nLevelMax; + int nChoicesGiven; + int nChoicesAdded; + // mapping data-structures + Vec_Int_t * vTemp; + int * pMatsTemp; + Amap_Cut_t ** ppCutsTemp; + Amap_Cut_t * pCutsPi; + Vec_Ptr_t * vCuts0; + Vec_Ptr_t * vCuts1; + Vec_Ptr_t * vCuts2; + // statistics + int nCutsUsed; + int nCutsTried; + int nCutsTried3; + int nBytesUsed; +}; +struct Amap_Lib_t_ +{ + char * pName; // library name + Vec_Ptr_t * vGates; // represenation of gates + Vec_Ptr_t * vSorted; // gates sorted for area-only mapping + Vec_Ptr_t * vSelect; // gates selected for area-only mapping + Amap_Gat_t * pGate0; // the constant zero gate + Amap_Gat_t * pGate1; // the constant one gate + Amap_Gat_t * pGateBuf; // the buffer + Amap_Gat_t * pGateInv; // the inverter + Aig_MmFlex_t * pMemGates; // memory manager for objects + int fHasXor; // XOR/NXOR gates are present + int fHasMux; // MUX/NMUX gates are present + // structural representation + int fVerbose; // enable detailed statistics + Amap_Nod_t * pNodes; // representation nodes + int nNodes; // the number of nodes used + int nNodesAlloc; // the number of nodes allocated + Vec_Ptr_t * vRules; // the rule of AND gate + Vec_Ptr_t * vRulesX; // the rule of XOR gate + Vec_Int_t * vRules3; // the rule of MUX gate + int ** pRules; // simplified representation + int ** pRulesX; // simplified representation + Aig_MmFlex_t * pMemSet; // memory manager for sets + int nSets; // the number of sets created +}; +struct Amap_Pin_t_ +{ + char * pName; + int Phase; + double dLoadInput; + double dLoadMax; + double dDelayBlockRise; + double dDelayFanoutRise; + double dDelayBlockFall; + double dDelayFanoutFall; + double dDelayBlockMax; +}; +struct Amap_Gat_t_ +{ + Amap_Lib_t * pLib; // library + char * pName; // the name of the gate + char * pOutName; // name of the output + double dArea; // the area of the gate + char * pForm; // the formula describing functionality + unsigned * pFunc; // truth table + unsigned Id : 23; // unique number of the gate + unsigned fMux : 1; // denotes MUX-gates + unsigned nPins : 8; // number of inputs + Amap_Pin_t Pins[0]; // description of inputs +}; +struct Amap_Set_t_ +{ + Amap_Set_t * pNext; + unsigned iGate : 16; + unsigned fInv : 1; + unsigned nIns : 15; + char Ins[AMAP_MAXINS];// mapping from gate inputs into fanins +}; +struct Amap_Nod_t_ +{ + unsigned Id : 16; // ID of the node + unsigned nSuppSize: 8; // support size + unsigned Type : 8; // the type of node + short iFan0; // fanin0 + short iFan1; // fanin1 + short iFan2; // fanin2 + short Unused; // + Amap_Set_t * pSets; // implementable gates +}; +struct Amap_Cut_t_ +{ + unsigned iMat : 16; + unsigned fInv : 1; + unsigned nFans : 15; + int Fans[0]; +}; +struct Amap_Mat_t_ +{ + Amap_Cut_t * pCut; // the cut + Amap_Set_t * pSet; // the set + float Area; // area flow / exact area of the node + float AveFan; // edge flow of the node + float Delay; // delay of the node +}; +struct Amap_Obj_t_ +{ + unsigned Type : 3; + unsigned Id : 29; + unsigned IdPio : 29; + unsigned fPhase : 1; + unsigned fRepr : 1; + unsigned fPolar : 1; // pCutBest->fInv ^ pSetBest->fInv + unsigned Level : 20; + unsigned nCuts : 12; + int nRefs; + int Equiv; + int Fan[3]; + union { + void * pData; + int iData; + }; + // match of the node + float EstRefs; // the number of estimated fanouts + int nFouts[2]; // the number of refs in each polarity + Amap_Mat_t Best; // the best match of the node +}; + +static inline int Amap_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Amap_Lit2Var( int Lit ) { return Lit >> 1; } +static inline int Amap_LitIsCompl( int Lit ) { return Lit & 1; } +static inline int Amap_LitNot( int Lit ) { return Lit ^ 1; } +static inline int Amap_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Amap_LitRegular( int Lit ) { return Lit & ~01; } + +static inline Amap_Obj_t * Amap_Regular( Amap_Obj_t * p ) { return (Amap_Obj_t *)((PORT_PTRUINT_T)(p) & ~01); } +static inline Amap_Obj_t * Amap_Not( Amap_Obj_t * p ) { return (Amap_Obj_t *)((PORT_PTRUINT_T)(p) ^ 01); } +static inline Amap_Obj_t * Amap_NotCond( Amap_Obj_t * p, int c ) { return (Amap_Obj_t *)((PORT_PTRUINT_T)(p) ^ (c)); } +static inline int Amap_IsComplement( Amap_Obj_t * p ) { return (int )(((PORT_PTRUINT_T)p) & 01); } + +static inline int Amap_ManPiNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_PI]; } +static inline int Amap_ManPoNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_PO]; } +static inline int Amap_ManAndNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_AND]; } +static inline int Amap_ManXorNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_XOR]; } +static inline int Amap_ManMuxNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_MUX]; } +static inline int Amap_ManObjNum( Amap_Man_t * p ) { return Vec_PtrSize(p->vObjs); } +static inline int Amap_ManNodeNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_AND] + p->nObjs[AMAP_OBJ_XOR] + p->nObjs[AMAP_OBJ_MUX]; } + +static inline Amap_Obj_t * Amap_ManConst1( Amap_Man_t * p ) { return p->pConst1; } +static inline Amap_Obj_t * Amap_ManPi( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vPis, i ); } +static inline Amap_Obj_t * Amap_ManPo( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vPos, i ); } +static inline Amap_Obj_t * Amap_ManObj( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } + +static inline int Amap_ObjIsConst1( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_CONST1; } +static inline int Amap_ObjIsPi( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_PI; } +static inline int Amap_ObjIsPo( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_PO; } +static inline int Amap_ObjIsAnd( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_AND; } +static inline int Amap_ObjIsXor( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_XOR; } +static inline int Amap_ObjIsMux( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_MUX; } +static inline int Amap_ObjIsNode( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_AND || pObj->Type == AMAP_OBJ_XOR || pObj->Type == AMAP_OBJ_MUX; } + +static inline int Amap_ObjToLit( Amap_Obj_t * pObj ) { return Amap_Var2Lit( Amap_Regular(pObj)->Id, Amap_IsComplement(pObj) ); } +static inline Amap_Obj_t * Amap_ObjFanin0( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[0])); } +static inline Amap_Obj_t * Amap_ObjFanin1( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[1])); } +static inline Amap_Obj_t * Amap_ObjFanin2( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[2])); } +static inline int Amap_ObjFaninC0( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[0]); } +static inline int Amap_ObjFaninC1( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[1]); } +static inline int Amap_ObjFaninC2( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[2]); } +static inline void * Amap_ObjCopy( Amap_Obj_t * pObj ) { return pObj->pData; } +static inline int Amap_ObjLevel( Amap_Obj_t * pObj ) { return pObj->Level; } +static inline void Amap_ObjSetLevel( Amap_Obj_t * pObj, int Level ) { pObj->Level = Level; } +static inline void Amap_ObjSetCopy( Amap_Obj_t * pObj, void * pCopy ) { pObj->pData = pCopy; } +static inline Amap_Obj_t * Amap_ObjChoice( Amap_Man_t * p, Amap_Obj_t * pObj ) { return pObj->Equiv? Amap_ManObj(p, pObj->Equiv) : NULL; } +static inline void Amap_ObjSetChoice( Amap_Obj_t * pObj, Amap_Obj_t * pEqu){ assert(pObj->Equiv==0); pObj->Equiv = pEqu->Id; } +static inline int Amap_ObjPhaseReal( Amap_Obj_t * pObj ) { return Amap_Regular(pObj)->fPhase ^ Amap_IsComplement(pObj); } +static inline int Amap_ObjRefsTotal( Amap_Obj_t * pObj ) { return pObj->nFouts[0] + pObj->nFouts[1]; } + +static inline Amap_Gat_t * Amap_LibGate( Amap_Lib_t * p, int i ) { return Vec_PtrEntry(p->vGates, i); } +static inline Amap_Nod_t * Amap_LibNod( Amap_Lib_t * p, int i ) { return p->pNodes + i; } + +// returns pointer to the next cut (internal cuts only) +static inline Amap_Cut_t * Amap_ManCutNext( Amap_Cut_t * pCut ) +{ return (Amap_Cut_t *)(((int *)pCut)+pCut->nFans+1); } +// returns pointer to the place of the next cut (temporary cuts only) +static inline Amap_Cut_t ** Amap_ManCutNextP( Amap_Cut_t * pCut ) +{ return (Amap_Cut_t **)(((int *)pCut)+pCut->nFans+1); } + +extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Amap_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPis, pObj, i ) +// iterator over the primary outputs +#define Amap_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Amap_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else +// iterator over all nodes +#define Amap_ManForEachNode( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL || !Amap_ObjIsNode(pObj) ) {} else + +// iterator through all gates of the library +#define Amap_LibForEachGate( pLib, pGate, i ) \ + Vec_PtrForEachEntry( pLib->vGates, pGate, i ) +// iterator through all pins of the gate +#define Amap_GateForEachPin( pGate, pPin ) \ + for ( pPin = pGate->Pins; pPin < pGate->Pins + pGate->nPins; pPin++ ) + +// iterator through all cuts of the node +#define Amap_NodeForEachCut( pNode, pCut, i ) \ + for ( i = 0, pCut = (Amap_Cut_t *)pNode->pData; i < (int)pNode->nCuts; \ + i++, pCut = Amap_ManCutNext(pCut) ) + +// iterator through all sets of one library node +#define Amap_LibNodeForEachSet( pNod, pSet ) \ + for ( pSet = pNod->pSets; pSet; pSet = pSet->pNext ) + +// iterates through each fanin of the match +#define Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i ) \ + for ( i = 0; i < (int)(pM)->pCut->nFans && \ + ((pFanin = Amap_ManObj((p), Amap_Lit2Var((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])]))), 1) && \ + ((fCompl = Amap_LitIsCompl((pM)->pSet->Ins[i]) ^ Amap_LitIsCompl((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])])), 1); \ + i++ ) + +// iterates through each fanin of the match +#define Amap_MatchForEachFanin( p, pM, pFanin, i ) \ + for ( i = 0; i < (int)(pM)->pCut->nFans && \ + ((pFanin = Amap_ManObj((p), Amap_Lit2Var((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])]))), 1); \ + i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== amapCore.c ==========================================================*/ +/*=== amapGraph.c ==========================================================*/ +extern Amap_Obj_t * Amap_ManCreatePi( Amap_Man_t * p ); +extern Amap_Obj_t * Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 ); +extern Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ); +extern Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ); +extern Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFanC, Amap_Obj_t * pFan1, Amap_Obj_t * pFan0 ); +extern void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj ); +extern void Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig ); +/*=== amapLib.c ==========================================================*/ +extern Amap_Lib_t * Amap_LibAlloc(); +extern void Amap_LibFree( Amap_Lib_t * p ); +extern int Amap_LibNumPinsMax( Amap_Lib_t * p ); +extern void Amap_LibWrite( FILE * pFile, Amap_Lib_t * pLib, int fPrintDsd ); +extern Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose ); +extern void Amap_LibPrintSelectedGates( Amap_Lib_t * p, int fAllGates ); +extern Amap_Lib_t * Amap_LibReadAndPrepare( char * pFileName, int fVerbose, int fVeryVerbose ); +/*=== amapMan.c ==========================================================*/ +extern Amap_Man_t * Amap_ManStart( int nNodes ); +extern void Amap_ManStop( Amap_Man_t * p ); +/*=== amapMatch.c ==========================================================*/ +extern void Amap_ManMap( Amap_Man_t * p ); +/*=== amapMerge.c ==========================================================*/ +extern void Amap_ManMerge( Amap_Man_t * p ); +/*=== amapOutput.c ==========================================================*/ +extern Vec_Ptr_t * Amap_ManProduceMapped( Amap_Man_t * p ); +/*=== amapParse.c ==========================================================*/ +extern int Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose ); +/*=== amapPerm.c ==========================================================*/ +/*=== amapRead.c ==========================================================*/ +extern Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose ); +/*=== amapRule.c ==========================================================*/ +extern short * Amap_LibTableFindNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor ); +extern void Amap_LibCreateRules( Amap_Lib_t * p, int fVeryVerbose ); +/*=== amapUniq.c ==========================================================*/ +extern int Amap_LibFindNode( Amap_Lib_t * pLib, int iFan0, int iFan1, int fXor ); +extern int Amap_LibFindMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ); +extern int Amap_LibCreateVar( Amap_Lib_t * p ); +extern int Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor ); +extern int Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ); +extern int ** Amap_LibLookupTableAlloc( Vec_Ptr_t * vVec, int fVerbose ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/map/amap/amapLib.c b/src/map/amap/amapLib.c new file mode 100644 index 00000000..816f0703 --- /dev/null +++ b/src/map/amap/amapLib.c @@ -0,0 +1,361 @@ +/**CFile**************************************************************** + + FileName [amapLib.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Standard-cell library.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocs a library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Lib_t * Amap_LibAlloc() +{ + Amap_Lib_t * p; + p = (Amap_Lib_t *)ALLOC( Amap_Lib_t, 1 ); + memset( p, 0, sizeof(Amap_Lib_t) ); + p->vGates = Vec_PtrAlloc( 100 ); + p->pMemGates = Aig_MmFlexStart(); + p->pMemSet = Aig_MmFlexStart(); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocs a library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibFree( Amap_Lib_t * p ) +{ + if ( p == NULL ) + return; + if ( p->vSelect ) + Vec_PtrFree( p->vSelect ); + if ( p->vSorted ) + Vec_PtrFree( p->vSorted ); + if ( p->vGates ) + Vec_PtrFree( p->vGates ); + if ( p->vRules ) + Vec_VecFree( (Vec_Vec_t *)p->vRules ); + if ( p->vRulesX ) + Vec_VecFree( (Vec_Vec_t *)p->vRulesX ); + if ( p->vRules3 ) + Vec_IntFree( p->vRules3 ); + Aig_MmFlexStop( p->pMemGates, 0 ); + Aig_MmFlexStop( p->pMemSet, 0 ); + FREE( p->pRules ); + FREE( p->pRulesX ); + FREE( p->pNodes ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the largest gate size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibNumPinsMax( Amap_Lib_t * p ) +{ + Amap_Gat_t * pGate; + int i, Counter = 0; + Amap_LibForEachGate( p, pGate, i ) + if ( Counter < (int)pGate->nPins ) + Counter = pGate->nPins; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Writes one pin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibWritePin( FILE * pFile, Amap_Pin_t * pPin ) +{ + char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" }; + fprintf( pFile, " PIN " ); + fprintf( pFile, "%9s ", pPin->pName ); + fprintf( pFile, "%10s ", pPhaseNames[pPin->Phase] ); + fprintf( pFile, "%6d ", (int)pPin->dLoadInput ); + fprintf( pFile, "%6d ", (int)pPin->dLoadMax ); + fprintf( pFile, "%6.2f ", pPin->dDelayBlockRise ); + fprintf( pFile, "%6.2f ", pPin->dDelayFanoutRise ); + fprintf( pFile, "%6.2f ", pPin->dDelayBlockFall ); + fprintf( pFile, "%6.2f", pPin->dDelayFanoutFall ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes one gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibWriteGate( FILE * pFile, Amap_Gat_t * pGate, int fPrintDsd ) +{ + Amap_Pin_t * pPin; + fprintf( pFile, "GATE " ); + fprintf( pFile, "%12s ", pGate->pName ); + fprintf( pFile, "%10.2f ", pGate->dArea ); + fprintf( pFile, "%s=%s;\n", pGate->pOutName, pGate->pForm ); + if ( fPrintDsd ) + { + if ( pGate->pFunc == NULL ) + printf( "Truth table is not available.\n" ); + else + Kit_DsdPrintFromTruth( pGate->pFunc, pGate->nPins ); + } + Amap_GateForEachPin( pGate, pPin ) + Amap_LibWritePin( pFile, pPin ); +} + +/**Function************************************************************* + + Synopsis [Writes library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibWrite( FILE * pFile, Amap_Lib_t * pLib, int fPrintDsd ) +{ + Amap_Gat_t * pGate; + int i; + fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName ); + Amap_LibForEachGate( pLib, pGate, i ) + Amap_LibWriteGate( pFile, pGate, fPrintDsd ); +} + +/**Function************************************************************* + + Synopsis [Compares two gates by area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibCompareGatesByArea( Amap_Gat_t ** pp1, Amap_Gat_t ** pp2 ) +{ + double Diff = (*pp1)->dArea - (*pp2)->dArea; + if ( Diff < 0.0 ) + return -1; + if ( Diff > 0.0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compares gates by area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Amap_LibSortGatesByArea( Amap_Lib_t * pLib ) +{ + Vec_Ptr_t * vSorted; + vSorted = Vec_PtrDup( pLib->vGates ); + qsort( (void *)Vec_PtrArray(vSorted), Vec_PtrSize(vSorted), sizeof(void *), + (int (*)(const void *, const void *)) Amap_LibCompareGatesByArea ); + return vSorted; +} + +/**Function************************************************************* + + Synopsis [Finds min-area gate with the given function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Gat_t * Amap_LibFindGate( Amap_Lib_t * p, unsigned uTruth ) +{ + Amap_Gat_t * pGate; + int i; + Vec_PtrForEachEntry( p->vSorted, pGate, i ) + if ( pGate->nPins <= 5 && pGate->pFunc[0] == uTruth ) + return pGate; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Selects gates useful for area-only mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose ) +{ + Vec_Ptr_t * vSelect; + Amap_Gat_t * pGate, * pGate2; + int i, k, clk = clock(); + p->pGate0 = Amap_LibFindGate( p, 0 ); + p->pGate1 = Amap_LibFindGate( p, ~0 ); + p->pGateBuf = Amap_LibFindGate( p, 0xAAAAAAAA ); + p->pGateInv = Amap_LibFindGate( p, ~0xAAAAAAAA ); + vSelect = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( p->vSorted, pGate, i ) + { + if ( pGate->pFunc == NULL ) + continue; + Vec_PtrForEachEntryStop( p->vSorted, pGate2, k, i ) + { + if ( pGate2->pFunc == NULL ) + continue; + if ( pGate2->nPins != pGate->nPins ) + continue; + if ( !memcmp( pGate2->pFunc, pGate->pFunc, sizeof(unsigned) * Aig_TruthWordNum(pGate->nPins) ) ) + break; + } + if ( k < i ) + continue; + Vec_PtrPush( vSelect, pGate ); + } + return vSelect; +} + +/**Function************************************************************* + + Synopsis [Selects gates useful for area-only mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibPrintSelectedGates( Amap_Lib_t * p, int fAllGates ) +{ + Vec_Ptr_t * vArray; + Amap_Gat_t * pGate; + int i; + vArray = fAllGates? p->vGates : p->vSelect; + Vec_PtrForEachEntry( vArray, pGate, i ) + { + printf( "Gate %4d : %15s Area = %9.2f\n", pGate->Id, pGate->pName, pGate->dArea ); + printf( " Formula: %s=%s\n", pGate->pOutName, pGate->pForm ); + printf( " DSD: " ); + Kit_DsdPrintFromTruth( pGate->pFunc, pGate->nPins ); + } +} + +/**Function************************************************************* + + Synopsis [Parses equations for the gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Lib_t * Amap_LibReadAndPrepare( char * pFileName, int fVerbose, int fVeryVerbose ) +{ + Amap_Lib_t * p; + int clk = clock(); + p = Amap_LibReadFile( pFileName, fVerbose ); + if ( fVerbose ) + printf( "Read %d gates from file \"%s\".\n", Vec_PtrSize(p->vGates), pFileName ); + if ( p == NULL ) + return NULL; + if ( !Amap_LibParseEquations( p, fVerbose ) ) + { + Amap_LibFree( p ); + return NULL; + } + p->vSorted = Amap_LibSortGatesByArea( p ); + p->vSelect = Amap_LibSelectGates( p, fVerbose ); + if ( fVerbose ) + { + printf( "Selected %d functionally unique gates. ", + Vec_PtrSize(p->vSelect), Vec_PtrSize(p->vSorted) ); + PRT( "Time", clock() - clk ); + } + clk = clock(); + Amap_LibCreateRules( p, fVeryVerbose ); + if ( fVerbose ) + { + printf( "Created %d rules and %d matches. ", + p->nNodes, p->nSets ); + PRT( "Time", clock() - clk ); + } + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapMan.c b/src/map/amap/amapMan.c new file mode 100644 index 00000000..521b4ffd --- /dev/null +++ b/src/map/amap/amapMan.c @@ -0,0 +1,99 @@ +/**CFile**************************************************************** + + FileName [amapMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Mapping manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Man_t * Amap_ManStart( int nNodes ) +{ + Amap_Man_t * p; + // start the manager + p = ALLOC( Amap_Man_t, 1 ); + memset( p, 0, sizeof(Amap_Man_t) ); + p->fEpsilonInternal = (float)0.01; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + p->vObjs = Vec_PtrAlloc( 100 ); + p->vTemp = Vec_IntAlloc( 100 ); + p->vCuts0 = Vec_PtrAlloc( 100 ); + p->vCuts1 = Vec_PtrAlloc( 100 ); + p->vCuts2 = Vec_PtrAlloc( 100 ); + // prepare the memory manager + p->pMemObj = Aig_MmFixedStart( sizeof(Amap_Obj_t), nNodes ); + p->pMemCuts = Aig_MmFlexStart(); + p->pMemCutBest = Aig_MmFlexStart(); + p->pMemTemp = Aig_MmFlexStart(); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManStop( Amap_Man_t * p ) +{ + Vec_PtrFree( p->vPis ); + Vec_PtrFree( p->vPos ); + Vec_PtrFree( p->vObjs ); + Vec_PtrFree( p->vCuts0 ); + Vec_PtrFree( p->vCuts1 ); + Vec_PtrFree( p->vCuts2 ); + Vec_IntFree( p->vTemp ); + Aig_MmFixedStop( p->pMemObj, 0 ); + Aig_MmFlexStop( p->pMemCuts, 0 ); + Aig_MmFlexStop( p->pMemCutBest, 0 ); + Aig_MmFlexStop( p->pMemTemp, 0 ); + FREE( p->pMatsTemp ); + FREE( p->ppCutsTemp ); + FREE( p->pCutsPi ); + free( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapMatch.c b/src/map/amap/amapMatch.c new file mode 100644 index 00000000..0b15a931 --- /dev/null +++ b/src/map/amap/amapMatch.c @@ -0,0 +1,538 @@ +/**CFile**************************************************************** + + FileName [amapMatch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapMatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Duplicates the cut using new memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Cut_t * Amap_ManDupCut( Amap_Man_t * p, Amap_Cut_t * pCut ) +{ + Amap_Cut_t * pNew; + int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * pCut->nFans; + pNew = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCutBest, nBytes ); + memcpy( pNew, pCut, nBytes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Starts the match with cut and set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Amap_ManMatchStart( Amap_Mat_t * p, Amap_Cut_t * pCut, Amap_Set_t * pSet ) +{ + memset( p, 0, sizeof(Amap_Mat_t) ); + p->pCut = pCut; + p->pSet = pSet; +} + +/**Function************************************************************* + + Synopsis [Cleans reference counters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManCleanRefs( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + int i; + Amap_ManForEachObj( p, pObj, i ) + pObj->nFouts[0] = pObj->nFouts[1] = 0; +} + +/**Function************************************************************* + + Synopsis [Computes delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Amap_ManMaxDelay( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + float Delay = 0.0; + int i; + Amap_ManForEachPo( p, pObj, i ) + Delay = AIG_MAX( Delay, Amap_ObjFanin0(p,pObj)->Best.Delay ); + return Delay; +} + +/**Function************************************************************* + + Synopsis [Cleans reference counters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManCleanData( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + int i; +// Amap_ManForEachNode( p, pObj, i ) +// FREE( pObj->pData ); + Amap_ManForEachObj( p, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Compute nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Amap_ManComputeMapping_rec( Amap_Man_t * p, Amap_Obj_t * pObj, int fCompl ) +{ + Amap_Mat_t * pM = &pObj->Best; + Amap_Obj_t * pFanin; + Amap_Gat_t * pGate; + int i, iFanin, fComplFanin; + float Area; + if ( pObj->nFouts[fCompl]++ + pObj->nFouts[!fCompl] > 0 ) + return 0.0; + if ( Amap_ObjIsPi(pObj) || Amap_ObjIsConst1(pObj) ) + return 0.0; + pGate = Amap_LibGate( p->pLib, pM->pSet->iGate ); + assert( pGate->nPins == pM->pCut->nFans ); + Area = pGate->dArea; + for ( i = 0; i < (int)pGate->nPins; i++ ) + { + iFanin = Amap_Lit2Var( pM->pSet->Ins[i] ); + pFanin = Amap_ManObj( p, Amap_Lit2Var(pM->pCut->Fans[iFanin]) ); + fComplFanin = Amap_LitIsCompl( pM->pSet->Ins[i] ) ^ Amap_LitIsCompl( pM->pCut->Fans[iFanin] ); + Area += Amap_ManComputeMapping_rec( p, pFanin, fComplFanin ); + } + return Area; +} + +/**Function************************************************************* + + Synopsis [Compute nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Amap_ManComputeMapping( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + float Area = 0.0; + int i; + Amap_ManCleanRefs( p ); + Amap_ManForEachPo( p, pObj, i ) + Area += Amap_ManComputeMapping_rec( p, Amap_ObjFanin0(p, pObj), Amap_ObjFaninC0(pObj) ); + return Area; +} + +/**Function************************************************************* + + Synopsis [Counts the number of inverters to be added.] + + Description [Should be called after mapping has been set.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_ManCountInverters( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + int i, Counter = 0; + Amap_ManForEachObj( p, pObj, i ) + Counter += (int)(pObj->nFouts[!pObj->fPolar] > 0); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Compare two matches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Amap_CutCompare( Amap_Man_t * p, Amap_Mat_t * pM0, Amap_Mat_t * pM1 ) +{ + // compare area flows + if ( pM0->Area < pM1->Area - p->pPars->fEpsilon ) + return -1; + if ( pM0->Area > pM1->Area + p->pPars->fEpsilon ) + return 1; + + // compare average fanouts + if ( pM0->AveFan > pM1->AveFan - p->pPars->fEpsilon ) + return -1; + if ( pM0->AveFan < pM1->AveFan + p->pPars->fEpsilon ) + return 1; + + // compare delay + if ( pM0->Delay < pM1->Delay - p->pPars->fEpsilon ) + return -1; + if ( pM0->Delay > pM1->Delay + p->pPars->fEpsilon ) + return 1; + return 1; +} + +/**Function************************************************************* + + Synopsis [Counts area while dereferencing the match.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Amap_CutAreaDeref( Amap_Man_t * p, Amap_Mat_t * pM ) +{ + Amap_Obj_t * pFanin; + int i, fCompl; + float Area = Amap_LibGate( p->pLib, pM->pSet->iGate )->dArea; + Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i ) + { + assert( Amap_ObjRefsTotal(pFanin) > 0 ); + if ( (int)pFanin->fPolar != fCompl && pFanin->nFouts[fCompl] == 1 ) + Area += p->fAreaInv; + if ( --pFanin->nFouts[fCompl] + pFanin->nFouts[!fCompl] == 0 && Amap_ObjIsNode(pFanin) ) + Area += Amap_CutAreaDeref( p, &pFanin->Best ); + } + return Area; +} + +/**Function************************************************************* + + Synopsis [Counts area while referencing the match.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Amap_CutAreaRef( Amap_Man_t * p, Amap_Mat_t * pM ) +{ + Amap_Obj_t * pFanin; + int i, fCompl; + float Area = Amap_LibGate( p->pLib, pM->pSet->iGate )->dArea; + Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i ) + { + assert( Amap_ObjRefsTotal(pFanin) >= 0 ); + if ( (int)pFanin->fPolar != fCompl && pFanin->nFouts[fCompl] == 0 ) + Area += p->fAreaInv; + if ( pFanin->nFouts[fCompl]++ + pFanin->nFouts[!fCompl] == 0 && Amap_ObjIsNode(pFanin) ) + Area += Amap_CutAreaRef( p, &pFanin->Best ); + } + return Area; +} + +/**Function************************************************************* + + Synopsis [Derives area of the match for a non-referenced node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Amap_CutAreaDerefed( Amap_Man_t * p, Amap_Obj_t * pNode, Amap_Mat_t * pM ) +{ + float aResult, aResult2; + int fComplNew; + aResult2 = Amap_CutAreaRef( p, pM ); + aResult = Amap_CutAreaDeref( p, pM ); + assert( aResult > aResult2 - p->fEpsilonInternal ); + assert( aResult < aResult2 + p->fEpsilonInternal ); + // if node is needed in another polarity, add inverter + fComplNew = pM->pCut->fInv ^ pM->pSet->fInv; + if ( pNode->nFouts[fComplNew] == 0 && pNode->nFouts[!fComplNew] > 0 ) + aResult += p->fAreaInv; + return aResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Amap_CutAreaTest( Amap_Man_t * p, Amap_Obj_t * pNode ) +{ + float aResult, aResult2; + if ( Amap_ObjRefsTotal(pNode) == 0 ) + { + aResult2 = Amap_CutAreaRef( p, &pNode->Best ); + aResult = Amap_CutAreaDeref( p, &pNode->Best ); + assert( aResult > aResult2 - p->fEpsilonInternal ); + assert( aResult < aResult2 + p->fEpsilonInternal ); + } + else + { + aResult = Amap_CutAreaDeref( p, &pNode->Best ); + aResult2 = Amap_CutAreaRef( p, &pNode->Best ); + assert( aResult > aResult2 - p->fEpsilonInternal ); + assert( aResult < aResult2 + p->fEpsilonInternal ); + } +} + +/**Function************************************************************* + + Synopsis [Derives parameters for the match.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Amap_ManMatchGetFlows( Amap_Man_t * p, Amap_Mat_t * pM ) +{ + Amap_Mat_t * pMFanin; + Amap_Obj_t * pFanin; + Amap_Gat_t * pGate; + int i; + pGate = Amap_LibGate( p->pLib, pM->pSet->iGate ); + assert( pGate->nPins == pM->pCut->nFans ); + assert( pM->Area == 0.0 ); + pM->Area = pGate->dArea; + pM->AveFan = 0.0; + pM->Delay = 0.0; + Amap_MatchForEachFanin( p, pM, pFanin, i ) + { + pMFanin = &pFanin->Best; + pM->Delay = AIG_MAX( pM->Delay, pMFanin->Delay ); + pM->AveFan += Amap_ObjRefsTotal(pFanin); + if ( Amap_ObjRefsTotal(pFanin) == 0 ) + pM->Area += pMFanin->Area; + else + pM->Area += pMFanin->Area / pFanin->EstRefs; + } + pM->AveFan /= pGate->nPins; + pM->Delay += 1.0; +} + +/**Function************************************************************* + + Synopsis [Derives parameters for the match.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Amap_ManMatchGetExacts( Amap_Man_t * p, Amap_Obj_t * pNode, Amap_Mat_t * pM ) +{ + Amap_Mat_t * pMFanin; + Amap_Obj_t * pFanin; + Amap_Gat_t * pGate; + int i; + pGate = Amap_LibGate( p->pLib, pM->pSet->iGate ); + assert( pGate->nPins == pM->pCut->nFans ); + assert( pM->Area == 0.0 ); + pM->AveFan = 0.0; + pM->Delay = 0.0; + Amap_MatchForEachFanin( p, pM, pFanin, i ) + { + pMFanin = &pFanin->Best; + pM->Delay = AIG_MAX( pM->Delay, pMFanin->Delay ); + pM->AveFan += Amap_ObjRefsTotal(pFanin); + } + pM->AveFan /= pGate->nPins; + pM->Delay += 1.0; + pM->Area = Amap_CutAreaDerefed( p, pNode, pM ); +} + +/**Function************************************************************* + + Synopsis [Computes the best match at each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManMatchNode( Amap_Man_t * p, Amap_Obj_t * pNode, int fFlow, int fRefs ) +{ + Amap_Mat_t M1, M2, * pMBest = &M1, * pMThis = &M2; + Amap_Cut_t * pCut; + Amap_Set_t * pSet; + Amap_Nod_t * pNod; + int i; + if ( fRefs ) + pNode->EstRefs = (float)((2.0 * pNode->EstRefs + Amap_ObjRefsTotal(pNode)) / 3.0); + else + pNode->EstRefs = (float)pNode->nRefs; + if ( fRefs && Amap_ObjRefsTotal(pNode) > 0 ) + Amap_CutAreaDeref( p, &pNode->Best ); + pMBest->pCut = NULL; + Amap_NodeForEachCut( pNode, pCut, i ) + { + if ( pCut->iMat == 0 ) + continue; + pNod = Amap_LibNod( p->pLib, pCut->iMat ); + Amap_LibNodeForEachSet( pNod, pSet ) + { + Amap_ManMatchStart( pMThis, pCut, pSet ); + if ( fFlow ) + Amap_ManMatchGetFlows( p, pMThis ); + else + Amap_ManMatchGetExacts( p, pNode, pMThis ); + if ( pMBest->pCut == NULL || Amap_CutCompare(p, pMBest, pMThis) == 1 ) + *pMBest = *pMThis; + } + } + pNode->fPolar = pMBest->pCut->fInv ^ pMBest->pSet->fInv; + pNode->Best = *pMBest; + pNode->Best.pCut = Amap_ManDupCut( p, pNode->Best.pCut ); + if ( fRefs && Amap_ObjRefsTotal(pNode) > 0 ) + Amap_CutAreaRef( p, &pNode->Best ); +} + +/**Function************************************************************* + + Synopsis [Performs one round of mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManMatch( Amap_Man_t * p, int fFlow, int fRefs ) +{ + Aig_MmFlex_t * pMemOld; + Amap_Obj_t * pObj; + float Area; + int i, nInvs, clk = clock(); + pMemOld = p->pMemCutBest; + p->pMemCutBest = Aig_MmFlexStart(); + Amap_ManForEachNode( p, pObj, i ) + if ( pObj->pData ) + Amap_ManMatchNode( p, pObj, fFlow, fRefs ); + Aig_MmFlexStop( pMemOld, 0 ); + Area = Amap_ManComputeMapping( p ); + nInvs = Amap_ManCountInverters( p ); +if ( p->pPars->fVerbose ) +{ + printf( "Area =%9.2f. Gate =%9.2f. Inv =%9.2f. (%6d.) Delay =%6.2f. ", + Area + nInvs * p->fAreaInv, + Area, nInvs * p->fAreaInv, nInvs, + Amap_ManMaxDelay(p) ); +PRT( "Time ", clock() - clk ); +} + // test procedures +// Amap_ManForEachNode( p, pObj, i ) +// Amap_CutAreaTest( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManMap( Amap_Man_t * p ) +{ + int i; + Amap_ManMerge( p ); + for ( i = 0; i < p->pPars->nIterFlow; i++ ) + Amap_ManMatch( p, 1, i>0 ); + for ( i = 0; i < p->pPars->nIterArea; i++ ) + Amap_ManMatch( p, 0, p->pPars->nIterFlow>0||i>0 ); +/* + for ( i = 0; i < p->pPars->nIterFlow; i++ ) + Amap_ManMatch( p, 1, 1 ); + for ( i = 0; i < p->pPars->nIterArea; i++ ) + Amap_ManMatch( p, 0, 1 ); +*/ + Amap_ManCleanData( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapMerge.c b/src/map/amap/amapMerge.c new file mode 100644 index 00000000..b024616e --- /dev/null +++ b/src/map/amap/amapMerge.c @@ -0,0 +1,521 @@ +/**CFile**************************************************************** + + FileName [amapMerge.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Computing cuts for the node.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates new cut and adds it to storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Cut_t * Amap_ManSetupPis( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + Amap_Cut_t * pCut; + int i, nBytes = sizeof(Amap_Cut_t) + sizeof(int); + char * pBuffer = ALLOC( char, Amap_ManPiNum(p) * nBytes ); + Amap_ManForEachPi( p, pObj, i ) + { + pCut = (Amap_Cut_t *)( pBuffer + i*nBytes ); + pCut->iMat = 0; + pCut->fInv = 0; + pCut->nFans = 1; + pCut->Fans[0] = Amap_Var2Lit( pObj->Id, 0 ); + pObj->pData = pCut; + pObj->nCuts = 1; + pObj->EstRefs = (float)1.0; + } + return (Amap_Cut_t *)pBuffer; +} + +/**Function************************************************************* + + Synopsis [Creates new cut and adds it to storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Cut_t * Amap_ManCutStore( Amap_Man_t * p, Amap_Cut_t * pCut, int fCompl ) +{ + Amap_Cut_t * pNew; + int iFan, nBytes = sizeof(Amap_Cut_t) + sizeof(int) * pCut->nFans + sizeof(Amap_Cut_t *); + pNew = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes ); + pNew->iMat = pCut->iMat; + pNew->fInv = pCut->fInv ^ fCompl; + pNew->nFans = pCut->nFans; + memcpy( pNew->Fans, pCut->Fans, sizeof(int) * pCut->nFans ); + // add it to storage + iFan = Amap_Var2Lit( pNew->iMat, pNew->fInv ); + if ( p->ppCutsTemp[ iFan ] == NULL ) + Vec_IntPushOrder( p->vTemp, iFan ); + *Amap_ManCutNextP( pNew ) = p->ppCutsTemp[ iFan ]; + p->ppCutsTemp[ iFan ] = pNew; + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creates new cut and adds it to storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Cut_t * Amap_ManCutCreate( Amap_Man_t * p, + Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, int iMat ) +{ + Amap_Cut_t * pCut; + int i, nSize = pCut0->nFans + pCut1->nFans; + int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * nSize + sizeof(Amap_Cut_t *); + assert( pCut0->iMat >= pCut1->iMat ); + pCut = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes ); + pCut->iMat = iMat; + pCut->fInv = 0; + pCut->nFans = nSize; + for ( i = 0; i < (int)pCut0->nFans; i++ ) + pCut->Fans[i] = pCut0->Fans[i]; + for ( i = 0; i < (int)pCut1->nFans; i++ ) + pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i]; + // add it to storage + if ( p->ppCutsTemp[ pCut->iMat ] == NULL ) + Vec_IntPushOrder( p->vTemp, pCut->iMat ); + *Amap_ManCutNextP( pCut ) = p->ppCutsTemp[ pCut->iMat ]; + p->ppCutsTemp[ pCut->iMat ] = pCut; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Creates new cut and adds it to storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Cut_t * Amap_ManCutCreate3( Amap_Man_t * p, + Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, Amap_Cut_t * pCut2, int iMat ) +{ + Amap_Cut_t * pCut; + int i, nSize = pCut0->nFans + pCut1->nFans + pCut2->nFans; + int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * nSize + sizeof(Amap_Cut_t *); + pCut = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes ); + pCut->iMat = iMat; + pCut->fInv = 0; + pCut->nFans = nSize; + for ( i = 0; i < (int)pCut0->nFans; i++ ) + pCut->Fans[i] = pCut0->Fans[i]; + for ( i = 0; i < (int)pCut1->nFans; i++ ) + pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i]; + for ( i = 0; i < (int)pCut2->nFans; i++ ) + pCut->Fans[pCut0->nFans+pCut1->nFans+i] = pCut2->Fans[i]; + // add it to storage + if ( p->ppCutsTemp[ pCut->iMat ] == NULL ) + Vec_IntPushOrder( p->vTemp, pCut->iMat ); + *Amap_ManCutNextP( pCut ) = p->ppCutsTemp[ pCut->iMat ]; + p->ppCutsTemp[ pCut->iMat ] = pCut; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Removes cuts from the temporary storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManCutSaveStored( Amap_Man_t * p, Amap_Obj_t * pNode ) +{ + int * pBuffer; + Amap_Cut_t * pNext, * pCut; + int i, nWords, Entry, nCuts; + assert( pNode->pData == NULL ); + // count memory needed + nCuts = 1; + nWords = 2; + Vec_IntForEachEntry( p->vTemp, Entry, i ) + { + for ( pCut = p->ppCutsTemp[Entry]; pCut; pCut = *Amap_ManCutNextP(pCut) ) + { + nCuts++; + nWords += pCut->nFans + 1; + } + } + p->nBytesUsed += 4*nWords; + // allocate memory + pBuffer = (int *)Aig_MmFlexEntryFetch( p->pMemCuts, 4*nWords ); + pNext = (Amap_Cut_t *)pBuffer; + // add the first cut + pNext->iMat = 0; + pNext->fInv = 0; + pNext->nFans = 1; + pNext->Fans[0] = Amap_Var2Lit(pNode->Id, 0); + pNext = (Amap_Cut_t *)(pBuffer + 2); + // add other cuts + Vec_IntForEachEntry( p->vTemp, Entry, i ) + { + for ( pCut = p->ppCutsTemp[Entry]; pCut; pCut = *Amap_ManCutNextP(pCut) ) + { + memcpy( pNext, pCut, sizeof(int) * (pCut->nFans + 1) ); + pNext = (Amap_Cut_t *)((int *)pNext + pCut->nFans + 1); + } + p->ppCutsTemp[Entry] = NULL; + } + assert( (int *)pNext - pBuffer == nWords ); + // restore the storage + Vec_IntClear( p->vTemp ); + Aig_MmFlexRestart( p->pMemTemp ); + for ( i = 0; i < 2*p->pLib->nNodes; i++ ) + if ( p->ppCutsTemp[i] != NULL ) + printf( "Amap_ManCutSaveStored(): Error!\n" ); + pNode->pData = (Amap_Cut_t *)pBuffer; + pNode->nCuts = nCuts; +// printf("%d ", nCuts ); + // verify cuts + pCut = NULL; + Amap_NodeForEachCut( pNode, pNext, i ) +// for ( i = 0, pNext = (Amap_Cut_t *)pNode->pData; i < (int)pNode->nCuts; +// i++, pNext = Amap_ManCutNext(pNext) ) + { + assert( pCut == NULL || pCut->iMat <= pNext->iMat ); + pCut = pNext; + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of possible new cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_ManMergeCountCuts( Amap_Man_t * p, Amap_Obj_t * pNode ) +{ + Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode ); + Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode ); + Amap_Cut_t * pCut0, * pCut1; + int Entry, c0, c1, iCompl0, iCompl1, iFan0, iFan1; + int Counter = 1; + Amap_NodeForEachCut( pFanin0, pCut0, c0 ) + Amap_NodeForEachCut( pFanin1, pCut1, c1 ) + { + iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode); + iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode); + iFan0 = !pCut0->iMat? 0: Amap_Var2Lit( pCut0->iMat, iCompl0 ); + iFan1 = !pCut1->iMat? 0: Amap_Var2Lit( pCut1->iMat, iCompl1 ); + Entry = Amap_LibFindNode( p->pLib, iFan0, iFan1, pNode->Type == AMAP_OBJ_XOR ); + Counter += ( Entry >=0 ); +// if ( Entry >=0 ) +// printf( "Full: %d + %d = %d\n", iFan0, iFan1, Entry ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Print cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManPrintCuts( Amap_Obj_t * pNode ) +{ + Amap_Cut_t * pCut; + int c, i; + printf( "NODE %5d : Type = ", pNode->Id ); + if ( pNode->Type == AMAP_OBJ_AND ) + printf( "AND" ); + else if ( pNode->Type == AMAP_OBJ_XOR ) + printf( "XOR" ); + else if ( pNode->Type == AMAP_OBJ_MUX ) + printf( "MUX" ); + printf( " Cuts = %d\n", pNode->nCuts ); + Amap_NodeForEachCut( pNode, pCut, c ) + { + printf( "%3d : Mat= %3d Inv=%d ", c, pCut->iMat, pCut->fInv ); + for ( i = 0; i < (int)pCut->nFans; i++ ) + printf( "%d%c ", Amap_Lit2Var(pCut->Fans[i]), Amap_LitIsCompl(pCut->Fans[i])?'-':'+' ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Derives cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManMergeNodeChoice( Amap_Man_t * p, Amap_Obj_t * pNode ) +{ + Amap_Obj_t * pTemp; + Amap_Cut_t * pCut; + int c; + // go through the nodes of the choice node + for ( pTemp = pNode; pTemp; pTemp = Amap_ObjChoice(p, pTemp) ) + { + Amap_NodeForEachCut( pTemp, pCut, c ) + if ( pCut->iMat ) + Amap_ManCutStore( p, pCut, pNode->fPhase ^ pTemp->fPhase ); + pTemp->pData = NULL; + } + Amap_ManCutSaveStored( p, pNode ); + +// Amap_ManPrintCuts( pNode ); +} + +/**Function************************************************************* + + Synopsis [Derives cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_ManFindCut( Amap_Obj_t * pNode, Amap_Obj_t * pFanin, int fComplFanin, int Val, Vec_Ptr_t * vCuts ) +{ + Amap_Cut_t * pCut; + int c, iCompl, iFan; + Vec_PtrClear( vCuts ); + Amap_NodeForEachCut( pFanin, pCut, c ) + { + iCompl = pCut->fInv ^ fComplFanin; + iFan = !pCut->iMat? 0: Amap_Var2Lit( pCut->iMat, iCompl ); + if ( iFan == Val ) + Vec_PtrPush( vCuts, pCut ); + } + return Vec_PtrSize(vCuts) == 0; +} + +/**Function************************************************************* + + Synopsis [Derives cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManMergeNodeCutsMux( Amap_Man_t * p, Amap_Obj_t * pNode ) +{ + Vec_Int_t * vRules = p->pLib->vRules3; + Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode ); + Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode ); + Amap_Obj_t * pFanin2 = Amap_ObjFanin2( p, pNode ); + int fComplFanin0 = Amap_ObjFaninC0( pNode ); + int fComplFanin1 = Amap_ObjFaninC1( pNode ); + int fComplFanin2 = Amap_ObjFaninC2( pNode ); + Amap_Cut_t * pCut0, * pCut1, * pCut2; + int x, c0, c1, c2; + assert( pNode->pData == NULL ); + assert( pNode->Type == AMAP_OBJ_MUX ); + assert( pNode->fRepr == 0 ); + // go through the rules + for ( x = 0; x < Vec_IntSize(vRules); x += 4 ) + { + if ( Amap_ManFindCut( pNode, pFanin0, fComplFanin0, Vec_IntEntry(vRules, x), p->vCuts0 ) ) + continue; + if ( Amap_ManFindCut( pNode, pFanin1, fComplFanin1, Vec_IntEntry(vRules, x+1), p->vCuts1 ) ) + continue; + if ( Amap_ManFindCut( pNode, pFanin2, fComplFanin2, Vec_IntEntry(vRules, x+2), p->vCuts2 ) ) + continue; + Vec_PtrForEachEntry( p->vCuts0, pCut0, c0 ) + Vec_PtrForEachEntry( p->vCuts1, pCut1, c1 ) + Vec_PtrForEachEntry( p->vCuts2, pCut2, c2 ) + { + Amap_Nod_t * pNod = Amap_LibNod( p->pLib, Vec_IntEntry(vRules, x+3) ); + if ( pNod->pSets == NULL ) + continue; + // complement literals + if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) ) + pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]); + if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) ) + pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]); + if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) ) + pCut2->Fans[0] = Amap_LitNot(pCut2->Fans[0]); + // create new cut + Amap_ManCutCreate3( p, pCut0, pCut1, pCut2, Vec_IntEntry(vRules, x+3) ); + // uncomplement literals + if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) ) + pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]); + if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) ) + pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]); + if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) ) + pCut2->Fans[0] = Amap_LitNot(pCut2->Fans[0]); + } + } + Amap_ManCutSaveStored( p, pNode ); + p->nCutsUsed += pNode->nCuts; + p->nCutsTried3 += pFanin0->nCuts * pFanin1->nCuts * pFanin2->nCuts; + +// Amap_ManPrintCuts( pNode ); +} + +/**Function************************************************************* + + Synopsis [Derives cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManMergeNodeCuts( Amap_Man_t * p, Amap_Obj_t * pNode ) +{ + Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode ); + Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode ); + Amap_Cut_t * pCut0, * pCut1; + int ** pRules, Entry, i, k, c, iCompl0, iCompl1, iFan0, iFan1; + assert( pNode->pData == NULL ); + if ( pNode->Type == AMAP_OBJ_MUX ) + { + Amap_ManMergeNodeCutsMux( p, pNode ); + return; + } + assert( pNode->Type != AMAP_OBJ_MUX ); + pRules = (pNode->Type == AMAP_OBJ_AND)? p->pLib->pRules: p->pLib->pRulesX; + Amap_NodeForEachCut( pFanin0, pCut0, c ) + { + iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode); + iFan0 = !pCut0->iMat? 0: Amap_Var2Lit( pCut0->iMat, iCompl0 ); + // complement literals + if ( pCut0->nFans == 1 && iCompl0 ) + pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]); + // label resulting sets + for ( i = 0; (Entry = pRules[iFan0][i]); i++ ) + p->pMatsTemp[Entry & 0xffff] = (Entry >> 16); + // iterate through the cuts + Amap_NodeForEachCut( pFanin1, pCut1, k ) + { + iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode); + iFan1 = !pCut1->iMat? 0: Amap_Var2Lit( pCut1->iMat, iCompl1 ); + if ( p->pMatsTemp[iFan1] == 0 ) + continue; + // complement literals + if ( pCut1->nFans == 1 && iCompl1 ) + pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]); + // create new cut + if ( iFan0 >= iFan1 ) + Amap_ManCutCreate( p, pCut0, pCut1, p->pMatsTemp[iFan1] ); + else + Amap_ManCutCreate( p, pCut1, pCut0, p->pMatsTemp[iFan1] ); + // uncomplement literals + if ( pCut1->nFans == 1 && iCompl1 ) + pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]); + } + // uncomplement literals + if ( pCut0->nFans == 1 && iCompl0 ) + pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]); + // label resulting sets + for ( i = 0; (Entry = pRules[iFan0][i]); i++ ) + p->pMatsTemp[Entry & 0xffff] = 0; + } + Amap_ManCutSaveStored( p, pNode ); + p->nCutsUsed += pNode->nCuts; + p->nCutsTried += pFanin0->nCuts * pFanin1->nCuts; +// assert( (int)pNode->nCuts == Amap_ManMergeCountCuts(p, pNode) ); + if ( pNode->fRepr ) + Amap_ManMergeNodeChoice( p, pNode ); + +// Amap_ManPrintCuts( pNode ); +} + +/**Function************************************************************* + + Synopsis [Derives cuts for all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_ManMerge( Amap_Man_t * p ) +{ + Amap_Obj_t * pObj; + int i, clk = clock(); + p->pCutsPi = Amap_ManSetupPis( p ); + Amap_ManForEachNode( p, pObj, i ) + Amap_ManMergeNodeCuts( p, pObj ); + if ( p->pPars->fVerbose ) + { + printf( "AIG object is %d bytes. ", sizeof(Amap_Obj_t) ); + printf( "Internal AIG = %5.2f Mb. Cuts = %5.2f Mb.\n", + 1.0*Amap_ManObjNum(p)*sizeof(Amap_Obj_t)/(1<<20), 1.0*p->nBytesUsed/(1<<20) ); + printf( "Node =%6d. Try =%9d. Try3 =%10d. Used =%7d. R =%6.2f. ", + Amap_ManNodeNum(p), p->nCutsTried, p->nCutsTried3, p->nCutsUsed, + 1.0*p->nCutsUsed/Amap_ManNodeNum(p) ); +PRT( "Time ", clock() - clk ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapOutput.c b/src/map/amap/amapOutput.c new file mode 100644 index 00000000..1decc52e --- /dev/null +++ b/src/map/amap/amapOutput.c @@ -0,0 +1,181 @@ +/**CFile**************************************************************** + + FileName [amapOutput.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Core mapping procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapOutput.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline char * Amap_OuputStrsav( Aig_MmFlex_t * p, char * pStr ) +{ return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates structure for storing one gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Out_t * Amap_OutputStructAlloc( Aig_MmFlex_t * pMem, Amap_Gat_t * pGate ) +{ + Amap_Out_t * pRes; + int nFans = pGate? pGate->nPins : 1; + pRes = (Amap_Out_t *)Aig_MmFlexEntryFetch( pMem, sizeof(Amap_Out_t)+sizeof(int)*nFans ); + memset( pRes, 0, sizeof(Amap_Out_t) ); + memset( pRes->pFans, 0xff, sizeof(int)*nFans ); + pRes->pName = pGate? Amap_OuputStrsav( pMem, pGate->pName ) : NULL; + pRes->nFans = nFans; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Returns mapped network as an array of structures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Amap_ManProduceMapped( Amap_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_MmFlex_t * pMem; + Amap_Obj_t * pObj, * pFanin; + Amap_Gat_t * pGate; + Amap_Out_t * pRes; + int i, k, iFanin, fCompl; + float TotalArea = 0.0; + pMem = Aig_MmFlexStart(); + // create mapping object for each node used in the mapping + vNodes = Vec_PtrAlloc( 10 ); + Amap_ManForEachObj( p, pObj, i ) + { + if ( Amap_ObjIsPi(pObj) ) + { + assert( pObj->fPolar == 0 ); + pRes = Amap_OutputStructAlloc( pMem, NULL ); + pRes->Type = -1; + pRes->nFans = 0; + // save this structure + pObj->iData = Vec_PtrSize( vNodes ); + Vec_PtrPush( vNodes, pRes ); + // create invertor if needed + if ( pObj->nFouts[1] ) // this PI is used in the neg polarity + { + pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGateInv ); + pRes->pFans[0] = pObj->iData; + // save this structure + Vec_PtrPush( vNodes, pRes ); + TotalArea += p->pLib->pGateInv->dArea; + } + continue; + } + if ( Amap_ObjIsNode(pObj) ) + { + // skip the node that is not used in the mapping + if ( Amap_ObjRefsTotal(pObj) == 0 ) + continue; + // get the gate + pGate = Amap_LibGate( p->pLib, pObj->Best.pSet->iGate ); + assert( pGate->nPins == pObj->Best.pCut->nFans ); + // allocate structure + pRes = Amap_OutputStructAlloc( pMem, pGate ); + Amap_MatchForEachFaninCompl( p, &pObj->Best, pFanin, fCompl, k ) + { + assert( Amap_ObjRefsTotal(pFanin) ); + if ( (int)pFanin->fPolar == fCompl ) + pRes->pFans[k] = pFanin->iData; + else + pRes->pFans[k] = pFanin->iData + 1; + } + // save this structure + pObj->iData = Vec_PtrSize( vNodes ); + Vec_PtrPush( vNodes, pRes ); + TotalArea += pGate->dArea; + // create invertor if needed + if ( pObj->nFouts[!pObj->fPolar] ) // needed in the opposite polarity + { + pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGateInv ); + pRes->pFans[0] = pObj->iData; + // save this structure + Vec_PtrPush( vNodes, pRes ); + TotalArea += p->pLib->pGateInv->dArea; + } + continue; + } + if ( Amap_ObjIsPo(pObj) ) + { + assert( pObj->fPolar == 0 ); + pFanin = Amap_ObjFanin0(p, pObj); + assert( Amap_ObjRefsTotal(pFanin) ); + if ( Amap_ObjIsConst1(pFanin) ) + { // create constant node + if ( Amap_ObjFaninC0(pObj) ) + { + pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGate0 ); + TotalArea += p->pLib->pGate0->dArea; + } + else + { + pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGate1 ); + TotalArea += p->pLib->pGate1->dArea; + } + // save this structure + iFanin = Vec_PtrSize( vNodes ); + Vec_PtrPush( vNodes, pRes ); + } + else + { + if ( (int)pFanin->fPolar == Amap_ObjFaninC0(pObj) ) + iFanin = pFanin->iData; + else + iFanin = pFanin->iData + 1; + } + // create PO node + pRes = Amap_OutputStructAlloc( pMem, NULL ); + pRes->Type = 1; + pRes->pFans[0] = iFanin; + // save this structure + Vec_PtrPush( vNodes, pRes ); + } + } + // return memory manager in the last entry of the array + Vec_PtrPush( vNodes, pMem ); + return vNodes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapParse.c b/src/map/amap/amapParse.c new file mode 100644 index 00000000..262fbd5a --- /dev/null +++ b/src/map/amap/amapParse.c @@ -0,0 +1,457 @@ +/**CFile**************************************************************** + + FileName [amapParse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Parses representations of gates.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapParse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the list of operation symbols to be used in expressions +#define AMAP_EQN_SYM_OPEN '(' // opening paranthesis +#define AMAP_EQN_SYM_CLOSE ')' // closing paranthesis +#define AMAP_EQN_SYM_CONST0 '0' // constant 0 +#define AMAP_EQN_SYM_CONST1 '1' // constant 1 +#define AMAP_EQN_SYM_NEG '!' // negation before the variable +#define AMAP_EQN_SYM_NEGAFT '\'' // negation after the variable +#define AMAP_EQN_SYM_AND '*' // logic AND +#define AMAP_EQN_SYM_XOR '^' // logic XOR +#define AMAP_EQN_SYM_OR '+' // logic OR + +// the list of opcodes (also specifying operation precedence) +#define AMAP_EQN_OPER_NEG 10 // negation +#define AMAP_EQN_OPER_AND 9 // logic AND +#define AMAP_EQN_OPER_XOR 8 // logic XOR +#define AMAP_EQN_OPER_OR 7 // logic OR +#define AMAP_EQN_OPER_MARK 1 // OpStack token standing for an opening paranthesis + +// these are values of the internal Flag +#define AMAP_EQN_FLAG_START 1 // after the opening parenthesis +#define AMAP_EQN_FLAG_VAR 2 // after operation is received +#define AMAP_EQN_FLAG_OPER 3 // after operation symbol is received +#define AMAP_EQN_FLAG_ERROR 4 // when error is detected + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs the operation on the top entries in the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Amap_ParseFormulaOper( Hop_Man_t * pMan, Vec_Ptr_t * pStackFn, int Oper ) +{ + Hop_Obj_t * gArg1, * gArg2, * gFunc; + // perform the given operation + gArg2 = Vec_PtrPop( pStackFn ); + gArg1 = Vec_PtrPop( pStackFn ); + if ( Oper == AMAP_EQN_OPER_AND ) + gFunc = Hop_And( pMan, gArg1, gArg2 ); + else if ( Oper == AMAP_EQN_OPER_OR ) + gFunc = Hop_Or( pMan, gArg1, gArg2 ); + else if ( Oper == AMAP_EQN_OPER_XOR ) + gFunc = Hop_Exor( pMan, gArg1, gArg2 ); + else + return NULL; +// Cudd_Ref( gFunc ); +// Cudd_RecursiveDeref( dd, gArg1 ); +// Cudd_RecursiveDeref( dd, gArg2 ); + Vec_PtrPush( pStackFn, gFunc ); + return gFunc; +} + +/**Function************************************************************* + + Synopsis [Derives the AIG corresponding to the equation.] + + Description [Takes the stream to output messages, the formula, the vector + of variable names and the AIG manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Amap_ParseFormula( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ) +{ + char * pFormula; + Vec_Ptr_t * pStackFn; + Vec_Int_t * pStackOp; + Hop_Obj_t * gFunc; + char * pTemp, * pName; + int nParans, fFound, Flag; + int Oper, Oper1, Oper2; + int i, v; + + // make sure that the number of opening and closing parantheses is the same + nParans = 0; + for ( pTemp = pFormInit; *pTemp; pTemp++ ) + if ( *pTemp == '(' ) + nParans++; + else if ( *pTemp == ')' ) + nParans--; + if ( nParans != 0 ) + { + fprintf( pOutput, "Amap_ParseFormula(): Different number of opening and closing parantheses ().\n" ); + return NULL; + } + + // copy the formula + pFormula = ALLOC( char, strlen(pFormInit) + 3 ); + sprintf( pFormula, "(%s)", pFormInit ); + + // start the stacks + pStackFn = Vec_PtrAlloc( 100 ); + pStackOp = Vec_IntAlloc( 100 ); + + Flag = AMAP_EQN_FLAG_START; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + { + switch ( *pTemp ) + { + // skip all spaces, tabs, and end-of-lines + case ' ': + case '\t': + case '\r': + case '\n': + continue; + case AMAP_EQN_SYM_CONST0: + Vec_PtrPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 ); + if ( Flag == AMAP_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Amap_ParseFormula(): No operation symbol before constant 0.\n" ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + Flag = AMAP_EQN_FLAG_VAR; + break; + case AMAP_EQN_SYM_CONST1: + Vec_PtrPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 ); + if ( Flag == AMAP_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Amap_ParseFormula(): No operation symbol before constant 1.\n" ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + Flag = AMAP_EQN_FLAG_VAR; + break; + case AMAP_EQN_SYM_NEG: + if ( Flag == AMAP_EQN_FLAG_VAR ) + {// if NEGBEF follows a variable, AND is assumed + Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND ); + Flag = AMAP_EQN_FLAG_OPER; + } + Vec_IntPush( pStackOp, AMAP_EQN_OPER_NEG ); + break; + case AMAP_EQN_SYM_NEGAFT: + if ( Flag != AMAP_EQN_FLAG_VAR ) + {// if there is no variable before NEGAFT, it is an error + fprintf( pOutput, "Amap_ParseFormula(): No variable is specified before the negation suffix.\n" ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + else // if ( Flag == PARSE_FLAG_VAR ) + Vec_PtrPush( pStackFn, Hop_Not( Vec_PtrPop(pStackFn) ) ); + break; + case AMAP_EQN_SYM_AND: + case AMAP_EQN_SYM_OR: + case AMAP_EQN_SYM_XOR: + if ( Flag != AMAP_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Amap_ParseFormula(): There is no variable before AND, EXOR, or OR.\n" ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + if ( *pTemp == AMAP_EQN_SYM_AND ) + Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND ); + else if ( *pTemp == AMAP_EQN_SYM_OR ) + Vec_IntPush( pStackOp, AMAP_EQN_OPER_OR ); + else //if ( *pTemp == AMAP_EQN_SYM_XOR ) + Vec_IntPush( pStackOp, AMAP_EQN_OPER_XOR ); + Flag = AMAP_EQN_FLAG_OPER; + break; + case AMAP_EQN_SYM_OPEN: + if ( Flag == AMAP_EQN_FLAG_VAR ) + { +// Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND ); + fprintf( pOutput, "Amap_ParseFormula(): An opening paranthesis follows a var without operation sign.\n" ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + Vec_IntPush( pStackOp, AMAP_EQN_OPER_MARK ); + // after an opening bracket, it feels like starting over again + Flag = AMAP_EQN_FLAG_START; + break; + case AMAP_EQN_SYM_CLOSE: + if ( Vec_IntSize( pStackOp ) != 0 ) + { + while ( 1 ) + { + if ( Vec_IntSize( pStackOp ) == 0 ) + { + fprintf( pOutput, "Amap_ParseFormula(): There is no opening paranthesis\n" ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + Oper = Vec_IntPop( pStackOp ); + if ( Oper == AMAP_EQN_OPER_MARK ) + break; + + // perform the given operation + if ( Amap_ParseFormulaOper( pMan, pStackFn, Oper ) == NULL ) + { + fprintf( pOutput, "Amap_ParseFormula(): Unknown operation\n" ); + free( pFormula ); + return NULL; + } + } + } + else + { + fprintf( pOutput, "Amap_ParseFormula(): There is no opening paranthesis\n" ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + if ( Flag != AMAP_EQN_FLAG_ERROR ) + Flag = AMAP_EQN_FLAG_VAR; + break; + + + default: + // scan the next name + for ( i = 0; pTemp[i] && + pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && + pTemp[i] != AMAP_EQN_SYM_AND && pTemp[i] != AMAP_EQN_SYM_OR && + pTemp[i] != AMAP_EQN_SYM_XOR && pTemp[i] != AMAP_EQN_SYM_CLOSE; i++ ) + { + if ( pTemp[i] == AMAP_EQN_SYM_NEG || pTemp[i] == AMAP_EQN_SYM_OPEN ) + { + fprintf( pOutput, "Amap_ParseFormula(): The negation sign or an opening paranthesis inside the variable name.\n" ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + } + // variable name is found + fFound = 0; + Vec_PtrForEachEntry( vVarNames, pName, v ) + if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) + { + pTemp += i-1; + fFound = 1; + break; + } + if ( !fFound ) + { + fprintf( pOutput, "Amap_ParseFormula(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + if ( Flag == AMAP_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Amap_ParseFormula(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); + Flag = AMAP_EQN_FLAG_ERROR; + break; + } + Vec_PtrPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] ); + Flag = AMAP_EQN_FLAG_VAR; + break; + } + + if ( Flag == AMAP_EQN_FLAG_ERROR ) + break; // error exit + else if ( Flag == AMAP_EQN_FLAG_START ) + continue; // go on parsing + else if ( Flag == AMAP_EQN_FLAG_VAR ) + while ( 1 ) + { // check if there are negations in the OpStack + if ( Vec_IntSize( pStackOp ) == 0 ) + break; + Oper = Vec_IntPop( pStackOp ); + if ( Oper != AMAP_EQN_OPER_NEG ) + { + Vec_IntPush( pStackOp, Oper ); + break; + } + else + { + Vec_PtrPush( pStackFn, Hop_Not(Vec_PtrPop(pStackFn)) ); + } + } + else // if ( Flag == AMAP_EQN_FLAG_OPER ) + while ( 1 ) + { // execute all the operations in the OpStack + // with precedence higher or equal than the last one + Oper1 = Vec_IntPop( pStackOp ); // the last operation + if ( Vec_IntSize( pStackOp ) == 0 ) + { // if it is the only operation, push it back + Vec_IntPush( pStackOp, Oper1 ); + break; + } + Oper2 = Vec_IntPop( pStackOp ); // the operation before the last one + if ( Oper2 >= Oper1 ) + { // if Oper2 precedence is higher or equal, execute it + if ( Amap_ParseFormulaOper( pMan, pStackFn, Oper2 ) == NULL ) + { + fprintf( pOutput, "Amap_ParseFormula(): Unknown operation\n" ); + free( pFormula ); + return NULL; + } + Vec_IntPush( pStackOp, Oper1 ); // push the last operation back + } + else + { // if Oper2 precedence is lower, push them back and done + Vec_IntPush( pStackOp, Oper2 ); + Vec_IntPush( pStackOp, Oper1 ); + break; + } + } + } + + if ( Flag != AMAP_EQN_FLAG_ERROR ) + { + if ( Vec_PtrSize(pStackFn) != 0 ) + { + gFunc = Vec_PtrPop(pStackFn); + if ( Vec_PtrSize(pStackFn) == 0 ) + if ( Vec_IntSize( pStackOp ) == 0 ) + { + Vec_PtrFree(pStackFn); + Vec_IntFree(pStackOp); +// Cudd_Deref( gFunc ); + free( pFormula ); + return gFunc; + } + else + fprintf( pOutput, "Amap_ParseFormula(): Something is left in the operation stack\n" ); + else + fprintf( pOutput, "Amap_ParseFormula(): Something is left in the function stack\n" ); + } + else + fprintf( pOutput, "Amap_ParseFormula(): The input string is empty\n" ); + } + free( pFormula ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Parses equations for the gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose ) +{ + extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars ); + Hop_Man_t * pMan; + Hop_Obj_t * pObj; + Vec_Ptr_t * vNames; + Vec_Int_t * vTruth; + Amap_Gat_t * pGate; + Amap_Pin_t * pPin; + unsigned * pTruth; + int i, nPinMax; + nPinMax = Amap_LibNumPinsMax(p); + if ( nPinMax > AMAP_MAXINS ) + printf( "Gates with more than %d inputs will be ignored.\n", AMAP_MAXINS ); + vTruth = Vec_IntAlloc( 1 << 16 ); + vNames = Vec_PtrAlloc( 100 ); + pMan = Hop_ManStart(); + Hop_IthVar( pMan, nPinMax - 1 ); + Vec_PtrForEachEntry( p->vGates, pGate, i ) + { + if ( pGate->nPins == 0 ) + { + pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, 4 ); + if ( strcmp( pGate->pForm, AMAP_STRING_CONST0 ) == 0 ) + pGate->pFunc[0] = 0; + else if ( strcmp( pGate->pForm, AMAP_STRING_CONST1 ) == 0 ) + pGate->pFunc[0] = ~0; + else + { + printf( "Cannot parse formula \"%s\" of gate \"%s\" with no pins.\n", pGate->pForm, pGate->pName ); + break; + } + continue; + } + if ( pGate->nPins > AMAP_MAXINS ) + continue; + Vec_PtrClear( vNames ); + Amap_GateForEachPin( pGate, pPin ) + Vec_PtrPush( vNames, pPin->pName ); + pObj = Amap_ParseFormula( stdout, pGate->pForm, vNames, pMan ); + if ( pObj == NULL ) + break; + pTruth = Hop_ManConvertAigToTruth( pMan, pObj, pGate->nPins, vTruth, 0 ); + if ( Kit_TruthSupportSize(pTruth, pGate->nPins) < (int)pGate->nPins ) + { + printf( "Skipping gate \"%s\" because its formula \"%s\" does not depend on some pin variables.\n", pGate->pName, pGate->pForm ); + continue; + } + pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, sizeof(unsigned)*Aig_TruthWordNum(pGate->nPins) ); + memcpy( pGate->pFunc, pTruth, sizeof(unsigned)*Aig_TruthWordNum(pGate->nPins) ); + } + Vec_PtrFree( vNames ); + Vec_IntFree( vTruth ); + Hop_ManStop( pMan ); + return i == Vec_PtrSize(p->vGates); +} + +/**Function************************************************************* + + Synopsis [Parses equations for the gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibParseTest( char * pFileName ) +{ + int fVerbose = 1; + Amap_Lib_t * p; + int clk = clock(); + p = Amap_LibReadFile( pFileName, fVerbose ); + if ( p == NULL ) + return; + Amap_LibParseEquations( p, fVerbose ); + Amap_LibFree( p ); + PRT( "Total time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapPerm.c b/src/map/amap/amapPerm.c new file mode 100644 index 00000000..17fb57e2 --- /dev/null +++ b/src/map/amap/amapPerm.c @@ -0,0 +1,344 @@ +/**CFile**************************************************************** + + FileName [amapPerm.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Deriving permutation for the gate.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapPerm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects fanins of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibCollectFanins_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, Vec_Int_t * vFanins ) +{ + Amap_Nod_t * pFan0, * pFan1; + if ( pNod->Id == 0 ) + { + Vec_IntPush( vFanins, 0 ); + return; + } + pFan0 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) ); + if ( Amap_LitIsCompl(pNod->iFan0) || pFan0->Type != pNod->Type ) + Vec_IntPush( vFanins, pNod->iFan0 ); + else + Amap_LibCollectFanins_rec( pLib, pFan0, vFanins ); + pFan1 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) ); + if ( Amap_LitIsCompl(pNod->iFan1) || pFan1->Type != pNod->Type ) + Vec_IntPush( vFanins, pNod->iFan1 ); + else + Amap_LibCollectFanins_rec( pLib, pFan1, vFanins ); +} + +/**Function************************************************************* + + Synopsis [Collects fanins of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Amap_LibCollectFanins( Amap_Lib_t * pLib, Amap_Nod_t * pNod ) +{ + Vec_Int_t * vFanins = Vec_IntAlloc( 10 ); + Amap_LibCollectFanins_rec( pLib, pNod, vFanins ); + return vFanins; +} + +/**Function************************************************************* + + Synopsis [Matches the node with the DSD node.] + + Description [Returns perm if the node can be matched.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, int iLit, Amap_Nod_t * pNod ) +{ + Vec_Int_t * vPerm, * vPermFanin, * vNodFanin, * vDsdLits; + Kit_DsdObj_t * pDsdObj, * pDsdFanin; + Amap_Nod_t * pNodFanin; + int iDsdFanin, iNodFanin, Value, iDsdLit, i, k, j; + assert( !Kit_DsdLitIsCompl(iLit) ); + pDsdObj = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iLit) ); + if ( pDsdObj == NULL ) + { + vPerm = Vec_IntAlloc( 1 ); + Vec_IntPush( vPerm, iLit ); + return vPerm; + } + if ( pDsdObj->Type == KIT_DSD_PRIME && pNod->Type == AMAP_OBJ_MUX ) + { + vPerm = Vec_IntAlloc( 10 ); + + iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[0]); + pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) ); + vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); + Vec_IntForEachEntry( vPermFanin, Value, k ) + Vec_IntPush( vPerm, Value ); + Vec_IntFree( vPermFanin ); + + iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[1]); + pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) ); + vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); + Vec_IntForEachEntry( vPermFanin, Value, k ) + Vec_IntPush( vPerm, Value ); + Vec_IntFree( vPermFanin ); + + iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[2]); + pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan2) ); + vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); + Vec_IntForEachEntry( vPermFanin, Value, k ) + Vec_IntPush( vPerm, Value ); + Vec_IntFree( vPermFanin ); + + return vPerm; + } + // return if wrong types + if ( pDsdObj->Type == KIT_DSD_PRIME || pNod->Type == AMAP_OBJ_MUX ) + return NULL; + // return if sizes do not agree + vNodFanin = Amap_LibCollectFanins( pLib, pNod ); + if ( Vec_IntSize(vNodFanin) != (int)pDsdObj->nFans ) + { + Vec_IntFree( vNodFanin ); + return NULL; + } + // match fanins of DSD with fanins of nodes + // clean the mark and save variable literals + vPerm = Vec_IntAlloc( 10 ); + vDsdLits = Vec_IntAlloc( 10 ); + Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i ) + { + pDsdFanin = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iDsdFanin) ); + if ( pDsdFanin ) + pDsdFanin->fMark = 0; + else + Vec_IntPush( vDsdLits, iDsdFanin ); + } + // match each fanins of the node + iDsdLit = 0; + Vec_IntForEachEntry( vNodFanin, iNodFanin, k ) + { + if ( iNodFanin == 0 ) + { + iDsdFanin = Vec_IntEntry( vDsdLits, iDsdLit++ ); + Vec_IntPush( vPerm, iDsdFanin ); + continue; + } + // find a matching component + pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(iNodFanin) ); + Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i ) + { + pDsdFanin = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iDsdFanin) ); + if ( pDsdFanin == NULL ) + continue; + if ( pDsdFanin->fMark == 1 ) + continue; + if ( !((pDsdFanin->Type == KIT_DSD_AND && pNodFanin->Type == AMAP_OBJ_AND) || + (pDsdFanin->Type == KIT_DSD_XOR && pNodFanin->Type == AMAP_OBJ_XOR) || + (pDsdFanin->Type == KIT_DSD_PRIME && pNodFanin->Type == AMAP_OBJ_MUX)) ) + continue; + vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Kit_DsdLitRegular(iDsdFanin), pNodFanin ); + if ( vPermFanin == NULL ) + continue; + pDsdFanin->fMark = 1; + Vec_IntForEachEntry( vPermFanin, Value, j ) + Vec_IntPush( vPerm, Value ); + Vec_IntFree( vPermFanin ); + break; + } + } + assert( iDsdLit == Vec_IntSize(vDsdLits) ); + Vec_IntFree( vNodFanin ); + Vec_IntFree( vDsdLits ); + return vPerm; +} + +/**Function************************************************************* + + Synopsis [Performs verification of one gate and one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Amap_LibVerifyPerm_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, + Vec_Ptr_t * vTtElems, Vec_Int_t * vTruth, int nWords, int * piInput ) +{ + Amap_Nod_t * pFan0, * pFan1; + unsigned * pTruth0, * pTruth1, * pTruth; + int i; + assert( pNod->Type != AMAP_OBJ_MUX ); + if ( pNod->Id == 0 ) + return Vec_PtrEntry( vTtElems, (*piInput)++ ); + pFan0 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) ); + pTruth0 = Amap_LibVerifyPerm_rec( pLib, pFan0, vTtElems, vTruth, nWords, piInput ); + pFan1 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) ); + pTruth1 = Amap_LibVerifyPerm_rec( pLib, pFan1, vTtElems, vTruth, nWords, piInput ); + pTruth = Vec_IntFetch( vTruth, nWords ); + if ( pNod->Type == AMAP_OBJ_XOR ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Amap_LitIsCompl(pNod->iFan0) && !Amap_LitIsCompl(pNod->iFan1) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Amap_LitIsCompl(pNod->iFan0) && Amap_LitIsCompl(pNod->iFan1) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Amap_LitIsCompl(pNod->iFan0) && !Amap_LitIsCompl(pNod->iFan1) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Amap_LitIsCompl(pNod->iFan0) && Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Performs verification of one gate and one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibVerifyPerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, int * pArray ) +{ + Vec_Ptr_t * vTtElems; + Vec_Ptr_t * vTtElemsPol; + Vec_Int_t * vTruth; + unsigned * pTruth; + int i, nWords; + int iInput = 0; + + // allocate storage for truth tables + assert( pGate->nPins > 1 ); + nWords = Kit_TruthWordNum( pGate->nPins ); + vTruth = Vec_IntAlloc( nWords * AMAP_MAXINS ); + vTtElems = Vec_PtrAllocTruthTables( pGate->nPins ); + vTtElemsPol = Vec_PtrAlloc( pGate->nPins ); + for ( i = 0; i < (int)pGate->nPins; i++ ) + { + pTruth = Vec_PtrEntry( vTtElems, Amap_Lit2Var(pArray[i]) ); + if ( Amap_LitIsCompl( pArray[i] ) ) + Kit_TruthNot( pTruth, pTruth, pGate->nPins ); + Vec_PtrPush( vTtElemsPol, pTruth ); + } +//Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 0), 4 ); printf("\n" ); +//Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 1), 4 ); printf("\n" ); + // compute the truth table recursively + pTruth = Amap_LibVerifyPerm_rec( pLib, pNod, vTtElemsPol, vTruth, nWords, &iInput ); + assert( iInput == (int)pGate->nPins ); + if ( Kit_DsdLitIsCompl(pNtk->Root) ) + Kit_TruthNot( pTruth, pTruth, pGate->nPins ); +//Extra_PrintBinary( stdout, pTruth, 4 ); printf("\n" ); +//Extra_PrintBinary( stdout, pGate->pFunc, 4 ); printf("\n" ); + // compare + if ( !Kit_TruthIsEqual(pGate->pFunc, pTruth, pGate->nPins) ) + printf( "Verification failed for gate %d (%s) and node %d.\n", + pGate->Id, pGate->pForm, pNod->Id ); + Vec_IntFree( vTruth ); + Vec_PtrFree( vTtElems ); + Vec_PtrFree( vTtElemsPol ); +} + +/**Function************************************************************* + + Synopsis [Matches the node with the DSD of a gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray ) +{ + int fVerbose = 0; + Vec_Int_t * vPerm; + int Entry, Entry2, i, k; + vPerm = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Kit_DsdLitRegular(pNtk->Root), pNod ); + if ( vPerm == NULL ) + return 0; + // check that the permutation is valid + assert( Vec_IntSize(vPerm) == (int)pNod->nSuppSize ); + Vec_IntForEachEntry( vPerm, Entry, i ) + Vec_IntForEachEntryStart( vPerm, Entry2, k, i+1 ) + if ( Amap_Lit2Var(Entry) == Amap_Lit2Var(Entry2) ) + { + Vec_IntFree( vPerm ); + return 0; + } + + // reverse the permutation + Vec_IntForEachEntry( vPerm, Entry, i ) + { + assert( Entry < 2 * (int)pNod->nSuppSize ); + pArray[Kit_DsdLit2Var(Entry)] = Amap_Var2Lit( i, Kit_DsdLitIsCompl(Entry) ); +// pArray[i] = Entry; +//printf( "%d=%d%c ", Kit_DsdLit2Var(Entry), i, Kit_DsdLitIsCompl(Entry)?'-':'+' ); + } +//printf( "\n" ); +// if ( Kit_DsdNonDsdSizeMax(pNtk) < 3 ) +// Amap_LibVerifyPerm( pLib, pGate, pNtk, pNod, Vec_IntArray(vPerm) ); + Vec_IntFree( vPerm ); + // print the result + if ( fVerbose ) + { + printf( "node %4d : ", pNod->Id ); + for ( i = 0; i < (int)pNod->nSuppSize; i++ ) + printf( "%d=%d%c ", i, Amap_Lit2Var(pArray[i]), Amap_LitIsCompl(pArray[i])?'-':'+' ); + printf( "\n" ); + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapRead.c b/src/map/amap/amapRead.c new file mode 100644 index 00000000..182de5d1 --- /dev/null +++ b/src/map/amap/amapRead.c @@ -0,0 +1,412 @@ +/**CFile**************************************************************** + + FileName [amapRead.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapRead.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AMAP_STRING_GATE "GATE" +#define AMAP_STRING_PIN "PIN" +#define AMAP_STRING_NONINV "NONINV" +#define AMAP_STRING_INV "INV" +#define AMAP_STRING_UNKNOWN "UNKNOWN" + +// these symbols (and no other) can appear in the formulas +#define AMAP_SYMB_AND '*' +#define AMAP_SYMB_OR1 '+' +#define AMAP_SYMB_OR2 '|' +#define AMAP_SYMB_XOR '^' +#define AMAP_SYMB_NOT '!' +#define AMAP_SYMB_AFTNOT '\'' +#define AMAP_SYMB_OPEN '(' +#define AMAP_SYMB_CLOSE ')' + +typedef enum { + AMAP_PHASE_UNKNOWN, + AMAP_PHASE_INV, + AMAP_PHASE_NONINV +} Amap_PinPhase_t; + +static inline Amap_Gat_t * Amap_ParseGateAlloc( Aig_MmFlex_t * p, int nPins ) +{ return (Amap_Gat_t *)Aig_MmFlexEntryFetch( p, sizeof(Amap_Gat_t)+sizeof(Amap_Pin_t)*nPins ); } +static inline char * Amap_ParseStrsav( Aig_MmFlex_t * p, char * pStr ) +{ return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Loads the file into temporary buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Amap_LoadFile( char * pFileName ) +{ + extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ); + FILE * pFile; + char * pBuffer; + int nFileSize; + // open the BLIF file for binary reading + pFile = Io_FileOpen( pFileName, "open_path", "rb", 1 ); +// pFile = fopen( FileName, "rb" ); + // if we got this far, file should be okay otherwise would + // have been detected by caller + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\".\n", pFileName ); + return NULL; + } + assert ( pFile != NULL ); + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + // move the file current reading position to the beginning + rewind( pFile ); + // load the contents of the file into memory + pBuffer = ALLOC( char, nFileSize + 10 ); + fread( pBuffer, nFileSize, 1, pFile ); + // terminate the string with '\0' + pBuffer[ nFileSize ] = '\0'; + strcat( pBuffer, "\n.end\n" ); + // close file + fclose( pFile ); + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [Eliminates comments from the input file.] + + Description [As a byproduct, this procedure also counts the number + lines and dot-statements in the input file. This also joins non-comment + lines that are joined with a backspace '\'] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_RemoveComments( char * pBuffer, int * pnDots, int * pnLines ) +{ + char * pCur; + int nDots, nLines; + // scan through the buffer and eliminate comments + // (in the BLIF file, comments are lines starting with "#") + nDots = nLines = 0; + for ( pCur = pBuffer; *pCur; pCur++ ) + { + // if this is the beginning of comment + // clean it with spaces until the new line statement + if ( *pCur == '#' ) + while ( *pCur != '\n' ) + *pCur++ = ' '; + + // count the number of new lines and dots + if ( *pCur == '\n' ) { + if (*(pCur-1)=='\r') { + // DOS(R) file support + if (*(pCur-2)!='\\') nLines++; + else { + // rewind to backslash and overwrite with a space + *(pCur-2) = ' '; + *(pCur-1) = ' '; + *pCur = ' '; + } + } else { + // UNIX(TM) file support + if (*(pCur-1)!='\\') nLines++; + else { + // rewind to backslash and overwrite with a space + *(pCur-1) = ' '; + *pCur = ' '; + } + } + } + else if ( *pCur == '.' ) + nDots++; + } + if ( pnDots ) + *pnDots = nDots; + if ( pnLines ) + *pnLines = nLines; +} + +/**Function************************************************************* + + Synopsis [Splits the stream into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Amap_DeriveTokens( char * pBuffer ) +{ + Vec_Ptr_t * vTokens; + char * pToken; + vTokens = Vec_PtrAlloc( 1000 ); + pToken = strtok( pBuffer, " ;=\t\r\n" ); + while ( pToken ) + { + Vec_PtrPush( vTokens, pToken ); + pToken = strtok( NULL, " ;=\t\r\n" ); + } + return vTokens; +} + +/**Function************************************************************* + + Synopsis [Finds the number of pins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_ParseCountPins( Vec_Ptr_t * vTokens, int iPos ) +{ + char * pToken; + int i, Counter = 0; + Vec_PtrForEachEntryStart( vTokens, pToken, i, iPos ) + if ( !strcmp( pToken, AMAP_STRING_PIN ) ) + Counter++; + else if ( !strcmp( pToken, AMAP_STRING_GATE ) ) + return Counter; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collect the pin names used in the formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_GateCollectNames( Aig_MmFlex_t * pMem, char * pForm, char * pPinNames[] ) +{ + char Buffer[1000]; + char * pTemp; + int nPins, i; + // save the formula as it was + strcpy( Buffer, pForm ); + // remove the non-name symbols + for ( pTemp = Buffer; *pTemp; pTemp++ ) + if ( *pTemp == AMAP_SYMB_AND || *pTemp == AMAP_SYMB_OR1 || *pTemp == AMAP_SYMB_OR2 + || *pTemp == AMAP_SYMB_XOR || *pTemp == AMAP_SYMB_NOT || *pTemp == AMAP_SYMB_OPEN + || *pTemp == AMAP_SYMB_CLOSE || *pTemp == AMAP_SYMB_AFTNOT ) + *pTemp = ' '; + // save the names + nPins = 0; + pTemp = strtok( Buffer, " " ); + while ( pTemp ) + { + for ( i = 0; i < nPins; i++ ) + if ( strcmp( pTemp, pPinNames[i] ) == 0 ) + break; + if ( i == nPins ) + { // cannot find this name; save it + pPinNames[nPins++] = Amap_ParseStrsav( pMem, pTemp ); + } + // get the next name + pTemp = strtok( NULL, " " ); + } + return nPins; +} + +/**Function************************************************************* + + Synopsis [Creates a duplicate gate with pins specified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Gat_t * Amap_ParseGateWithSamePins( Amap_Gat_t * p ) +{ + Amap_Gat_t * pGate; + Amap_Pin_t * pPin; + char * pPinNames[128]; + int nPinNames; + assert( p->nPins == 1 && !strcmp( p->Pins->pName, "*" ) ); + nPinNames = Amap_GateCollectNames( p->pLib->pMemGates, p->pForm, pPinNames ); + pGate = Amap_ParseGateAlloc( p->pLib->pMemGates, nPinNames ); + *pGate = *p; + pGate->nPins = nPinNames; + Amap_GateForEachPin( pGate, pPin ) + { + *pPin = *p->Pins; + pPin->pName = pPinNames[pPin - pGate->Pins]; + } + return pGate; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose ) +{ + Amap_Lib_t * p; + Amap_Gat_t * pGate; + Amap_Pin_t * pPin; + char * pToken; + int nPins, iPos = 0; + p = Amap_LibAlloc(); + pToken = Vec_PtrEntry(vTokens, iPos++); + do + { + if ( strcmp( pToken, AMAP_STRING_GATE ) ) + { + printf( "The first line should begin with %s.\n", AMAP_STRING_GATE ); + return NULL; + } + // start gate + nPins = Amap_ParseCountPins( vTokens, iPos ); + pGate = Amap_ParseGateAlloc( p->pMemGates, nPins ); + memset( pGate, 0, sizeof(Amap_Gat_t) ); + pGate->Id = Vec_PtrSize( p->vGates ); + Vec_PtrPush( p->vGates, pGate ); + pGate->pLib = p; + pGate->nPins = nPins; + // read gate + pToken = Vec_PtrEntry(vTokens, iPos++); + pGate->pName = Amap_ParseStrsav( p->pMemGates, pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + pGate->dArea = atof( pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + pGate->pOutName = Amap_ParseStrsav( p->pMemGates, pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + pGate->pForm = Amap_ParseStrsav( p->pMemGates, pToken ); + // read pins + Amap_GateForEachPin( pGate, pPin ) + { + pToken = Vec_PtrEntry(vTokens, iPos++); + if ( strcmp( pToken, AMAP_STRING_PIN ) ) + { + printf( "Cannot parse gate %s.\n", pGate->pName ); + return NULL; + } + // read pin + pToken = Vec_PtrEntry(vTokens, iPos++); + pPin->pName = Amap_ParseStrsav( p->pMemGates, pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + if ( strcmp( pToken, AMAP_STRING_UNKNOWN ) == 0 ) + pPin->Phase = AMAP_PHASE_UNKNOWN; + else if ( strcmp( pToken, AMAP_STRING_INV ) == 0 ) + pPin->Phase = AMAP_PHASE_INV; + else if ( strcmp( pToken, AMAP_STRING_NONINV ) == 0 ) + pPin->Phase = AMAP_PHASE_NONINV; + else + { + printf( "Cannot read phase of pin %s of gate %s\n", pPin->pName, pGate->pName ); + return NULL; + } + pToken = Vec_PtrEntry(vTokens, iPos++); + pPin->dLoadInput = atof( pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + pPin->dLoadMax = atof( pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + pPin->dDelayBlockRise = atof( pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + pPin->dDelayFanoutRise = atof( pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + pPin->dDelayBlockFall = atof( pToken ); + pToken = Vec_PtrEntry(vTokens, iPos++); + pPin->dDelayFanoutFall = atof( pToken ); + if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall ) + pPin->dDelayBlockMax = pPin->dDelayBlockRise; + else + pPin->dDelayBlockMax = pPin->dDelayBlockFall; + } + // fix the situation when all pins are represented as one + if ( pGate->nPins == 1 && !strcmp( pGate->Pins->pName, "*" ) ) + { + pGate = Amap_ParseGateWithSamePins( pGate ); + Vec_PtrPop( p->vGates ); + Vec_PtrPush( p->vGates, pGate ); + } + pToken = Vec_PtrEntry(vTokens, iPos++); + } + while ( strcmp( pToken, ".end" ) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Reads the library from the input file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose ) +{ + Amap_Lib_t * pLib; + Vec_Ptr_t * vTokens; + char * pBuffer; + pBuffer = Amap_LoadFile( pFileName ); + if ( pBuffer == NULL ) + return NULL; + Amap_RemoveComments( pBuffer, NULL, NULL ); + vTokens = Amap_DeriveTokens( pBuffer ); + pLib = Amap_ParseTokens( vTokens, fVerbose ); + if ( pLib == NULL ) + return NULL; + pLib->pName = Amap_ParseStrsav( pLib->pMemGates, pFileName ); + Vec_PtrFree( vTokens ); + free( pBuffer ); + return pLib; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapRule.c b/src/map/amap/amapRule.c new file mode 100644 index 00000000..212f7631 --- /dev/null +++ b/src/map/amap/amapRule.c @@ -0,0 +1,368 @@ +/**CFile**************************************************************** + + FileName [amapRule.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Matching rules.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapRule.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if the three-argument rule exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Amap_CreateRulesPrime( Amap_Lib_t * p, Vec_Int_t * vNods0, Vec_Int_t * vNods1, Vec_Int_t * vNods2 ) +{ + Vec_Int_t * vRes; + int i, k, j, iNod, iNod0, iNod1, iNod2; + if ( p->vRules3 == NULL ) + p->vRules3 = Vec_IntAlloc( 100 ); + vRes = Vec_IntAlloc( 10 ); + Vec_IntForEachEntry( vNods0, iNod0, i ) + Vec_IntForEachEntry( vNods1, iNod1, k ) + Vec_IntForEachEntry( vNods2, iNod2, j ) + { + iNod = Amap_LibFindMux( p, iNod0, iNod1, iNod2 ); + if ( iNod == -1 ) + iNod = Amap_LibCreateMux( p, iNod0, iNod1, iNod2 ); + Vec_IntPush( vRes, Amap_Var2Lit(iNod, 0) ); + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_CreateRulesTwo( Amap_Lib_t * p, Vec_Int_t * vNods, Vec_Int_t * vNods0, Vec_Int_t * vNods1, int fXor ) +{ + int i, k, iNod, iNod0, iNod1; + Vec_IntForEachEntry( vNods0, iNod0, i ) + Vec_IntForEachEntry( vNods1, iNod1, k ) + { + iNod = Amap_LibFindNode( p, iNod0, iNod1, fXor ); + if ( iNod == -1 ) + iNod = Amap_LibCreateNode( p, iNod0, iNod1, fXor ); + Vec_IntPushUnique( vNods, Amap_Var2Lit(iNod, 0) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_CreateCheckAllZero( Vec_Ptr_t * vVecNods ) +{ + Vec_Int_t * vNods; + int i; + Vec_PtrForEachEntryReverse( vVecNods, vNods, i ) + if ( Vec_IntSize(vNods) != 1 || Vec_IntEntry(vNods,0) != 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Amap_CreateRulesVector_rec( Amap_Lib_t * p, Vec_Ptr_t * vVecNods, int fXor ) +{ + Vec_Ptr_t * vVecNods0, * vVecNods1; + Vec_Int_t * vRes, * vNods, * vNods0, * vNods1; + int i, k; + if ( Vec_PtrSize(vVecNods) == 1 ) + return Vec_IntDup( Vec_PtrEntry(vVecNods, 0) ); + vRes = Vec_IntAlloc( 10 ); + vVecNods0 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) ); + vVecNods1 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) ); + if ( Amap_CreateCheckAllZero(vVecNods) ) + { + for ( i = Vec_PtrSize(vVecNods)-1; i > 0; i-- ) + { + Vec_PtrClear( vVecNods0 ); + Vec_PtrClear( vVecNods1 ); + Vec_PtrForEachEntryStop( vVecNods, vNods, k, i ) + Vec_PtrPush( vVecNods0, vNods ); + Vec_PtrForEachEntryStart( vVecNods, vNods, k, i ) + Vec_PtrPush( vVecNods1, vNods ); + vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor ); + vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor ); + Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor ); + Vec_IntFree( vNods0 ); + Vec_IntFree( vNods1 ); + } + } + else + { + int Limit = (1 << Vec_PtrSize(vVecNods))-2; + for ( i = 1; i < Limit; i++ ) + { + Vec_PtrClear( vVecNods0 ); + Vec_PtrClear( vVecNods1 ); + Vec_PtrForEachEntryReverse( vVecNods, vNods, k ) + { + if ( i & (1 << k) ) + Vec_PtrPush( vVecNods1, vNods ); + else + Vec_PtrPush( vVecNods0, vNods ); + } + assert( Vec_PtrSize(vVecNods0) > 0 ); + assert( Vec_PtrSize(vVecNods1) > 0 ); + assert( Vec_PtrSize(vVecNods0) < Vec_PtrSize(vVecNods) ); + assert( Vec_PtrSize(vVecNods1) < Vec_PtrSize(vVecNods) ); + vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor ); + vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor ); + Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor ); + Vec_IntFree( vNods0 ); + Vec_IntFree( vNods1 ); + } + } + Vec_PtrFree( vVecNods0 ); + Vec_PtrFree( vVecNods1 ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Amap_CreateRulesFromDsd_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * p, int iLit ) +{ + Vec_Int_t * vRes; + Vec_Ptr_t * vVecNods; + Vec_Int_t * vNodsFanin; + Kit_DsdObj_t * pObj; + unsigned i; + int iFanin, iNod, k; + assert( !Kit_DsdLitIsCompl(iLit) ); + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + if ( pObj == NULL ) + return Vec_IntStartNatural( 1 ); + // solve for the inputs + vVecNods = Vec_PtrAlloc( pObj->nFans ); + Kit_DsdObjForEachFanin( p, pObj, iFanin, i ) + { + vNodsFanin = Amap_CreateRulesFromDsd_rec( pLib, p, Kit_DsdLitRegular(iFanin) ); + if ( Kit_DsdLitIsCompl(iFanin) ) + { + Vec_IntForEachEntry( vNodsFanin, iNod, k ) + if ( iNod > 0 ) + Vec_IntWriteEntry( vNodsFanin, k, Amap_LitNot(iNod) ); + } + Vec_PtrPush( vVecNods, vNodsFanin ); + } + if ( pObj->Type == KIT_DSD_AND ) + vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 0 ); + else if ( pObj->Type == KIT_DSD_XOR ) + vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 1 ); + else if ( pObj->Type == KIT_DSD_PRIME ) + { + assert( pObj->nFans == 3 ); + assert( Kit_DsdObjTruth(pObj)[0] == 0xCACACACA ); + vRes = Amap_CreateRulesPrime( pLib, Vec_PtrEntry(vVecNods, 0), + Vec_PtrEntry(vVecNods, 1), Vec_PtrEntry(vVecNods, 2) ); + } + else assert( 0 ); + Vec_PtrForEachEntry( vVecNods, vNodsFanin, k ) + Vec_IntFree( vNodsFanin ); + Vec_PtrFree( vVecNods ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Amap_CreateRulesFromDsd( Amap_Lib_t * pLib, Kit_DsdNtk_t * p ) +{ + Vec_Int_t * vNods; + int iNod, i; + assert( p->nVars >= 2 ); + vNods = Amap_CreateRulesFromDsd_rec( pLib, p, Kit_DsdLitRegular(p->Root) ); + if ( vNods == NULL ) + return NULL; + if ( Kit_DsdLitIsCompl(p->Root) ) + { + Vec_IntForEachEntry( vNods, iNod, i ) + Vec_IntWriteEntry( vNods, i, Amap_LitNot(iNod) ); + } + return vNods; +} + +/**Function************************************************************* + + Synopsis [Creates rules for the given gate] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_CreateRulesForGate( Amap_Lib_t * pLib, Amap_Gat_t * pGate ) +{ + Kit_DsdNtk_t * pNtk, * pTemp; + Vec_Int_t * vNods; + Amap_Nod_t * pNod; + Amap_Set_t * pSet; + int iNod, i; +// if ( pGate->nPins > 4 ) +// return; + pNtk = Kit_DsdDecomposeMux( pGate->pFunc, pGate->nPins, 2 ); + if ( pGate->nPins == 2 && (pGate->pFunc[0] == 0x66666666 || pGate->pFunc[0] == ~0x66666666) ) + pLib->fHasXor = 1; + if ( Kit_DsdNonDsdSizeMax(pNtk) == 3 ) + pLib->fHasMux = pGate->fMux = 1; + pNtk = Kit_DsdExpand( pTemp = pNtk ); + Kit_DsdNtkFree( pTemp ); + Kit_DsdVerify( pNtk, pGate->pFunc, pGate->nPins ); +if ( pLib->fVerbose ) +//if ( pGate->fMux ) +{ +printf( "\nProcessing library gate %4d: %10s ", pGate->Id, pGate->pName ); +Kit_DsdPrint( stdout, pNtk ); +} + vNods = Amap_CreateRulesFromDsd( pLib, pNtk ); + if ( vNods ) + { + Vec_IntForEachEntry( vNods, iNod, i ) + { + assert( iNod > 1 ); + pNod = Amap_LibNod( pLib, Amap_Lit2Var(iNod) ); + assert( pNod->Type == AMAP_OBJ_MUX || pNod->nSuppSize == pGate->nPins ); + pSet = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) ); + memset( pSet, 0, sizeof(Amap_Set_t) ); + pSet->iGate = pGate->Id; + pSet->fInv = Amap_LitIsCompl(iNod); + pSet->nIns = pGate->nPins; + if ( Amap_LibDeriveGatePerm( pLib, pGate, pNtk, pNod, pSet->Ins ) == 0 ) + { +if ( pLib->fVerbose ) +{ + printf( "Cound not prepare gate \"%s\": ", pGate->pName ); + Kit_DsdPrint( stdout, pNtk ); +} + continue; + } + pSet->pNext = pNod->pSets; + pNod->pSets = pSet; + pLib->nSets++; + } + Vec_IntFree( vNods ); + } + Kit_DsdNtkFree( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Creates rules for the given gate] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Amap_LibCreateRules( Amap_Lib_t * pLib, int fVeryVerbose ) +{ + Amap_Gat_t * pGate; + int i, nGates = 0; + int clk = clock(); + pLib->fVerbose = fVeryVerbose; + pLib->vRules = Vec_PtrAlloc( 100 ); + pLib->vRulesX = Vec_PtrAlloc( 100 ); + pLib->vRules3 = Vec_IntAlloc( 100 ); + Amap_LibCreateVar( pLib ); + Vec_PtrForEachEntry( pLib->vSelect, pGate, i ) + { + if ( pGate->nPins < 2 ) + continue; + if ( pGate->pFunc == NULL ) + { + printf( "Amap_LibCreateRules(): Skipping gate %s (%s).\n", pGate->pName, pGate->pForm ); + continue; + } + Amap_CreateRulesForGate( pLib, pGate ); + nGates++; + } + assert( Vec_PtrSize(pLib->vRules) == 2*pLib->nNodes ); + assert( Vec_PtrSize(pLib->vRulesX) == 2*pLib->nNodes ); + pLib->pRules = Amap_LibLookupTableAlloc( pLib->vRules, 0 ); + pLib->pRulesX = Amap_LibLookupTableAlloc( pLib->vRulesX, 0 ); + Vec_VecFree( (Vec_Vec_t *)pLib->vRules ); pLib->vRules = NULL; + Vec_VecFree( (Vec_Vec_t *)pLib->vRulesX ); pLib->vRulesX = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/amapUniq.c b/src/map/amap/amapUniq.c new file mode 100644 index 00000000..83fce6a2 --- /dev/null +++ b/src/map/amap/amapUniq.c @@ -0,0 +1,312 @@ +/**CFile**************************************************************** + + FileName [amapUniq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Technology mapper for standard cells.] + + Synopsis [Checks if the structural node already exists.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: amapUniq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "amapInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if the entry exists and returns value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntCheckWithMask( Vec_Int_t * p, int Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( (0xffff & p->pArray[i]) == (0xffff & Entry) ) + return p->pArray[i] >> 16; + return -1; +} + +/**Function************************************************************* + + Synopsis [Pushes entry in the natural order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntPushOrderWithMask( Vec_Int_t * p, int Entry ) +{ + int i; + if ( p->nSize == p->nCap ) + Vec_IntGrow( p, 2 * p->nCap ); + p->nSize++; + for ( i = p->nSize-2; i >= 0; i-- ) + if ( (0xffff & p->pArray[i]) > (0xffff & Entry) ) + p->pArray[i+1] = p->pArray[i]; + else + break; + p->pArray[i+1] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibFindNode( Amap_Lib_t * pLib, int iFan0, int iFan1, int fXor ) +{ + if ( fXor ) + return Vec_IntCheckWithMask( Vec_PtrEntry(pLib->vRulesX, iFan0), iFan1 ); + else + return Vec_IntCheckWithMask( Vec_PtrEntry(pLib->vRules, iFan0), iFan1 ); +} + +/**Function************************************************************* + + Synopsis [Checks if the three-argument rule exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibFindMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ) +{ + int x; + for ( x = 0; x < Vec_IntSize(p->vRules3); x += 4 ) + { + if ( Vec_IntEntry(p->vRules3, x) == iFan0 && + Vec_IntEntry(p->vRules3, x+1) == iFan1 && + Vec_IntEntry(p->vRules3, x+2) == iFan2 ) + { + return Vec_IntEntry(p->vRules3, x+3); + } + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Amap_Nod_t * Amap_LibCreateObj( Amap_Lib_t * p ) +{ + Amap_Nod_t * pNode; + if ( p->nNodes == p->nNodesAlloc ) + { + p->pNodes = REALLOC( Amap_Nod_t, p->pNodes, 2*p->nNodesAlloc ); + p->nNodesAlloc *= 2; + } + pNode = Amap_LibNod( p, p->nNodes ); + memset( pNode, 0, sizeof(Amap_Nod_t) ); + pNode->Id = p->nNodes++; + Vec_PtrPush( p->vRules, Vec_IntAlloc(8) ); + Vec_PtrPush( p->vRules, Vec_IntAlloc(8) ); + Vec_PtrPush( p->vRulesX, Vec_IntAlloc(8) ); + Vec_PtrPush( p->vRulesX, Vec_IntAlloc(8) ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibCreateVar( Amap_Lib_t * p ) +{ + Amap_Nod_t * pNode; + // start the manager + assert( p->pNodes == NULL ); + p->nNodesAlloc = 256; + p->pNodes = ALLOC( Amap_Nod_t, p->nNodesAlloc ); + // create the first node + pNode = Amap_LibCreateObj( p ); + p->pNodes->Type = AMAP_OBJ_PI; + p->pNodes->nSuppSize = 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor ) +{ + Amap_Nod_t * pNode; + int iFan; + if ( iFan0 < iFan1 ) + { + iFan = iFan0; + iFan0 = iFan1; + iFan1 = iFan; + } + pNode = Amap_LibCreateObj( p ); + pNode->Type = fXor? AMAP_OBJ_XOR : AMAP_OBJ_AND; + pNode->nSuppSize = p->pNodes[Amap_Lit2Var(iFan0)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan1)].nSuppSize; + pNode->iFan0 = iFan0; + pNode->iFan1 = iFan1; +if ( p->fVerbose ) +printf( "Creating node %5d %c : iFan0 = %5d%c iFan1 = %5d%c\n", +pNode->Id, (fXor?'x':' '), +Amap_Lit2Var(iFan0), (Amap_LitIsCompl(iFan0)?'-':'+'), +Amap_Lit2Var(iFan1), (Amap_LitIsCompl(iFan1)?'-':'+') ); + + if ( fXor ) + { + if ( iFan0 == iFan1 ) + Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRulesX, iFan0), (pNode->Id << 16) | iFan1 ); + else + { + Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRulesX, iFan0), (pNode->Id << 16) | iFan1 ); + Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRulesX, iFan1), (pNode->Id << 16) | iFan0 ); + } + } + else + { + if ( iFan0 == iFan1 ) + Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRules, iFan0), (pNode->Id << 16) | iFan1 ); + else + { + Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRules, iFan0), (pNode->Id << 16) | iFan1 ); + Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRules, iFan1), (pNode->Id << 16) | iFan0 ); + } + } + return pNode->Id; +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ) +{ + Amap_Nod_t * pNode; + pNode = Amap_LibCreateObj( p ); + pNode->Type = AMAP_OBJ_MUX; + pNode->nSuppSize = p->pNodes[Amap_Lit2Var(iFan0)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan1)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan2)].nSuppSize; + pNode->iFan0 = iFan0; + pNode->iFan1 = iFan1; + pNode->iFan2 = iFan2; +if ( p->fVerbose ) +printf( "Creating node %5d %c : iFan0 = %5d%c iFan1 = %5d%c iFan2 = %5d%c\n", +pNode->Id, 'm', +Amap_Lit2Var(iFan0), (Amap_LitIsCompl(iFan0)?'-':'+'), +Amap_Lit2Var(iFan1), (Amap_LitIsCompl(iFan1)?'-':'+'), +Amap_Lit2Var(iFan2), (Amap_LitIsCompl(iFan2)?'-':'+') ); + + Vec_IntPush( p->vRules3, iFan0 ); + Vec_IntPush( p->vRules3, iFan1 ); + Vec_IntPush( p->vRules3, iFan2 ); + Vec_IntPush( p->vRules3, pNode->Id ); + return pNode->Id; +} + +/**Function************************************************************* + + Synopsis [Allocates triangular lookup table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int ** Amap_LibLookupTableAlloc( Vec_Ptr_t * vVec, int fVerbose ) +{ + Vec_Int_t * vOne; + int ** pRes, * pBuffer; + int i, k, nTotal, nSize, nEntries, Value; + // count the total size + nEntries = nSize = Vec_PtrSize( vVec ); + Vec_PtrForEachEntry( vVec, vOne, i ) + nEntries += Vec_IntSize(vOne); + pBuffer = ALLOC( int, nSize * sizeof(void *) + nEntries ); + pRes = (int **)pBuffer; + pRes[0] = pBuffer + nSize * sizeof(void *); + nTotal = 0; + Vec_PtrForEachEntry( vVec, vOne, i ) + { + pRes[i] = pRes[0] + nTotal; + nTotal += Vec_IntSize(vOne) + 1; + if ( fVerbose ) + printf( "%d : ", i ); + Vec_IntForEachEntry( vOne, Value, k ) + { + pRes[i][k] = Value; + if ( fVerbose ) + printf( "%d(%d) ", Value&0xffff, Value>>16 ); + } + if ( fVerbose ) + printf( "\n" ); + pRes[i][k] = 0; + } + assert( nTotal == nEntries ); + return pRes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/amap/module.make b/src/map/amap/module.make new file mode 100644 index 00000000..d5edadb9 --- /dev/null +++ b/src/map/amap/module.make @@ -0,0 +1,12 @@ +SRC += src/map/amap/amapCore.c \ + src/map/amap/amapGraph.c \ + src/map/amap/amapLib.c \ + src/map/amap/amapMan.c \ + src/map/amap/amapMatch.c \ + src/map/amap/amapMerge.c \ + src/map/amap/amapOutput.c \ + src/map/amap/amapParse.c \ + src/map/amap/amapPerm.c \ + src/map/amap/amapRead.c \ + src/map/amap/amapRule.c \ + src/map/amap/amapUniq.c diff --git a/src/map/if/if.h b/src/map/if/if.h index 24046f06..ce2cb483 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -88,6 +88,7 @@ struct If_Par_t_ int fExpRed; // expand/reduce of the best cuts int fLatchPaths; // reset timing on latch paths int fEdge; // uses edge-based cut selection heuristics + int fPower; // uses power-aware cut selection heuristics int fCutMin; // performs cut minimization by removing functionally reducdant variables int fSeqMap; // sequential mapping int fBidec; // use bi-decomposition @@ -141,12 +142,14 @@ struct If_Man_t_ float RequiredGlo2; // global required times float AreaGlo; // global area int nNets; // the sum total of fanins of all LUTs in the mapping + float dPower; // the sum total of switching activities of all LUTs in the mapping int nCutsUsed; // the number of cuts currently used int nCutsMerged; // the total number of cuts merged unsigned * puTemp[4]; // used for the truth table computation int SortMode; // one of the three sorting modes int fNextRound; // set to 1 after the first round int nChoices; // the number of choice nodes + Vec_Int_t * vSwitching; // switching activity of each node // sequential mapping Vec_Ptr_t * vLatchOrder; // topological ordering of latches Vec_Int_t * vLags; // sequentail lags of all nodes @@ -177,6 +180,7 @@ struct If_Cut_t_ float Area; // area (or area-flow) of the cut float AveRefs; // the average number of leaf references float Edge; // the edge flow + float Power; // the power flow float Delay; // delay of the cut unsigned uSign; // cut signature unsigned Cost : 14; // the user's cost of the cut @@ -351,6 +355,7 @@ extern void If_CutLift( If_Cut_t * pCut ); extern void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc ); extern float If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut ); +extern float If_CutPowerFlow( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); extern float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut ); @@ -360,6 +365,10 @@ extern float If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut ); +extern float If_CutPowerDeref( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); +extern float If_CutPowerRef( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); +extern float If_CutPowerDerefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); +extern float If_CutPowerRefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); /*=== ifLib.c =============================================================*/ extern If_Lib_t * If_LutLibRead( char * FileName ); extern If_Lib_t * If_LutLibDup( If_Lib_t * p ); diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index afaae239..af1f5213 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -432,40 +432,144 @@ void If_ManSortCuts( If_Man_t * p, int Mode ) ***********************************************************************/ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 ) { - if ( p->SortMode == 1 ) // area + if ( p->pPars->fPower ) { - if ( pC0->Area < pC1->Area - p->fEpsilon ) + if ( p->SortMode == 1 ) // area flow + { + if ( pC0->Area < pC1->Area - p->fEpsilon ) + return -1; + if ( pC0->Area > pC1->Area + p->fEpsilon ) + return 1; + //printf("area(%.2f, %.2f), power(%.2f, %.2f), edge(%.2f, %.2f)\n", + // pC0->Area, pC1->Area, pC0->Power, pC1->Power, pC0->Edge, pC1->Edge); + if ( pC0->Power < pC1->Power - p->fEpsilon ) + return -1; + if ( pC0->Power > pC1->Power + p->fEpsilon ) + return 1; + if ( pC0->Edge < pC1->Edge - p->fEpsilon ) + return -1; + if ( pC0->Edge > pC1->Edge + p->fEpsilon ) + return 1; + if ( pC0->AveRefs > pC1->AveRefs ) + return -1; + if ( pC0->AveRefs < pC1->AveRefs ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Delay < pC1->Delay - p->fEpsilon ) + return -1; + if ( pC0->Delay > pC1->Delay + p->fEpsilon ) + return 1; + return 0; + } + if ( p->SortMode == 0 ) // delay + { + if ( pC0->Delay < pC1->Delay - p->fEpsilon ) + return -1; + if ( pC0->Delay > pC1->Delay + p->fEpsilon ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Area < pC1->Area - p->fEpsilon ) + return -1; + if ( pC0->Area > pC1->Area + p->fEpsilon ) + return 1; + if ( pC0->Power < pC1->Power - p->fEpsilon ) + return -1; + if ( pC0->Power > pC1->Power + p->fEpsilon ) + return 1; + if ( pC0->Edge < pC1->Edge - p->fEpsilon ) + return -1; + if ( pC0->Edge > pC1->Edge + p->fEpsilon ) + return 1; + return 0; + } + assert( p->SortMode == 2 ); // delay old, exact area + if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) + if ( pC0->Delay > pC1->Delay + p->fEpsilon ) + return 1; + if ( pC0->Power < pC1->Power - p->fEpsilon ) + return -1; + if ( pC0->Power > pC1->Power + p->fEpsilon ) return 1; if ( pC0->Edge < pC1->Edge - p->fEpsilon ) return -1; if ( pC0->Edge > pC1->Edge + p->fEpsilon ) return 1; - if ( pC0->AveRefs > pC1->AveRefs ) + if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; - if ( pC0->AveRefs < pC1->AveRefs ) + if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; return 0; - } - if ( p->SortMode == 0 ) // delay + } + else // reglar { + if ( p->SortMode == 1 ) // area + { + if ( pC0->Area < pC1->Area - p->fEpsilon ) + return -1; + if ( pC0->Area > pC1->Area + p->fEpsilon ) + return 1; + if ( pC0->Edge < pC1->Edge - p->fEpsilon ) + return -1; + if ( pC0->Edge > pC1->Edge + p->fEpsilon ) + return 1; + if ( pC0->Power < pC1->Power - p->fEpsilon ) + return -1; + if ( pC0->Power > pC1->Power + p->fEpsilon ) + return 1; + if ( pC0->AveRefs > pC1->AveRefs ) + return -1; + if ( pC0->AveRefs < pC1->AveRefs ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Delay < pC1->Delay - p->fEpsilon ) + return -1; + if ( pC0->Delay > pC1->Delay + p->fEpsilon ) + return 1; + return 0; + } + if ( p->SortMode == 0 ) // delay + { + if ( pC0->Delay < pC1->Delay - p->fEpsilon ) + return -1; + if ( pC0->Delay > pC1->Delay + p->fEpsilon ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Area < pC1->Area - p->fEpsilon ) + return -1; + if ( pC0->Area > pC1->Area + p->fEpsilon ) + return 1; + if ( pC0->Edge < pC1->Edge - p->fEpsilon ) + return -1; + if ( pC0->Edge > pC1->Edge + p->fEpsilon ) + return 1; + if ( pC0->Power < pC1->Power - p->fEpsilon ) + return -1; + if ( pC0->Power > pC1->Power + p->fEpsilon ) + return 1; + return 0; + } + assert( p->SortMode == 2 ); // delay old if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) @@ -474,26 +578,16 @@ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC return -1; if ( pC0->Edge > pC1->Edge + p->fEpsilon ) return 1; + if ( pC0->Power < pC1->Power - p->fEpsilon ) + return -1; + if ( pC0->Power > pC1->Power + p->fEpsilon ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; return 0; } - assert( p->SortMode == 2 ); // delay old - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; - if ( pC0->Area < pC1->Area - p->fEpsilon ) - return -1; - if ( pC0->Area > pC1->Area + p->fEpsilon ) - return 1; - if ( pC0->Edge < pC1->Edge - p->fEpsilon ) - return -1; - if ( pC0->Edge > pC1->Edge + p->fEpsilon ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - return 0; } /**Function************************************************************* @@ -818,6 +912,40 @@ float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut ) return Flow; } +/**Function************************************************************* + + Synopsis [Computes area flow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutPowerFlow( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) +{ + If_Obj_t * pLeaf; + float * pSwitching = (float *)p->vSwitching->pArray; + float Power = 0; + int i; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + Power += pSwitching[pLeaf->Id]; + if ( pLeaf->nRefs == 0 ) + Power += If_ObjCutBest(pLeaf)->Power; + else if ( p->pPars->fSeqMap ) // seq + Power += If_ObjCutBest(pLeaf)->Power / pLeaf->nRefs; + else + { + assert( pLeaf->EstRefs > p->fEpsilon ); + Power += If_ObjCutBest(pLeaf)->Power / pLeaf->EstRefs; + } + } + return Power; +} + /**Function************************************************************* Synopsis [Average number of references of the leaves.] @@ -1038,6 +1166,107 @@ float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut ) return aResult; } + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutPowerDeref( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) +{ + If_Obj_t * pLeaf; + float * pSwitching = (float *)p->vSwitching->pArray; + float Power = 0; + int i; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + Power += pSwitching[pLeaf->Id]; + assert( pLeaf->nRefs > 0 ); + if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) ) + continue; + Power += If_CutPowerDeref( p, If_ObjCutBest(pLeaf), pRoot ); + } + return Power; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutPowerRef( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) +{ + If_Obj_t * pLeaf; + float * pSwitching = (float *)p->vSwitching->pArray; + float Power = 0; + int i; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + Power += pSwitching[pLeaf->Id]; + assert( pLeaf->nRefs >= 0 ); + if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) ) + continue; + Power += If_CutPowerRef( p, If_ObjCutBest(pLeaf), pRoot ); + } + return Power; +} + +/**Function************************************************************* + + Synopsis [Computes Power of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutPowerDerefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) +{ + float aResult, aResult2; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + aResult2 = If_CutPowerRef( p, pCut, pRoot ); + aResult = If_CutPowerDeref( p, pCut, pRoot ); + assert( aResult > aResult2 - p->fEpsilon ); + assert( aResult < aResult2 + p->fEpsilon ); + return aResult; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutPowerRefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) +{ + float aResult, aResult2; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + aResult2 = If_CutPowerDeref( p, pCut, pRoot ); + aResult = If_CutPowerRef( p, pCut, pRoot ); + assert( aResult > aResult2 - p->fEpsilon ); + assert( aResult < aResult2 + p->fEpsilon ); + return aResult; +} + /**Function************************************************************* Synopsis [Computes the cone of the cut in AIG with choices.] diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c index 35b0cccc..82ee6728 100644 --- a/src/map/if/ifMan.c +++ b/src/map/if/ifMan.c @@ -145,6 +145,8 @@ void If_ManStop( If_Man_t * p ) FREE( p->pPars->pTimesReq ); if ( p->pManTim ) Tim_ManStop( p->pManTim ); + if ( p->vSwitching ) + Vec_IntFree( p->vSwitching ); free( p ); } diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index 75370dff..fc3d7cd3 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -95,6 +95,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut ); if ( p->pPars->fEdge ) pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut ); + if ( p->pPars->fPower ) + pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj ); // save the best cut from the previous iteration if ( !fPreprocess ) If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut ); @@ -141,6 +143,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut ); if ( p->pPars->fEdge ) pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut ); + if ( p->pPars->fPower ) + pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj ); pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); // insert the cut into storage If_CutSort( p, pCutSet, pCut ); @@ -227,6 +231,8 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut ); if ( p->pPars->fEdge ) pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut ); + if ( p->pPars->fPower ) + pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj ); pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); // insert the cut into storage If_CutSort( p, pCutSet, pCut ); @@ -334,8 +340,8 @@ int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPrepr if ( p->pPars->fVerbose ) { char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A')); - printf( "%c: Del = %7.2f. Ar = %9.1f. Edge = %8d. Cut = %8d. ", - Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged ); + printf( "%c: Del = %7.2f. Ar = %9.1f. Edge = %8d. Switch = %7.2f. Cut = %8d. ", + Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->dPower, p->nCutsMerged ); PRT( "T", clock() - clk ); // printf( "Max number of cuts = %d. Average number of cuts = %5.2f.\n", // p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); diff --git a/src/map/if/ifReduce.c b/src/map/if/ifReduce.c index fd1af0d7..a5fa7d86 100644 --- a/src/map/if/ifReduce.c +++ b/src/map/if/ifReduce.c @@ -55,8 +55,8 @@ void If_ManImproveMapping( If_Man_t * p ) If_ManComputeRequired( p ); if ( p->pPars->fVerbose ) { - printf( "E: Del = %7.2f. Ar = %9.1f. Edge = %8d. Cut = %8d. ", - p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged ); + printf( "E: Del = %7.2f. Ar = %9.1f. Edge = %8d. Switch = %7.2f. Cut = %8d. ", + p->RequiredGlo, p->AreaGlo, p->nNets, p->dPower, p->nCutsMerged ); PRT( "T", clock() - clk ); } diff --git a/src/map/if/ifUtil.c b/src/map/if/ifUtil.c index 57e1ad13..06015b06 100644 --- a/src/map/if/ifUtil.c +++ b/src/map/if/ifUtil.c @@ -585,6 +585,7 @@ float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pLeaf; If_Cut_t * pCutBest; + float * pSwitching = p->vSwitching? (float*)p->vSwitching->pArray : NULL; float aArea; int i; if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) ) @@ -596,7 +597,10 @@ float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj ) p->nNets += pCutBest->nLeaves; aArea = If_CutLutArea( p, pCutBest ); If_CutForEachLeaf( p, pCutBest, pLeaf, i ) + { + p->dPower += pSwitching? pSwitching[pLeaf->Id] : 0.0; aArea += If_ManMarkMapping_rec( p, pLeaf ); + } return aArea; } @@ -622,6 +626,7 @@ void If_ManMarkMapping( If_Man_t * p ) pObj->nRefs = 0; } p->nNets = 0; + p->dPower = 0.0; p->AreaGlo = 0.0; If_ManForEachCo( p, pObj, i ) p->AreaGlo += If_ManMarkMapping_rec( p, If_ObjFanin0(pObj) ); diff --git a/src/map/mapper/mapperTime.c b/src/map/mapper/mapperTime.c index cc4173cf..309863fd 100644 --- a/src/map/mapper/mapperTime.c +++ b/src/map/mapper/mapperTime.c @@ -206,7 +206,7 @@ void Map_TimeComputeRequiredGlobal( Map_Man_t * p ) } else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon ) { - if ( p->fMappingMode == 1 ) + if ( p->fMappingMode == 1 && p->fVerbose ) printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget ); p->fRequiredGlo = p->DelayTarget; } diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index 37ba82c2..1326dbbf 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -28,6 +28,10 @@ #include "mioInt.h" #include "mapper.h" +extern void Amap_LibFree( void * p ); +extern void Amap_LibPrintSelectedGates( void * p, int fAllGates ); +extern void * Amap_LibReadAndPrepare( char * pFileName, int fVerbose, int fVeryVerbose ); + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -35,6 +39,9 @@ static int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); static int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); +static int Mio_CommandReadLibrary2( Abc_Frame_t * pAbc, int argc, char **argv ); +static int Mio_CommandPrintLibrary2( Abc_Frame_t * pAbc, int argc, char **argv ); + // internal version of GENLIB library static char * pMcncGenlib[25] = { "GATE inv1 1 O=!a; PIN * INV 1 999 0.9 0.0 0.9 0.0\n", @@ -78,7 +85,7 @@ static char * pMcncGenlib[25] = { void Mio_Init( Abc_Frame_t * pAbc ) { char * pFileTemp = "mcnc_temp.genlib"; - Mio_Library_t * pLibGen; + void * pLibGen; FILE * pFile; int i; @@ -90,6 +97,9 @@ void Mio_Init( Abc_Frame_t * pAbc ) // read genlib from file pLibGen = Mio_LibraryRead( pAbc, pFileTemp, NULL, 0 ); Abc_FrameSetLibGen( pLibGen ); + pLibGen = Amap_LibReadAndPrepare( pFileTemp, 0, 0 ); + Abc_FrameSetLibGen2( pLibGen ); + #ifdef WIN32 _unlink( pFileTemp ); #else @@ -98,6 +108,9 @@ void Mio_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "SC mapping", "read_library", Mio_CommandReadLibrary, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "print_library", Mio_CommandPrintLibrary, 0 ); + + Cmd_CommandAdd( pAbc, "SC mapping", "read_library2", Mio_CommandReadLibrary2, 0 ); + Cmd_CommandAdd( pAbc, "SC mapping", "print_library2", Mio_CommandPrintLibrary2, 0 ); } /**Function************************************************************* @@ -115,6 +128,7 @@ void Mio_End() { // Mio_LibraryDelete( s_pLib ); Mio_LibraryDelete( Abc_FrameReadLibGen() ); + Amap_LibFree( Abc_FrameReadLibGen2() ); } @@ -190,25 +204,124 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) if ( Abc_FrameReadLibSuper() ) { extern void Map_SuperLibFree( Map_SuperLib_t * p ); -// Map_SuperLibFree( s_pSuperLib ); -// s_pSuperLib = NULL; Map_SuperLibFree( Abc_FrameReadLibSuper() ); Abc_FrameSetLibSuper( NULL ); } // replace the current library -// Mio_LibraryDelete( s_pLib ); -// s_pLib = pLib; Mio_LibraryDelete( Abc_FrameReadLibGen() ); Abc_FrameSetLibGen( pLib ); + + // set the new network + pLib = Amap_LibReadAndPrepare( FileName, 1, 0 ); + if ( pLib == NULL ) + { + fprintf( pErr, "Reading GENLIB library has failed.\n" ); + return 1; + } + // replace the current library + Amap_LibFree( Abc_FrameReadLibGen2() ); + Abc_FrameSetLibGen2( pLib ); return 0; usage: fprintf( pErr, "usage: read_library [-vh]\n"); fprintf( pErr, "\t read the library from a genlib file\n" ); fprintf( pErr, "\t (if the library contains more than one gate\n" ); - fprintf( pErr, "\t with the same Boolean function, only the first gate\n" ); - fprintf( pErr, "\t in the order of their appearance in the file is used)\n" ); + fprintf( pErr, "\t with the same Boolean function, only the gate\n" ); + fprintf( pErr, "\t with the smallest area will be used)\n" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : enable verbose output\n"); + return 1; /* error exit */ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_CommandReadLibrary2( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Mio_Library_t * pLib; + Abc_Ntk_t * pNet; + char * FileName; + int fVerbose; + int fVeryVerbose; + int c; + + pNet = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fVerbose = 1; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vwh")) != EOF ) + { + switch (c) + { + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) + { + fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) ) + fprintf( pErr, "Did you mean \"%s\"?", FileName ); + fprintf( pErr, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pLib = Amap_LibReadAndPrepare( FileName, fVerbose, fVeryVerbose ); + if ( pLib == NULL ) + { + fprintf( pErr, "Reading GENLIB library has failed.\n" ); + return 1; + } + + // replace the current library + Amap_LibFree( Abc_FrameReadLibGen2() ); + Abc_FrameSetLibGen2( pLib ); + return 0; + +usage: + fprintf( pErr, "usage: read_library2 [-vh]\n"); + fprintf( pErr, "\t read the library from a genlib file\n" ); + fprintf( pErr, "\t (if the library contains more than one gate\n" ); + fprintf( pErr, "\t with the same Boolean function, only the gate\n" ); + fprintf( pErr, "\t with the smallest area will be used)\n" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle detailed printout [default = %s]\n", fVeryVerbose? "yes": "no" ); fprintf( pErr, "\t-h : enable verbose output\n"); return 1; /* error exit */ } @@ -271,6 +384,72 @@ usage: fprintf( pErr, "\t-h : print the command usage\n"); return 1; /* error exit */ } + + +/**Function************************************************************* + + Synopsis [Command procedure to read LUT libraries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_CommandPrintLibrary2( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNet; + int fPrintAll; + int fVerbose; + int c; + + pNet = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fPrintAll = 0; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "avh")) != EOF ) + { + switch (c) + { + case 'a': + fPrintAll ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc != globalUtilOptind ) + { + goto usage; + } + + // set the new network + Amap_LibPrintSelectedGates( Abc_FrameReadLibGen2(), fPrintAll ); + return 0; + +usage: + fprintf( pErr, "\nusage: print_library2 [-avh]\n"); + fprintf( pErr, "\t print gates used for area-oriented tech-mapping\n" ); + fprintf( pErr, "\t-a : toggles printing all gates [default = %s]\n", (fPrintAll? "yes" : "no") ); + fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; /* error exit */ +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h index dbe2420b..0e5a39d3 100644 --- a/src/map/mio/mio.h +++ b/src/map/mio/mio.h @@ -79,6 +79,7 @@ typedef struct Mio_PinStruct_t_ Mio_Pin_t; extern char * Mio_LibraryReadName ( Mio_Library_t * pLib ); extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ); +extern Mio_Gate_t ** Mio_LibraryReadGatesByName( Mio_Library_t * pLib ); extern DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName ); extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char * pName ); @@ -110,6 +111,8 @@ extern int Mio_GateReadInputs ( Mio_Gate_t * pGate ); extern double Mio_GateReadDelayMax ( Mio_Gate_t * pGate ); extern char * Mio_GateReadSop ( Mio_Gate_t * pGate ); extern DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ); +extern int Mio_GateReadValue ( Mio_Gate_t * pGate ); +extern void Mio_GateSetValue ( Mio_Gate_t * pGate, int Value ); extern char * Mio_PinReadName ( Mio_Pin_t * pPin ); extern Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin ); extern double Mio_PinReadInputLoad ( Mio_Pin_t * pPin ); diff --git a/src/map/mio/mio81214.zip b/src/map/mio/mio81214.zip new file mode 100644 index 00000000..12f766a9 Binary files /dev/null and b/src/map/mio/mio81214.zip differ diff --git a/src/map/mio/mioApi.c b/src/map/mio/mioApi.c index 73473f8b..61cc2509 100644 --- a/src/map/mio/mioApi.c +++ b/src/map/mio/mioApi.c @@ -40,6 +40,7 @@ char * Mio_LibraryReadName ( Mio_Library_t * pLib ) { return pLib->pName; } int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ) { return pLib->nGates; } Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { return pLib->pGates; } +Mio_Gate_t ** Mio_LibraryReadGatesByName ( Mio_Library_t * pLib ) { return pLib->ppGatesName;} DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ) { return pLib->dd; } Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ) { return pLib->pGateBuf; } Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ) { return pLib->pGateInv; } @@ -131,17 +132,19 @@ char * Mio_LibraryReadSopByName( Mio_Library_t * pLib, char * pName ) SeeAlso [] ***********************************************************************/ -char * Mio_GateReadName ( Mio_Gate_t * pGate ) { return pGate->pName; } -char * Mio_GateReadOutName ( Mio_Gate_t * pGate ) { return pGate->pOutName; } -double Mio_GateReadArea ( Mio_Gate_t * pGate ) { return pGate->dArea; } -char * Mio_GateReadForm ( Mio_Gate_t * pGate ) { return pGate->pForm; } -Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ) { return pGate->pPins; } -Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ) { return pGate->pLib; } -Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ) { return pGate->pNext; } -int Mio_GateReadInputs ( Mio_Gate_t * pGate ) { return pGate->nInputs; } -double Mio_GateReadDelayMax( Mio_Gate_t * pGate ) { return pGate->dDelayMax; } -char * Mio_GateReadSop ( Mio_Gate_t * pGate ) { return pGate->pSop; } -DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ) { return pGate->bFunc; } +char * Mio_GateReadName ( Mio_Gate_t * pGate ) { return pGate->pName; } +char * Mio_GateReadOutName ( Mio_Gate_t * pGate ) { return pGate->pOutName; } +double Mio_GateReadArea ( Mio_Gate_t * pGate ) { return pGate->dArea; } +char * Mio_GateReadForm ( Mio_Gate_t * pGate ) { return pGate->pForm; } +Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ) { return pGate->pPins; } +Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ) { return pGate->pLib; } +Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ) { return pGate->pNext; } +int Mio_GateReadInputs ( Mio_Gate_t * pGate ) { return pGate->nInputs; } +double Mio_GateReadDelayMax( Mio_Gate_t * pGate ) { return pGate->dDelayMax; } +char * Mio_GateReadSop ( Mio_Gate_t * pGate ) { return pGate->pSop; } +DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ) { return pGate->bFunc; } +int Mio_GateReadValue ( Mio_Gate_t * pGate ) { return pGate->Value; } +void Mio_GateSetValue ( Mio_Gate_t * pGate, int Value ) { pGate->Value = Value; } /**Function************************************************************* diff --git a/src/map/mio/mioGENERIC.c b/src/map/mio/mioGENERIC.c deleted file mode 100644 index 972c4ffc..00000000 --- a/src/map/mio/mioGENERIC.c +++ /dev/null @@ -1,46 +0,0 @@ -/**CFile**************************************************************** - - FileName [mio___.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mio___.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mioInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mio/mioInt.h b/src/map/mio/mioInt.h index 3f90b625..654b7e19 100644 --- a/src/map/mio/mioInt.h +++ b/src/map/mio/mioInt.h @@ -54,6 +54,8 @@ struct Mio_LibraryStruct_t_ { char * pName; // the name of the library int nGates; // the number of the gates + Mio_Gate_t ** ppGates0; // the array of gates in the original order + Mio_Gate_t ** ppGatesName; // the array of gates sorted by name Mio_Gate_t * pGates; // the linked list of all gates in no particular order Mio_Gate_t * pGate0; // the constant zero gate Mio_Gate_t * pGate1; // the constant one gate @@ -84,7 +86,8 @@ struct Mio_GateStruct_t_ int nInputs; // the number of inputs double dDelayMax; // the maximum delay DdNode * bFunc; // the functionality - char * pSop; + char * pSop; // sum-of-products + int Value; // user's information }; struct Mio_PinStruct_t_ diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c index 5b92d3e1..ae33c942 100644 --- a/src/map/mio/mioRead.c +++ b/src/map/mio/mioRead.c @@ -407,6 +407,85 @@ char * chomp( char *s ) return a; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_LibraryCompareGatesByArea( Mio_Gate_t ** pp1, Mio_Gate_t ** pp2 ) +{ + double Diff = (*pp1)->dArea - (*pp2)->dArea; + if ( Diff < 0.0 ) + return -1; + if ( Diff > 0.0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_LibraryCompareGatesByName( Mio_Gate_t ** pp1, Mio_Gate_t ** pp2 ) +{ + int Diff = strcmp( (*pp1)->pName, (*pp2)->pName ); + if ( Diff < 0.0 ) + return -1; + if ( Diff > 0.0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_LibrarySortGates( Mio_Library_t * pLib ) +{ + Mio_Gate_t ** ppGates, * pGate; + int i = 0; + ppGates = ALLOC( Mio_Gate_t *, pLib->nGates ); + Mio_LibraryForEachGate( pLib, pGate ) + ppGates[i++] = pGate; + assert( i == pLib->nGates ); + // sort gates by area + pLib->ppGates0 = ALLOC( Mio_Gate_t *, pLib->nGates ); + for ( i = 0; i < pLib->nGates; i++ ) + pLib->ppGates0[i] = ppGates[i]; + qsort( (void *)ppGates, pLib->nGates, sizeof(void *), + (int (*)(const void *, const void *)) Mio_LibraryCompareGatesByArea ); + for ( i = 0; i < pLib->nGates; i++ ) + ppGates[i]->pNext = (i < pLib->nGates-1)? ppGates[i+1] : NULL; + pLib->pGates = ppGates[0]; + free( ppGates ); + // sort gates by name + pLib->ppGatesName = ALLOC( Mio_Gate_t *, pLib->nGates ); + for ( i = 0; i < pLib->nGates; i++ ) + pLib->ppGatesName[i] = pLib->ppGates0[i]; + qsort( (void *)pLib->ppGatesName, pLib->nGates, sizeof(void *), + (int (*)(const void *, const void *)) Mio_LibraryCompareGatesByName ); +} + /**Function************************************************************* Synopsis [] @@ -423,6 +502,8 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ) Mio_Gate_t * pGate; DdNode * bFuncBuf, * bFuncInv, * bFuncNand2, * bFuncAnd2; + Mio_LibrarySortGates( pLib ); + bFuncBuf = pLib->dd->vars[0]; Cudd_Ref( bFuncBuf ); bFuncInv = Cudd_Not( pLib->dd->vars[0] ); Cudd_Ref( bFuncInv ); bFuncNand2 = Cudd_bddNand( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncNand2 ); diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c index bd3d01f7..2a1d1f30 100644 --- a/src/map/mio/mioUtils.c +++ b/src/map/mio/mioUtils.c @@ -59,6 +59,8 @@ void Mio_LibraryDelete( Mio_Library_t * pLib ) st_free_table( pLib->tName2Gate ); if ( pLib->dd ) Cudd_Quit( pLib->dd ); + FREE( pLib->ppGates0 ); + FREE( pLib->ppGatesName ); free( pLib ); } @@ -82,7 +84,7 @@ void Mio_GateDelete( Mio_Gate_t * pGate ) if ( pGate->bFunc ) Cudd_RecursiveDeref( pGate->pLib->dd, pGate->bFunc ); Mio_GateForEachPinSafe( pGate, pPin, pPin2 ) - Mio_PinDelete( pPin ); + Mio_PinDelete( pPin ); free( pGate ); } @@ -142,11 +144,14 @@ Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ) ***********************************************************************/ void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops ) { - Mio_Gate_t * pGate; +// Mio_Gate_t * pGate; + int i; fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName ); - Mio_LibraryForEachGate( pLib, pGate ) - Mio_WriteGate( pFile, pGate, fPrintSops ); +// Mio_LibraryForEachGate( pLib, pGate ) +// Mio_WriteGate( pFile, pGate, fPrintSops ); + for ( i = 0; i < pLib->nGates; i++ ) + Mio_WriteGate( pFile, pLib->ppGates0[i], fPrintSops ); } /**Function************************************************************* diff --git a/src/map/super/superGate.c b/src/map/super/superGate.c index 915ff86d..c8aa02ba 100644 --- a/src/map/super/superGate.c +++ b/src/map/super/superGate.c @@ -345,7 +345,12 @@ Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGat continue; } } - +/* + if ( strcmp(Mio_GateReadName(ppGates[k]), "MUX2IX0") == 0 ) + { + int s = 0; + } +*/ // select the subset of gates to be considered with this root gate // all the gates past this point will lead to delay larger than the limit tDelayMio = (float)Mio_GateReadDelayMax(ppGates[k]); diff --git a/src/misc/avl/avl.c b/src/misc/avl/avl.c new file mode 100644 index 00000000..2c2dec88 --- /dev/null +++ b/src/misc/avl/avl.c @@ -0,0 +1,616 @@ +/* + * Revision Control Information + * + * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.c,v $ + * $Author: sis $ + * $Revision: 1.3 $ + * $Date: 1994/07/15 23:00:40 $ + * + */ +/* LINTLIBRARY */ + + +#include +#include + +#include "avl.h" + + + +#define HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height) +#define BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left)) + +#define compute_height(node) { \ + int x=HEIGHT(node->left), y=HEIGHT(node->right); \ + (node)->height = MAX(x,y) + 1; \ +} + +#define COMPARE(key, nodekey, compare) \ + ((compare == avl_numcmp) ? \ + (int) key - (int) nodekey : \ + (*compare)(key, nodekey)) + + +#define STACK_SIZE 50 + +static avl_node *new_node (); +static avl_node *find_rightmost (); +static void do_rebalance (); +static rotate_left (); +static rotate_right (); +static int do_check_tree (); + +avl_tree * +avl_init_table (compar) + int (*compar) (); +{ + avl_tree *tree; + + tree = ALLOC (avl_tree, 1); + tree->root = NIL (avl_node); + tree->compar = compar; + tree->num_entries = 0; + return tree; +} + + + +avl_lookup (tree, key, value_p) + avl_tree *tree; + register char *key; + char **value_p; +{ + register avl_node *node; + register int (*compare) () = tree->compar, diff; + + node = tree->root; + while (node != NIL (avl_node)) + { + diff = COMPARE (key, node->key, compare); + if (diff == 0) + { + /* got a match */ + if (value_p != NIL (char *)) + *value_p = node->value; + return 1; + } + node = (diff < 0) ? node->left : node->right; + } + return 0; +} + +avl_first (tree, key_p, value_p) + avl_tree *tree; + char **key_p; + char **value_p; +{ + register avl_node *node; + + if (tree->root == 0) + { + return 0; /* no entries */ + } + else + { + /* walk down the tree; stop at leftmost leaf */ + for (node = tree->root; node->left != 0; node = node->left) + { + } + if (key_p != NIL (char *)) + *key_p = node->key; + if (value_p != NIL (char *)) + *value_p = node->value; + return 1; + } +} + + +avl_last (tree, key_p, value_p) + avl_tree *tree; + char **key_p; + char **value_p; +{ + register avl_node *node; + + if (tree->root == 0) + { + return 0; /* no entries */ + } + else + { + /* walk down the tree; stop at rightmost leaf */ + for (node = tree->root; node->right != 0; node = node->right) + { + } + if (key_p != NIL (char *)) + *key_p = node->key; + if (value_p != NIL (char *)) + *value_p = node->value; + return 1; + } +} + +avl_insert (tree, key, value) + avl_tree *tree; + char *key; + char *value; +{ + register avl_node **node_p, *node; + register int stack_n = 0; + register int (*compare) () = tree->compar; + avl_node **stack_nodep[STACK_SIZE]; + int diff, status; + + node_p = &tree->root; + + /* walk down the tree (saving the path); stop at insertion point */ + status = 0; + while ((node = *node_p) != NIL (avl_node)) + { + stack_nodep[stack_n++] = node_p; + diff = COMPARE (key, node->key, compare); + if (diff == 0) + status = 1; + node_p = (diff < 0) ? &node->left : &node->right; + } + + /* insert the item and re-balance the tree */ + *node_p = new_node (key, value); + do_rebalance (stack_nodep, stack_n); + tree->num_entries++; + tree->modified = 1; + return status; +} + + + +avl_find_or_add (tree, key, slot_p) + avl_tree *tree; + char *key; + char ***slot_p; +{ + register avl_node **node_p, *node; + register int stack_n = 0; + register int (*compare) () = tree->compar; + avl_node **stack_nodep[STACK_SIZE]; + int diff; + + node_p = &tree->root; + + /* walk down the tree (saving the path); stop at insertion point */ + while ((node = *node_p) != NIL (avl_node)) + { + stack_nodep[stack_n++] = node_p; + diff = COMPARE (key, node->key, compare); + if (diff == 0) + { + if (slot_p != 0) + *slot_p = &node->value; + return 1; /* found */ + } + node_p = (diff < 0) ? &node->left : &node->right; + } + + /* insert the item and re-balance the tree */ + *node_p = new_node (key, NIL (char)); + if (slot_p != 0) + *slot_p = &(*node_p)->value; + do_rebalance (stack_nodep, stack_n); + tree->num_entries++; + tree->modified = 1; + return 0; /* not already in tree */ +} + +avl_delete (tree, key_p, value_p) + avl_tree *tree; + char **key_p; + char **value_p; +{ + register avl_node **node_p, *node, *rightmost; + register int stack_n = 0; + char *key = *key_p; + int (*compare) () = tree->compar, diff; + avl_node **stack_nodep[STACK_SIZE]; + + node_p = &tree->root; + + /* Walk down the tree saving the path; return if not found */ + while ((node = *node_p) != NIL (avl_node)) + { + diff = COMPARE (key, node->key, compare); + if (diff == 0) + goto delete_item; + stack_nodep[stack_n++] = node_p; + node_p = (diff < 0) ? &node->left : &node->right; + } + return 0; /* not found */ + + /* prepare to delete node and replace it with rightmost of left tree */ + delete_item: + *key_p = node->key; + if (value_p != 0) + *value_p = node->value; + if (node->left == NIL (avl_node)) + { + *node_p = node->right; + } + else + { + rightmost = find_rightmost (&node->left); + rightmost->left = node->left; + rightmost->right = node->right; + rightmost->height = -2; /* mark bogus height for do_rebal */ + *node_p = rightmost; + stack_nodep[stack_n++] = node_p; + } + FREE (node); + + /* work our way back up, re-balancing the tree */ + do_rebalance (stack_nodep, stack_n); + tree->num_entries--; + tree->modified = 1; + return 1; +} + +static void +avl_record_gen_forward (node, gen) + avl_node *node; + avl_generator *gen; +{ + if (node != NIL (avl_node)) + { + avl_record_gen_forward (node->left, gen); + gen->nodelist[gen->count++] = node; + avl_record_gen_forward (node->right, gen); + } +} + + +static void +avl_record_gen_backward (node, gen) + avl_node *node; + avl_generator *gen; +{ + if (node != NIL (avl_node)) + { + avl_record_gen_backward (node->right, gen); + gen->nodelist[gen->count++] = node; + avl_record_gen_backward (node->left, gen); + } +} + + +avl_generator * +avl_init_gen (tree, dir) + avl_tree *tree; + int dir; +{ + avl_generator *gen; + + /* what a hack */ + gen = ALLOC (avl_generator, 1); + gen->tree = tree; + gen->nodelist = ALLOC (avl_node *, avl_count (tree)); + gen->count = 0; + if (dir == AVL_FORWARD) + { + avl_record_gen_forward (tree->root, gen); + } + else + { + avl_record_gen_backward (tree->root, gen); + } + gen->count = 0; + + /* catch any attempt to modify the tree while we generate */ + tree->modified = 0; + return gen; +} + + +avl_gen (gen, key_p, value_p) + avl_generator *gen; + char **key_p; + char **value_p; +{ + avl_node *node; + + if (gen->count == gen->tree->num_entries) + { + return 0; + } + else + { + node = gen->nodelist[gen->count++]; + if (key_p != NIL (char *)) + *key_p = node->key; + if (value_p != NIL (char *)) + *value_p = node->value; + return 1; + } +} + + +void +avl_free_gen (gen) + avl_generator *gen; +{ + FREE (gen->nodelist); + FREE (gen); +} + +static avl_node * +find_rightmost (node_p) + register avl_node **node_p; +{ + register avl_node *node; + register int stack_n = 0; + avl_node **stack_nodep[STACK_SIZE]; + + node = *node_p; + while (node->right != NIL (avl_node)) + { + stack_nodep[stack_n++] = node_p; + node_p = &node->right; + node = *node_p; + } + *node_p = node->left; + + do_rebalance (stack_nodep, stack_n); + return node; +} + + +static void +do_rebalance (stack_nodep, stack_n) + register avl_node ***stack_nodep; + register int stack_n; +{ + register avl_node **node_p, *node; + register int hl, hr; + int height; + + /* work our way back up, re-balancing the tree */ + while (--stack_n >= 0) + { + node_p = stack_nodep[stack_n]; + node = *node_p; + hl = HEIGHT (node->left); /* watch for NIL */ + hr = HEIGHT (node->right); /* watch for NIL */ + if ((hr - hl) < -1) + { + rotate_right (node_p); + } + else if ((hr - hl) > 1) + { + rotate_left (node_p); + } + else + { + height = MAX (hl, hr) + 1; + if (height == node->height) + break; + node->height = height; + } + } +} + +static +rotate_left (node_p) + register avl_node **node_p; +{ + register avl_node *old_root = *node_p, *new_root, *new_right; + + if (BALANCE (old_root->right) >= 0) + { + *node_p = new_root = old_root->right; + old_root->right = new_root->left; + new_root->left = old_root; + } + else + { + new_right = old_root->right; + *node_p = new_root = new_right->left; + old_root->right = new_root->left; + new_right->left = new_root->right; + new_root->right = new_right; + new_root->left = old_root; + compute_height (new_right); + } + compute_height (old_root); + compute_height (new_root); +} + + +static +rotate_right (node_p) + avl_node **node_p; +{ + register avl_node *old_root = *node_p, *new_root, *new_left; + + if (BALANCE (old_root->left) <= 0) + { + *node_p = new_root = old_root->left; + old_root->left = new_root->right; + new_root->right = old_root; + } + else + { + new_left = old_root->left; + *node_p = new_root = new_left->right; + old_root->left = new_root->right; + new_left->right = new_root->left; + new_root->left = new_left; + new_root->right = old_root; + compute_height (new_left); + } + compute_height (old_root); + compute_height (new_root); +} + +static void +avl_walk_forward (node, func) + avl_node *node; + void (*func) (); +{ + if (node != NIL (avl_node)) + { + avl_walk_forward (node->left, func); + (*func) (node->key, node->value); + avl_walk_forward (node->right, func); + } +} + + +static void +avl_walk_backward (node, func) + avl_node *node; + void (*func) (); +{ + if (node != NIL (avl_node)) + { + avl_walk_backward (node->right, func); + (*func) (node->key, node->value); + avl_walk_backward (node->left, func); + } +} + + +void +avl_foreach (tree, func, direction) + avl_tree *tree; + void (*func) (); + int direction; +{ + if (direction == AVL_FORWARD) + { + avl_walk_forward (tree->root, func); + } + else + { + avl_walk_backward (tree->root, func); + } +} + + +static void +free_entry (node, key_free, value_free) + avl_node *node; + void (*key_free) (); + void (*value_free) (); +{ + if (node != NIL (avl_node)) + { + free_entry (node->left, key_free, value_free); + free_entry (node->right, key_free, value_free); + if (key_free != 0) + (*key_free) (node->key); + if (value_free != 0) + (*value_free) (node->value); + FREE (node); + } +} + + +void +avl_free_table (tree, key_free, value_free) + avl_tree *tree; + void (*key_free) (); + void (*value_free) (); +{ + free_entry (tree->root, key_free, value_free); + FREE (tree); +} + + +int +avl_count (tree) + avl_tree *tree; +{ + return tree->num_entries; +} + +static avl_node * +new_node (key, value) + char *key; + char *value; +{ + register avl_node *new; + + new = ALLOC (avl_node, 1); + new->key = key; + new->value = value; + new->height = 0; + new->left = new->right = NIL (avl_node); + return new; +} + + +int +avl_numcmp (x, y) + char *x, *y; +{ + return (int) x - (int) y; +} + +int +avl_check_tree (tree) + avl_tree *tree; +{ + int error = 0; + (void) do_check_tree (tree->root, tree->compar, &error); + return error; +} + + +static int +do_check_tree (node, compar, error) + avl_node *node; + int (*compar) (); + int *error; +{ + int l_height, r_height, comp_height, bal; + + if (node == NIL (avl_node)) + { + return -1; + } + + r_height = do_check_tree (node->right, compar, error); + l_height = do_check_tree (node->left, compar, error); + + comp_height = MAX (l_height, r_height) + 1; + bal = r_height - l_height; + + if (comp_height != node->height) + { + (void) printf ("Bad height for 0x%08x: computed=%d stored=%d\n", + node, comp_height, node->height); + ++*error; + } + + if (bal > 1 || bal < -1) + { + (void) printf ("Out of balance at node 0x%08x, balance = %d\n", + node, bal); + ++*error; + } + + if (node->left != NIL (avl_node) && + (*compar) (node->left->key, node->key) > 0) + { + (void) printf ("Bad ordering between 0x%08x and 0x%08x", + node, node->left); + ++*error; + } + + if (node->right != NIL (avl_node) && + (*compar) (node->key, node->right->key) > 0) + { + (void) printf ("Bad ordering between 0x%08x and 0x%08x", + node, node->right); + ++*error; + } + + return comp_height; +} diff --git a/src/misc/avl/avl.doc b/src/misc/avl/avl.doc new file mode 100644 index 00000000..a9753b3a --- /dev/null +++ b/src/misc/avl/avl.doc @@ -0,0 +1,166 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/avl/avl.doc,v + * rajeev + * 1.3 + * 1995/08/08 22:36:22 + * + */ +avl_tree * +avl_init_table(compare) +int (*compare)(); + Initialize and return a new avl_tree. Use the function `compare' to + compare items in the tree. `compare' should be of the form: + + int + compare(a,b) + char *a, *b; + + and return a number < 0, == 0, > 0 depending on whether a < b, + a == b, or a > b, respectively. + + +void +avl_free_table(tree, key_delete_func, value_delete_func) +avl_tree *tree; +void (*key_delete_func)(); +void (*value_delete_func)(); + + Delete all storage associated with `tree'. The functions + key_delete_func and value_delete_func, if non-null, are called + to free each (key, value) pair. They are declared as: + + void + key_delete_func(key) + char *key; + {} + + void + value_delete_func(value) + char *value; + {} + + The C-library function free is often suitable as a free function. + + +avl_first(tree, key_p, value_p) +avl_tree *tree; +char **key_p; +char **value_p; + Retrieves the smallest element in the tree. Returns 0 if there + are no elements in the tree. + + +avl_last(tree, key_p, value_p) +avl_tree *tree; +char **key_p; +char **value_p; + Retrieves the largest element in the tree. Returns 0 if there + are no elements in the tree. + + +avl_lookup(tree, key, value_p) +avl_tree *tree; +char *key; +char **value_p; + Search for an entry matching `key'. If found, set `value_p' to + the associated value field and return 1. If not found, return + 0 and leave `value_p' unchanged. + + +avl_insert(tree, key, value); +avl_tree *tree; +char *key; +char *value; + Insert the value `value' under the key `key'. Multiple items + are allowed with the same value; all are inserted. + + +avl_delete(tree, key_p, value_p) +avl_tree *tree; +char **key_p; +char **value_p; + Search for the item with key `*key_p' in `tree'. If found, set + `key_p' and `value_p' to point to the key and value of item, + delete the item and return 1. Otherwise return 0 and leave + `key_p' and `value_p' unchanged. WARNING: This interface is + buggy; in particular, if identical keys are in the table, it is + not possible to delete a particular (key, value) pair. This + will be fixed either with 'handles' or a separate delete + function. + + +avl_find_or_add(tree, key, slot_p) +avl_tree *tree; +char *key; +char ***slot_p; + Search for an entry matching key; if not found, insert key and + return the address of the value slot for this entry. If found, + do not insert key, and return the address of the value slot for + the existing entry. slot_p can be used to associate a value with + the key. + + +void +avl_foreach(tree, func, direction) +avl_tree *tree; +int (*func)(); +int direction; + + Apply `func' to each item in the tree `tree' in turn. If + direction is AVL_FORWARD, the tree is traversed from smallest + to largest. Otherwise it is traversed from largest to smallest. + + func should be of the form: + + void + func(key, value) + char *key; + char *value; + + where `key' is the key the item was stored under, and `value' + the value of the item. + + +avl_count(tree) +avl_tree *tree; + Returns the number of entries in the avl tree. + + +avl_generator * +avl_init_gen(tree, direction) +avl_tree *tree; +int direction; + Start up a generator on an avl-tree. direction is either + AVL_FORWARD or AVL_BACKWARD indicating the direction of + generation. + + +avl_gen(gen, key_p, value_p) +avl_generator *gen; +char **key_p; +char **value_p; + Generate the next item from the avl-tree. Returns 0 if there + are no more items in the tree. Deletion of last generated item + (via avl_delete) is supported. Insertion of items during + generation will result in these items never being generated + (until the next avl_init_gen()). Excercise for the interested + student: how does one write an avl generator ? + + +void +avl_free_gen(gen) +avl_generator *gen; + Free a generator. + + +avl_foreach_item(tree, gen, direction, key_p, value_p) +avl_tree *tree; +avl_generator *gen; +int direction; +char **key_p; +char **value_p; + Generate over all items in an avl-tree. This macro iterator + combines avl_init_gen(), avl_gen(), and avl_free_gen() into + a single statement iterator. diff --git a/src/misc/avl/avl.h b/src/misc/avl/avl.h new file mode 100644 index 00000000..21d811da --- /dev/null +++ b/src/misc/avl/avl.h @@ -0,0 +1,80 @@ +/* + * Revision Control Information + * + * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.h,v $ + * $Author: sis $ + * $Revision: 1.3 $ + * $Date: 1994/07/15 23:00:40 $ + * + */ +#ifndef AVL_INCLUDED +#define AVL_INCLUDED + +#define EXTERN +#define ARGS(protos) protos + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +#define NIL(type) \ + ((type *) 0) +#define ALLOC(type, num) \ + ((type *) malloc(sizeof(type) * (num))) +#define REALLOC(type, obj, num) \ + ((type *) realloc((char *) obj, sizeof(type) * (num))) +#define FREE(obj) \ + free((char *) (obj)) + + + +typedef struct avl_node_struct avl_node; +struct avl_node_struct { + avl_node *left, *right; + char *key; + char *value; + int height; +}; + + +typedef struct avl_tree_struct avl_tree; +struct avl_tree_struct { + avl_node *root; + int (*compar)(); + int num_entries; + int modified; +}; + + +typedef struct avl_generator_struct avl_generator; +struct avl_generator_struct { + avl_tree *tree; + avl_node **nodelist; + int count; +}; + + +#define AVL_FORWARD 0 +#define AVL_BACKWARD 1 + + +EXTERN avl_tree *avl_init_table ARGS((int (*)())); +EXTERN int avl_delete ARGS((avl_tree *, char **, char **)); +EXTERN int avl_insert ARGS((avl_tree *, char *, char *)); +EXTERN int avl_lookup ARGS((avl_tree *, char *, char **)); +EXTERN int avl_first ARGS((avl_tree *, char **, char **)); +EXTERN int avl_last ARGS((avl_tree *, char **, char **)); +EXTERN int avl_find_or_add ARGS((avl_tree *, char *, char ***)); +EXTERN int avl_count ARGS((avl_tree *)); +EXTERN int avl_numcmp ARGS((char *, char *)); +EXTERN int avl_gen ARGS((avl_generator *, char **, char **)); +EXTERN void avl_foreach ARGS((avl_tree *, void (*)(), int)); +EXTERN void avl_free_table ARGS((avl_tree *, void (*)(), void (*)())); +EXTERN void avl_free_gen ARGS((avl_generator *)); +EXTERN avl_generator *avl_init_gen ARGS((avl_tree *, int)); + +#define avl_is_member(tree, key) avl_lookup(tree, key, (char **) 0) + +#define avl_foreach_item(table, gen, dir, key_p, value_p) \ + for(gen = avl_init_gen(table, dir); \ + avl_gen(gen, key_p, value_p) || (avl_free_gen(gen),0);) + +#endif diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index beb5a4d0..d7a3e98c 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -41,12 +41,6 @@ extern "C" { /* Nested includes */ /*---------------------------------------------------------------------------*/ -// this include should be the first one in the list -// it is used to catch memory leaks on Windows -#if defined(_DEBUG) && defined(_MSC_VER) && (_MSC_VER <= 1200) // 1200 = MSVC 6.0 -#include "leaks.h" -#endif - #include #include #include @@ -56,6 +50,12 @@ extern "C" { #include "cuddInt.h" #include "port_type.h" +// catch memory leaks in Visual Studio +#ifdef _DEBUG +#define _CRTDBG_MAP_ALLOC +#include +#endif + /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ @@ -77,17 +77,16 @@ extern "C" { /*---------------------------------------------------------------------------*/ #ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#define DLLIMPORT __declspec(dllimport) +#define ABC_DLLEXPORT __declspec(dllexport) +#define ABC_DLLIMPORT __declspec(dllimport) #else /* defined(WIN32) */ -#define DLLIMPORT +#define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL -#define ABC_DLL DLLIMPORT +#define ABC_DLL ABC_DLLIMPORT #endif - typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; diff --git a/src/misc/extra/extraUtilMemory.c b/src/misc/extra/extraUtilMemory.c index 39c34296..e672afbb 100644 --- a/src/misc/extra/extraUtilMemory.c +++ b/src/misc/extra/extraUtilMemory.c @@ -339,7 +339,7 @@ int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p ) ***********************************************************************/ Extra_MmFlex_t * Extra_MmFlexStart() -{ +{ Extra_MmFlex_t * p; //printf( "allocing flex\n" ); p = ALLOC( Extra_MmFlex_t, 1 ); @@ -349,7 +349,7 @@ Extra_MmFlex_t * Extra_MmFlexStart() p->pCurrent = NULL; p->pEnd = NULL; - p->nChunkSize = (1 << 10); + p->nChunkSize = (1 << 12); p->nChunksAlloc = 64; p->nChunks = 0; p->pChunks = ALLOC( char *, p->nChunksAlloc ); diff --git a/src/misc/extra/extraUtilUtil.c b/src/misc/extra/extraUtilUtil.c index abe08d7a..7165a0cd 100644 --- a/src/misc/extra/extraUtilUtil.c +++ b/src/misc/extra/extraUtilUtil.c @@ -377,6 +377,22 @@ double Extra_CpuTimeDouble() } #endif +/**Function************************************************************* + + Synopsis [Testing memory leaks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MemTest() +{ + malloc( 1002 ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/misc/util/leaks.h b/src/misc/util/leaks.h deleted file mode 100644 index 1a32062a..00000000 --- a/src/misc/util/leaks.h +++ /dev/null @@ -1,30 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -// This file is used to detect memory leaks using Visual Studio 6.0 -// 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__ - -#ifdef _DEBUG -#define _CRTDBG_MAP_ALLOC // include Microsoft memory leak detection procedures -//#define _INC_MALLOC // exclude standard memory alloc procedures - -#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) -//#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) -//#define free(p) _free_dbg(p, _NORMAL_BLOCK) -//#define _msize(p) _msize_dbg(p, _NORMAL_BLOCK) - -//#include -#include -#include -#endif - -#endif - -////////////////////////////////////// - - diff --git a/src/misc/util/stdlib_hack.h b/src/misc/util/stdlib_hack.h deleted file mode 100644 index 2ddf73d1..00000000 --- a/src/misc/util/stdlib_hack.h +++ /dev/null @@ -1,4 +0,0 @@ - -#include - - diff --git a/src/misc/vec/vec.h b/src/misc/vec/vec.h index 4c19b5ee..67ec44aa 100644 --- a/src/misc/vec/vec.h +++ b/src/misc/vec/vec.h @@ -48,10 +48,10 @@ typedef long long sint64; /// INCLUDES /// //////////////////////////////////////////////////////////////////////// -// this include should be the first one in the list -// it is used to catch memory leaks on Windows -#if defined(_DEBUG) && defined(_MSC_VER) && (_MSC_VER <= 1200) // 1200 = MSVC 6.0 -#include "leaks.h" +// catch memory leaks in Visual Studio +#ifdef _DEBUG +#define _CRTDBG_MAP_ALLOC +#include #endif //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h index dee05dfc..faa249f2 100644 --- a/src/opt/cut/cut.h +++ b/src/opt/cut/cut.h @@ -64,8 +64,10 @@ struct Cut_ParamsStruct_t_ int fGlobal; // compute only global cuts int fLocal; // compute only local cuts int fRecord; // record the cut computation flow + int fRecordAig; // record the cut functions int fFancy; // perform fancy computations int fMap; // computes delay of FPGA mapping with cuts + int fAdjust; // removed useless fanouts of XORs/MUXes int fVerbose; // the verbosiness flag }; diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c index 2d17020b..633219fd 100644 --- a/src/opt/cut/cutNode.c +++ b/src/opt/cut/cutNode.c @@ -393,6 +393,13 @@ p->timeMerge += clock() - clk; Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) ); Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) ); } + if ( p->pParams->fRecordAig ) + { + extern void Aig_RManRecord( unsigned * pTruth, int nVarsInit ); + Cut_ListForEachCut( pList, pCut ) + if ( Cut_CutReadLeaveNum(pCut) > 4 ) + Aig_RManRecord( Cut_CutReadTruth(pCut), Cut_CutReadLeaveNum(pCut) ); + } // check if the node is over the list if ( p->nNodeCuts == p->pParams->nKeepMax ) p->nCutsLimit++; diff --git a/src/opt/lpk/lpkAbcDsd.c b/src/opt/lpk/lpkAbcDsd.c index 46d9179a..a1cd9def 100644 --- a/src/opt/lpk/lpkAbcDsd.c +++ b/src/opt/lpk/lpkAbcDsd.c @@ -287,7 +287,12 @@ void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth, if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving continue; if ( fVerbose ) -Lpk_PrintSetOne( uBoundSet ); +{ +Lpk_PrintSetOne( uBoundSet & 0xFFFF ); +//printf( "\n" ); +//Lpk_PrintSetOne( uBoundSet >> 16 ); +//printf( "\n" ); +} assert( (uBoundSet & (uBoundSet >> 16)) == 0 ); nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF ); if ( nVarsBS == 1 ) diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c index 78356d81..d8dd15b7 100644 --- a/src/opt/lpk/lpkCore.c +++ b/src/opt/lpk/lpkCore.c @@ -387,6 +387,10 @@ p->timeCuts += clock() - clk; p->nCutsUseful += p->nEvals; for ( i = 0; i < p->nEvals; i++ ) { + if ( p->pObj->Id == 1478 ) + { + int x = 0; + } // get the cut pCut = p->pCuts + p->pEvals[i]; if ( p->pPars->fFirst && i == 1 ) diff --git a/src/opt/mfs/mfs.h b/src/opt/mfs/mfs.h index 9550a31b..bddb9328 100644 --- a/src/opt/mfs/mfs.h +++ b/src/opt/mfs/mfs.h @@ -54,6 +54,7 @@ struct Mfs_Par_t_ int fSwapEdge; // performs edge swapping int fOneHotness; // adds one-hotness conditions int fDelay; // performs optimization for delay + int fPower; // performs power-aware optimization int fVerbose; // enable basic stats int fVeryVerbose; // enable detailed stats }; diff --git a/src/opt/mfs/mfsCore.c b/src/opt/mfs/mfsCore.c index 3444bab1..e8820acd 100644 --- a/src/opt/mfs/mfsCore.c +++ b/src/opt/mfs/mfsCore.c @@ -9,7 +9,7 @@ Synopsis [Core procedures of this package.] Author [Alan Mishchenko] - + Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] @@ -24,6 +24,8 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +extern int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -33,7 +35,7 @@ Synopsis [] Description [] - + SideEffects [] SeeAlso [] @@ -57,13 +59,176 @@ void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars ) pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } +/* +int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pProbab[pFanin->Id] >= 0.4 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } else if ( pProbab[pFanin->Id] >= 0.3 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + return 1; + } + } + return 0; +} +*/ + +int Abc_WinNode(Mfs_Man_t * p, Abc_Obj_t *pNode) +{ +// int clk; +// Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; +// int i; + + p->nNodesTried++; + // prepare data structure for this node + Mfs_ManClean( p ); + // compute window roots, window support, and window nodes + p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); + p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); + p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); + if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax ) + return 1; + // compute the divisors of the window + p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 ); + p->nTotalDivs += Vec_PtrSize(p->vDivs); + // construct AIG for the window + p->pAigWin = Abc_NtkConstructAig( p, pNode ); + // translate it into CNF + p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); + // create the SAT problem + p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 ); + if ( p->pSat == NULL ) + { + p->nNodesBad++; + return 1; + } + return 0; +} + +/* +int Abc_NtkMfsPowerResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + int clk; + Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + + if (Abc_WinNode(p, pNode) // something wrong + return 1; + + // solve the SAT problem + // Abc_NtkMfsEdgePower( p, pNode ); + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.1 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + return 1; + + if ( Abc_ObjFaninNum(pNode) == p->nFaninMax ) + return 0; + + // try replacing area critical fanins while adding two new fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) + return 1; + } + return 0; + + return 1; +} +*/ + +Abc_NtkMfsPowerResub( Mfs_Man_t * p, Mfs_Par_t * pPars) +{ + int i, k; + Abc_Obj_t *pFanin, *pNode; + Abc_Ntk_t *pNtk = p->pNtk; + int nFaninMax = Abc_NtkGetFaninMax(p->pNtk); + float * pProbab = (float *)p->vProbs->pArray; + + Abc_NtkForEachNode( pNtk, pNode, k ) + { + if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) + continue; + if (Abc_WinNode(p, pNode) ) // something wrong + continue; + + // solve the SAT problem + // Abc_NtkMfsEdgePower( p, pNode ); + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + continue; + } + + Abc_NtkForEachNode( pNtk, pNode, k ) + { + if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) + continue; + if (Abc_WinNode(p, pNode) ) // something wrong + continue; + + // solve the SAT problem + // Abc_NtkMfsEdgePower( p, pNode ); + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + continue; + } + + Abc_NtkForEachNode( pNtk, pNode, k ) + { + if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) + continue; + if (Abc_WinNode(p, pNode) ) // something wrong + continue; + + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.2 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + continue; + } +/* + Abc_NtkForEachNode( pNtk, pNode, k ) + { + if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax - 2) + continue; + if (Abc_WinNode(p, pNode) ) // something wrong + continue; + + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) + continue; + } +*/ +} /**Function************************************************************* Synopsis [] Description [] - + SideEffects [] SeeAlso [] @@ -74,7 +239,7 @@ int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode ) int clk; p->nNodesTried++; // prepare data structure for this node - Mfs_ManClean( p ); + Mfs_ManClean( p ); // compute window roots, window support, and window nodes clk = clock(); p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); @@ -105,7 +270,9 @@ clk = clock(); return 1; } // solve the SAT problem - if ( p->pPars->fSwapEdge ) + if ( p->pPars->fPower ) + Abc_NtkMfsEdgePower( p, pNode ); + else if ( p->pPars->fSwapEdge ) Abc_NtkMfsEdgeSwapEval( p, pNode ); else { @@ -122,7 +289,7 @@ p->timeSat += clock() - clk; Synopsis [] Description [] - + SideEffects [] SeeAlso [] @@ -132,7 +299,8 @@ int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Hop_Obj_t * pObj; int RetValue; - extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare ); + float dProb; + extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); int nGain, clk; p->nNodesTried++; @@ -173,14 +341,15 @@ p->timeSat += clock() - clk; } // minimize the local function of the node using bi-decomposition assert( p->nFanins == Abc_ObjFaninNum(pNode) ); - pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare ); + dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; + pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb ); nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj); if ( nGain >= 0 ) { p->nNodesDec++; p->nNodesGained += nGain; p->nNodesGainedLevel += nGain; - pNode->pData = pObj; + pNode->pData = pObj; } return 1; } @@ -190,7 +359,7 @@ p->timeSat += clock() - clk; Synopsis [] Description [] - + SideEffects [] SeeAlso [] @@ -198,7 +367,7 @@ p->timeSat += clock() - clk; ***********************************************************************/ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) { - extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ); + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Bdc_Par_t Pars = {0}, * pDecPars = &Pars; ProgressBar * pProgress; @@ -242,16 +411,32 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) p = Mfs_ManAlloc( pPars ); p->pNtk = pNtk; p->nFaninMax = nFaninMax; + + // precomputer power-aware metrics + if ( pPars->fPower ) + { + extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ); + if ( pPars->fResub ) + p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); + else + p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 ); +#if 0 + printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#else + p->TotalSwitchingBeg = Abc_NtkMfsTotalSwitching(pNtk); +#endif + } + if ( pNtk->pExcare ) { Abc_Ntk_t * pTemp; if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) ) - printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", + printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) ); else { pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 ); - p->pCare = Abc_NtkToDar( pTemp, 0 ); + p->pCare = Abc_NtkToDar( pTemp, 0, 0 ); Abc_NtkDelete( pTemp ); p->vSuppsInv = Aig_ManSupportsInverse( p->pCare ); } @@ -273,7 +458,7 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pData = (void *)(PORT_PTRUINT_T)i; } - + // compute levels Abc_NtkLevel( pNtk ); Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); @@ -284,6 +469,14 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) p->nTotalEdgesBeg = nTotalEdgesBeg; if ( pPars->fResub ) { +#if 0 + printf( "TotalSwitching (%7.2f --> ", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif + if (pPars->fPower) + { + Abc_NtkMfsPowerResub( p, pPars); + } else + { pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) { @@ -299,9 +492,15 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) Abc_NtkMfsNode( p, pObj ); } Extra_ProgressBarStop( pProgress ); +#if 0 + printf( " %7.2f )\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif } - else + } else { +#if 0 + printf( "Total switching before = %7.2f, ----> ", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); vLevels = Abc_NtkLevelize( pNtk ); Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) @@ -320,22 +519,27 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) continue; if ( pPars->fResub ) Abc_NtkMfsResub( p, pObj ); - else + else Abc_NtkMfsNode( p, pObj ); } nNodes += Vec_PtrSize(vNodes); if ( pPars->fVerbose ) { - printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", + /* + printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", k, Vec_PtrSize(vNodes), 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes), 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes), 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) ); PRT( "Time", clock() - clk2 ); + */ } } Extra_ProgressBarStop( pProgress ); Vec_VecFree( vLevels ); +#if 0 + printf( " %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif } Abc_NtkStopReverseLevels( pNtk ); @@ -357,6 +561,16 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) pObj->pData = NULL; } + if ( pPars->fPower ) + { +#if 1 + p->TotalSwitchingEnd = Abc_NtkMfsTotalSwitching(pNtk); +// printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#else + printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); +#endif + } + // free the manager p->timeTotal = clock() - clk; Mfs_ManStop( p ); diff --git a/src/opt/mfs/mfsCore_.c b/src/opt/mfs/mfsCore_.c new file mode 100644 index 00000000..66b497f6 --- /dev/null +++ b/src/opt/mfs/mfsCore_.c @@ -0,0 +1,388 @@ +/**CFile**************************************************************** + + FileName [mfsCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The good old minimization with complete don't-cares.] + + Synopsis [Core procedures of this package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mfsCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mfsInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Mfs_Par_t) ); + pPars->nWinTfoLevs = 2; + pPars->nFanoutsMax = 10; + pPars->nDepthMax = 20; + pPars->nDivMax = 250; + pPars->nWinSizeMax = 300; + pPars->nGrowthLevel = 0; + pPars->nBTLimit = 5000; + pPars->fResub = 1; + pPars->fArea = 0; + pPars->fMoreEffort = 0; + pPars->fSwapEdge = 0; + pPars->fOneHotness = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + int clk; + p->nNodesTried++; + // prepare data structure for this node + Mfs_ManClean( p ); + // compute window roots, window support, and window nodes +clk = clock(); + p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); + p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); + p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); +p->timeWin += clock() - clk; + if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax ) + return 1; + // compute the divisors of the window +clk = clock(); + p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 ); + p->nTotalDivs += Vec_PtrSize(p->vDivs); +p->timeDiv += clock() - clk; + // construct AIG for the window +clk = clock(); + p->pAigWin = Abc_NtkConstructAig( p, pNode ); +p->timeAig += clock() - clk; + // translate it into CNF +clk = clock(); + p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); +p->timeCnf += clock() - clk; + // create the SAT problem +clk = clock(); + p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 ); + if ( p->pSat == NULL ) + { + p->nNodesBad++; + return 1; + } + // solve the SAT problem + if ( p->pPars->fPower ) + Abc_NtkMfsEdgePower( p, pNode ); + else if ( p->pPars->fSwapEdge ) + Abc_NtkMfsEdgeSwapEval( p, pNode ); + else + { + Abc_NtkMfsResubNode( p, pNode ); + if ( p->pPars->fMoreEffort ) + Abc_NtkMfsResubNode2( p, pNode ); + } +p->timeSat += clock() - clk; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Hop_Obj_t * pObj; + int RetValue; + float dProb; + extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); + + int nGain, clk; + p->nNodesTried++; + // prepare data structure for this node + Mfs_ManClean( p ); + // compute window roots, window support, and window nodes +clk = clock(); + p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); + p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); + p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); +p->timeWin += clock() - clk; + // count the number of patterns +// p->dTotalRatios += Abc_NtkConstraintRatio( p, pNode ); + // construct AIG for the window +clk = clock(); + p->pAigWin = Abc_NtkConstructAig( p, pNode ); +p->timeAig += clock() - clk; + // translate it into CNF +clk = clock(); + p->pCnf = Cnf_DeriveSimple( p->pAigWin, Abc_ObjFaninNum(pNode) ); +p->timeCnf += clock() - clk; + // create the SAT problem +clk = clock(); + p->pSat = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); + if ( p->pSat && p->pPars->fOneHotness ) + Abc_NtkAddOneHotness( p ); + if ( p->pSat == NULL ) + return 0; + // solve the SAT problem + RetValue = Abc_NtkMfsSolveSat( p, pNode ); + p->nTotConfLevel += p->pSat->stats.conflicts; +p->timeSat += clock() - clk; + if ( RetValue == 0 ) + { + p->nTimeOutsLevel++; + p->nTimeOuts++; + return 0; + } + // minimize the local function of the node using bi-decomposition + assert( p->nFanins == Abc_ObjFaninNum(pNode) ); + dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; + pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb ); + nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj); + if ( nGain >= 0 ) + { + p->nNodesDec++; + p->nNodesGained += nGain; + p->nNodesGainedLevel += nGain; + pNode->pData = pObj; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + + Bdc_Par_t Pars = {0}, * pDecPars = &Pars; + ProgressBar * pProgress; + Mfs_Man_t * p; + Abc_Obj_t * pObj; + Vec_Vec_t * vLevels; + Vec_Ptr_t * vNodes; + int i, k, nNodes, nFaninMax, clk = clock(), clk2; + int nTotalNodesBeg = Abc_NtkNodeNum(pNtk); + int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk); + + assert( Abc_NtkIsLogic(pNtk) ); + nFaninMax = Abc_NtkGetFaninMax(pNtk); + if ( pPars->fResub ) + { + if ( nFaninMax > 8 ) + { + printf( "Nodes with more than %d fanins will node be processed.\n", 8 ); + nFaninMax = 8; + } + } + else + { + if ( nFaninMax > MFS_FANIN_MAX ) + { + printf( "Nodes with more than %d fanins will node be processed.\n", MFS_FANIN_MAX ); + nFaninMax = MFS_FANIN_MAX; + } + } + // perform the network sweep + Abc_NtkSweep( pNtk, 0 ); + // convert into the AIG + if ( !Abc_NtkToAig(pNtk) ) + { + fprintf( stdout, "Converting to AIGs has failed.\n" ); + return 0; + } + assert( Abc_NtkHasAig(pNtk) ); + + // start the manager + p = Mfs_ManAlloc( pPars ); + p->pNtk = pNtk; + p->nFaninMax = nFaninMax; + + // precomputer power-aware metrics + if ( pPars->fPower ) + { + extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ); + if ( pPars->fResub ) + p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); + else + p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 ); + printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); + } + + if ( pNtk->pExcare ) + { + Abc_Ntk_t * pTemp; + if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) ) + printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", + Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) ); + else + { + pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 ); + p->pCare = Abc_NtkToDar( pTemp, 0, 0 ); + Abc_NtkDelete( pTemp ); + p->vSuppsInv = Aig_ManSupportsInverse( p->pCare ); + } + } + if ( p->pCare != NULL ) + printf( "Performing optimization with %d external care clauses.\n", Aig_ManPoNum(p->pCare) ); + // prepare the BDC manager + if ( !pPars->fResub ) + { + pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax; + pDecPars->fVerbose = pPars->fVerbose; + p->vTruth = Vec_IntAlloc( 0 ); + p->pManDec = Bdc_ManAlloc( pDecPars ); + } + + // label the register outputs + if ( p->pCare ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pData = (void *)(PORT_PTRUINT_T)i; + } + + // compute levels + Abc_NtkLevel( pNtk ); + Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); + + // compute don't-cares for each node + nNodes = 0; + p->nTotalNodesBeg = nTotalNodesBeg; + p->nTotalEdgesBeg = nTotalEdgesBeg; + if ( pPars->fResub ) + { + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) + continue; + if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) + continue; + if ( !p->pPars->fVeryVerbose ) + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( pPars->fResub ) + Abc_NtkMfsResub( p, pObj ); + else + Abc_NtkMfsNode( p, pObj ); + } + Extra_ProgressBarStop( pProgress ); + } + else + { + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); + vLevels = Abc_NtkLevelize( pNtk ); + Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) + { + if ( !p->pPars->fVeryVerbose ) + Extra_ProgressBarUpdate( pProgress, nNodes, NULL ); + p->nNodesGainedLevel = 0; + p->nTotConfLevel = 0; + p->nTimeOutsLevel = 0; + clk2 = clock(); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) + break; + if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) + continue; + if ( pPars->fResub ) + Abc_NtkMfsResub( p, pObj ); + else + Abc_NtkMfsNode( p, pObj ); + } + nNodes += Vec_PtrSize(vNodes); + if ( pPars->fVerbose ) + { + printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", + k, Vec_PtrSize(vNodes), + 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes), + 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes), + 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) ); + PRT( "Time", clock() - clk2 ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_VecFree( vLevels ); + } + Abc_NtkStopReverseLevels( pNtk ); + + // perform the sweeping + if ( !pPars->fResub ) + { + extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); +// Abc_NtkSweep( pNtk, 0 ); +// Abc_NtkBidecResyn( pNtk, 0 ); + } + + p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk); + p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk); + + // undo labesl + if ( p->pCare ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pData = NULL; + } + if ( pPars->fPower ) + printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); + + // free the manager + p->timeTotal = clock() - clk; + Mfs_ManStop( p ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/opt/mfs/mfsInt.h b/src/opt/mfs/mfsInt.h index df8a4848..9eb6e4a4 100644 --- a/src/opt/mfs/mfsInt.h +++ b/src/opt/mfs/mfsInt.h @@ -81,6 +81,8 @@ struct Mfs_Man_t_ Vec_Ptr_t * vFanins; // the new set of fanins int nTotConfLim; // total conflict limit int nTotConfLevel; // total conflicts on this level + // switching activity + Vec_Int_t * vProbs; // the result of solving int nFanins; // the number of fanins int nWords; // the number of words @@ -102,6 +104,8 @@ struct Mfs_Man_t_ int nTotalNodesEnd; int nTotalEdgesBeg; int nTotalEdgesEnd; + float TotalSwitchingBeg; + float TotalSwitchingEnd; // statistics int timeWin; int timeDiv; @@ -137,6 +141,7 @@ extern void Mfs_ManClean( Mfs_Man_t * p ); /*=== mfsResub.c ==========================================================*/ extern void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ); extern int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ); +extern int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode ); /*=== mfsSat.c ==========================================================*/ diff --git a/src/opt/mfs/mfsMan.c b/src/opt/mfs/mfsMan.c index d0642368..9a043ed8 100644 --- a/src/opt/mfs/mfsMan.c +++ b/src/opt/mfs/mfsMan.c @@ -108,6 +108,7 @@ void Mfs_ManPrint( Mfs_Man_t * p ) { if ( p->pPars->fResub ) { +/* printf( "Reduction in nodes = %5d. (%.2f %%) ", p->nTotalNodesBeg-p->nTotalNodesEnd, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg ); @@ -122,6 +123,28 @@ void Mfs_ManPrint( Mfs_Man_t * p ) p->nNodesResub, Abc_NtkGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Abc_NtkGetTotalFanins(p->pNtk) ); else Abc_NtkMfsPrintResubStats( p ); +// printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) ); +*/ + printf( "@@@------- Node( %4d, %4.2f%% ), ", + p->nTotalNodesBeg-p->nTotalNodesEnd, + 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg ); + printf( "Edge( %4d, %4.2f%% ), ", + p->nTotalEdgesBeg-p->nTotalEdgesEnd, + 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/p->nTotalEdgesBeg ); + if (p->pPars->fPower) + printf( "Power( %5.2f, %4.2f%%) ", + p->TotalSwitchingBeg - p->TotalSwitchingEnd, + 100.0*(p->TotalSwitchingBeg-p->TotalSwitchingEnd)/p->TotalSwitchingBeg ); + printf( "\n" ); +#if 0 + printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d.\n", + Abc_NtkNodeNum(p->pNtk), p->nNodesTried, p->nNodesResub, p->nTotalDivs, p->nSatCalls, p->nTimeOuts ); +#endif + if ( p->pPars->fSwapEdge ) + printf( "Swappable edges = %d. Total edges = %d. Ratio = %5.2f.\n", + p->nNodesResub, Abc_NtkGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Abc_NtkGetTotalFanins(p->pNtk) ); + else + Abc_NtkMfsPrintResubStats( p ); // printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) ); } else @@ -168,6 +191,8 @@ void Mfs_ManStop( Mfs_Man_t * p ) Aig_ManStop( p->pCare ); if ( p->vSuppsInv ) Vec_VecFree( (Vec_Vec_t *)p->vSuppsInv ); + if ( p->vProbs ) + Vec_IntFree( p->vProbs ); Mfs_ManClean( p ); Int_ManFree( p->pMan ); Vec_IntFree( p->vMem ); diff --git a/src/opt/mfs/mfsResub.c b/src/opt/mfs/mfsResub.c index b6c7299b..e9ea2c40 100644 --- a/src/opt/mfs/mfsResub.c +++ b/src/opt/mfs/mfsResub.c @@ -80,8 +80,8 @@ void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ) nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax); } } - printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", - nAreaCrits, nAreaExpanse ); +// printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", +// nAreaCrits, nAreaExpanse ); } /**Function************************************************************* @@ -209,6 +209,8 @@ p->timeInt += clock() - clk; iVar = -1; while ( 1 ) { + float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); + assert( (pProbab != NULL) == p->pPars->fPower ); if ( fVeryVerbose ) { printf( "%3d: %2d ", p->nCexes, iVar ); @@ -225,6 +227,13 @@ p->timeInt += clock() - clk; assert( nWords <= p->nDivWords ); for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { + if ( p->pPars->fPower ) + { + Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); + // only accept the divisor if it is "cool" + if ( pProbab[Abc_ObjId(pDiv)] >= 0.15 ) + continue; + } pData = Vec_PtrEntry( p->vDivCexes, iVar ); for ( w = 0; w < nWords; w++ ) if ( pData[w] != ~0 ) @@ -345,6 +354,10 @@ p->timeInt += clock() - clk; iVar = iVar2 = -1; while ( 1 ) { +#if 1 // sjang + float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); + assert( (pProbab != NULL) == p->pPars->fPower ); +#endif if ( fVeryVerbose ) { printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 ); @@ -363,9 +376,27 @@ p->timeInt += clock() - clk; for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { pData = Vec_PtrEntry( p->vDivCexes, iVar ); +#if 1 // sjang + if ( p->pPars->fPower ) + { + Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); + // only accept the divisor if it is "cool" + if ( pProbab[Abc_ObjId(pDiv)] >= 0.12 ) + continue; + } +#endif for ( iVar2 = 0; iVar2 < iVar; iVar2++ ) { pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 ); +#if 1 // sjang + if ( p->pPars->fPower ) + { + Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar2); + // only accept the divisor if it is "cool" + if ( pProbab[Abc_ObjId(pDiv)] >= 0.12 ) + continue; + } +#endif for ( w = 0; w < nWords; w++ ) if ( (pData[w] | pData2[w]) != ~0 ) break; @@ -432,6 +463,38 @@ int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ) return 0; } +/**Function************************************************************* + + Synopsis [Evaluates the possibility of replacing given edge by another edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pProbab[pFanin->Id] >= 0.35 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } else if ( pProbab[pFanin->Id] >= 0.25 ) // sjang + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + return 1; + } + } + return 0; +} + /**Function************************************************************* Synopsis [Performs resubstitution for the node.] diff --git a/src/opt/mfs/mfsResub_.c b/src/opt/mfs/mfsResub_.c new file mode 100644 index 00000000..47600b30 --- /dev/null +++ b/src/opt/mfs/mfsResub_.c @@ -0,0 +1,560 @@ +/**CFile**************************************************************** + + FileName [mfsResub.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The good old minimization with complete don't-cares.] + + Synopsis [Procedures to perform resubstitution.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mfsResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mfsInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Updates the network after resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMfsUpdateNetwork( Mfs_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc ) +{ + Abc_Obj_t * pObjNew, * pFanin; + int k; + // create the new node + pObjNew = Abc_NtkCreateNode( pObj->pNtk ); + pObjNew->pData = pFunc; + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Abc_ObjAddFanin( pObjNew, pFanin ); + // replace the old node by the new node +//printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj ); +//printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew ); + // update the level of the node + Abc_NtkUpdate( pObj, pObjNew, p->vLevels ); +} + +/**Function************************************************************* + + Synopsis [Prints resub candidate stats.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ) +{ + Abc_Obj_t * pFanin, * pNode; + int i, k, nAreaCrits = 0, nAreaExpanse = 0; + int nFaninMax = Abc_NtkGetFaninMax(p->pNtk); + Abc_NtkForEachNode( p->pNtk, pNode, i ) + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + nAreaCrits++; + nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax); + } + } + printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", + nAreaCrits, nAreaExpanse ); +} + +/**Function************************************************************* + + Synopsis [Tries resubstitution.] + + Description [Returns 1 if it is feasible, or 0 if c-ex is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsTryResubOnce( Mfs_Man_t * p, int * pCands, int nCands ) +{ + unsigned * pData; + int RetValue, iVar, i; + p->nSatCalls++; + RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (sint64)p->pPars->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); +// assert( RetValue == l_False || RetValue == l_True ); + if ( RetValue == l_False ) + return 1; + if ( RetValue != l_True ) + { + p->nTimeOuts++; + return -1; + } + p->nSatCexes++; + // store the counter-example + Vec_IntForEachEntry( p->vProjVars, iVar, i ) + { + pData = Vec_PtrEntry( p->vDivCexes, i ); + if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!! + { + assert( Aig_InfoHasBit(pData, p->nCexes) ); + Aig_InfoXorBit( pData, p->nCexes ); + } + } + p->nCexes++; + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ) +{ + int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; + unsigned * pData; + int pCands[MFS_FANIN_MAX]; + int RetValue, iVar, i, nCands, nWords, w, clk; + Abc_Obj_t * pFanin; + Hop_Obj_t * pFunc; + assert( iFanin >= 0 ); + + // clean simulation info + Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); + p->nCexes = 0; + if ( fVeryVerbose ) + { + printf( "\n" ); + printf( "Node %5d : Level = %2d. Divs = %3d. Fanin = %d (out of %d). MFFC = %d\n", + pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), + iFanin, Abc_ObjFaninNum(pNode), + Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); + } + + // try fanins without the critical fanin + nCands = 0; + Vec_PtrClear( p->vFanins ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( i == iFanin ) + continue; + Vec_PtrPush( p->vFanins, pFanin ); + iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; + pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 ); + } + RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); + if ( RetValue == -1 ) + return 0; + if ( RetValue == 1 ) + { + if ( fVeryVerbose ) + printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin ); + p->nNodesResub++; + p->nNodesGainedLevel++; + if ( fSkipUpdate ) + return 1; +clk = clock(); + // derive the function + pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); + if ( pFunc == NULL ) + return 0; + // update the network + Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); +p->timeInt += clock() - clk; + return 1; + } + + if ( fOnlyRemove ) + return 0; + + if ( fVeryVerbose ) + { + for ( i = 0; i < 8; i++ ) + printf( " " ); + for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) + printf( "%d", i % 10 ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + if ( i == iFanin ) + printf( "*" ); + else + printf( "%c", 'a' + i ); + printf( "\n" ); + } + iVar = -1; + while ( 1 ) + { + float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); + assert( (pProbab != NULL) == p->pPars->fPower ); + if ( fVeryVerbose ) + { + printf( "%3d: %2d ", p->nCexes, iVar ); + for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) + { + pData = Vec_PtrEntry( p->vDivCexes, i ); + printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); + } + printf( "\n" ); + } + + // find the next divisor to try + nWords = Aig_BitWordNum(p->nCexes); + assert( nWords <= p->nDivWords ); + for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) + { + if ( p->pPars->fPower ) + { + Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); + // only accept the divisor if it is "cool" + if ( pProbab[Abc_ObjId(pDiv)] >= 0.2 ) + continue; + } + pData = Vec_PtrEntry( p->vDivCexes, iVar ); + for ( w = 0; w < nWords; w++ ) + if ( pData[w] != ~0 ) + break; + if ( w == nWords ) + break; + } + if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) + return 0; + + pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 ); + RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+1 ); + if ( RetValue == -1 ) + return 0; + if ( RetValue == 1 ) + { + if ( fVeryVerbose ) + printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar ); + p->nNodesResub++; + p->nNodesGainedLevel++; + if ( fSkipUpdate ) + return 1; +clk = clock(); + // derive the function + pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+1 ); + if ( pFunc == NULL ) + return 0; + // update the network + Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); + Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); +p->timeInt += clock() - clk; + return 1; + } + if ( p->nCexes >= p->pPars->nDivMax ) + break; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsSolveSatResub2( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int iFanin2 ) +{ + int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; + unsigned * pData, * pData2; + int pCands[MFS_FANIN_MAX]; + int RetValue, iVar, iVar2, i, w, nCands, clk, nWords, fBreak; + Abc_Obj_t * pFanin; + Hop_Obj_t * pFunc; + assert( iFanin >= 0 ); + assert( iFanin2 >= 0 || iFanin2 == -1 ); + + // clean simulation info + Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); + p->nCexes = 0; + if ( fVeryVerbose ) + { + printf( "\n" ); + printf( "Node %5d : Level = %2d. Divs = %3d. Fanins = %d/%d (out of %d). MFFC = %d\n", + pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), + iFanin, iFanin2, Abc_ObjFaninNum(pNode), + Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); + } + + // try fanins without the critical fanin + nCands = 0; + Vec_PtrClear( p->vFanins ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( i == iFanin || i == iFanin2 ) + continue; + Vec_PtrPush( p->vFanins, pFanin ); + iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; + pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 ); + } + RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); + if ( RetValue == -1 ) + return 0; + if ( RetValue == 1 ) + { + if ( fVeryVerbose ) + printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 ); + p->nNodesResub++; + p->nNodesGainedLevel++; +clk = clock(); + // derive the function + pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); + if ( pFunc == NULL ) + return 0; + // update the network + Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); +p->timeInt += clock() - clk; + return 1; + } + + if ( fVeryVerbose ) + { + for ( i = 0; i < 11; i++ ) + printf( " " ); + for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) + printf( "%d", i % 10 ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + if ( i == iFanin || i == iFanin2 ) + printf( "*" ); + else + printf( "%c", 'a' + i ); + printf( "\n" ); + } + iVar = iVar2 = -1; + while ( 1 ) + { + if ( fVeryVerbose ) + { + printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 ); + for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) + { + pData = Vec_PtrEntry( p->vDivCexes, i ); + printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); + } + printf( "\n" ); + } + + // find the next divisor to try + nWords = Aig_BitWordNum(p->nCexes); + assert( nWords <= p->nDivWords ); + fBreak = 0; + for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) + { + pData = Vec_PtrEntry( p->vDivCexes, iVar ); + for ( iVar2 = 0; iVar2 < iVar; iVar2++ ) + { + pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 ); + for ( w = 0; w < nWords; w++ ) + if ( (pData[w] | pData2[w]) != ~0 ) + break; + if ( w == nWords ) + { + fBreak = 1; + break; + } + } + if ( fBreak ) + break; + } + if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) + return 0; + + pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar2), 1 ); + pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 ); + RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+2 ); + if ( RetValue == -1 ) + return 0; + if ( RetValue == 1 ) + { + if ( fVeryVerbose ) + printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 ); + p->nNodesResub++; + p->nNodesGainedLevel++; +clk = clock(); + // derive the function + pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+2 ); + if ( pFunc == NULL ) + return 0; + // update the network + Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar2) ); + Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); + assert( Vec_PtrSize(p->vFanins) == nCands + 2 ); + Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); +p->timeInt += clock() - clk; + return 1; + } + if ( p->nCexes >= p->pPars->nDivMax ) + break; + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Evaluates the possibility of replacing given edge by another edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i; + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 1 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Evaluates the possibility of replacing given edge by another edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + float * pProbab = (float *)p->vProbs->pArray; + int i; + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pProbab[pFanin->Id] >= 0.4 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i; + // try replacing area critical fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } + // try removing redundant edges + if ( !p->pPars->fArea ) + { + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( Abc_ObjIsCi(pFanin) || Abc_ObjFanoutNum(pFanin) != 1 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) + return 1; + } + } + if ( Abc_ObjFaninNum(pNode) == p->nFaninMax ) + return 0; + // try replacing area critical fanins while adding two new fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs resubstitution for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin, * pFanin2; + int i, k; +/* + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) + return 1; + } +*/ + if ( Abc_ObjFaninNum(pNode) < 2 ) + return 0; + // try replacing one area critical fanin and one other fanin while adding two new fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + { + // consider second fanin to remove at the same time + Abc_ObjForEachFanin( pNode, pFanin2, k ) + { + if ( i != k && Abc_NtkMfsSolveSatResub2( p, pNode, i, k ) ) + return 1; + } + } + } + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/opt/sim/simSwitch.c b/src/opt/sim/simSwitch.c index 218d4d59..baabc320 100644 --- a/src/opt/sim/simSwitch.c +++ b/src/opt/sim/simSwitch.c @@ -97,7 +97,7 @@ float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ) int nOnes, nTotal; nTotal = 32 * nSimWords; nOnes = Sim_UtilCountOnes( pSimInfo, nSimWords ); - return (float)2.0 * nOnes * (nTotal - nOnes) / nTotal / nTotal; + return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; } //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/bsat/satInterP.c b/src/sat/bsat/satInterP.c index 686774fa..c944c36d 100644 --- a/src/sat/bsat/satInterP.c +++ b/src/sat/bsat/satInterP.c @@ -601,6 +601,27 @@ int Intp_ManProofTraceOne( Intp_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pF Intp_ManPrintResolvent( p->pResLits, p->nResLits ); Intp_ManPrintClause( p, pFinal ); } + + // if there are literals in the clause that are not in the resolvent + // it means that the derived resolvent is stronger than the clause + // we can replace the clause with the resolvent by removing these literals + if ( p->nResLits != (int)pFinal->nLits ) + { + for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ ) + { + for ( v2 = 0; v2 < p->nResLits; v2++ ) + if ( pFinal->pLits[v1] == p->pResLits[v2] ) + break; + if ( v2 < p->nResLits ) + continue; + // remove literal v1 from the final clause + pFinal->nLits--; + for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ ) + pFinal->pLits[v2] = pFinal->pLits[v2+1]; + v1--; + } + assert( p->nResLits == (int)pFinal->nLits ); + } } p->timeTrace += clock() - clk; @@ -610,6 +631,10 @@ p->timeTrace += clock() - clk; // Intp_ManPrintInterOne( p, pFinal ); // } Intp_ManProofSet( p, pFinal, p->Counter ); + // make sure the same proof ID is not asssigned to two consecutive clauses + assert( p->pProofNums[pFinal->Id-1] != p->Counter ); +// if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] ) +// p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id]; return p->Counter; } @@ -634,9 +659,19 @@ int Intp_ManProofRecordOne( Intp_Man_t * p, Sto_Cls_t * pClause ) if ( pClause->nLits == 0 ) printf( "Error: Empty clause is attempted.\n" ); - // add assumptions to the trail assert( !pClause->fRoot ); assert( p->nTrailSize == p->nRootSize ); + + // if any of the clause literals are already assumed + // it means that the clause is redundant and can be skipped + for ( i = 0; i < (int)pClause->nLits; i++ ) + if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] ) + { + Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) ); + return 1; + } + + // add assumptions to the trail for ( i = 0; i < (int)pClause->nLits; i++ ) if ( !Intp_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) { @@ -652,6 +687,28 @@ int Intp_ManProofRecordOne( Intp_Man_t * p, Sto_Cls_t * pClause ) return 0; } + // skip the clause if it is weaker or the same as the conflict clause + if ( pClause->nLits >= pConflict->nLits ) + { + // check if every literal of conflict clause can be found in the given clause + int j; + for ( i = 0; i < (int)pConflict->nLits; i++ ) + { + for ( j = 0; j < (int)pClause->nLits; j++ ) + if ( pConflict->pLits[i] == pClause->pLits[j] ) + break; + if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found + break; + } + if ( i == (int)pConflict->nLits ) // all lits are found + { + // undo to the root level + Intp_ManCancelUntil( p, p->nRootSize ); + Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) ); + return 1; + } + } + // construct the proof Intp_ManProofTraceOne( p, pConflict, pClause ); @@ -737,8 +794,12 @@ int Intp_ManProcessRoots( Intp_Man_t * p ) if ( !Intp_ManEnqueue( p, pClause->pLits[0], pClause ) ) { // detected root level conflict - printf( "Error in Intp_ManProcessRoots(): Detected a root-level conflict too early!\n" ); - assert( 0 ); +// printf( "Error in Intp_ManProcessRoots(): Detected a root-level conflict too early!\n" ); +// assert( 0 ); + // detected root level conflict + Intp_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); + if ( p->fVerbose ) + printf( "Found root level conflict!\n" ); return 0; } } @@ -760,6 +821,68 @@ int Intp_ManProcessRoots( Intp_Man_t * p ) } +/**Function************************************************************* + + Synopsis [Verifies the UNSAT core.] + + Description [Takes the interpolation manager, the CNF derived by the SAT + solver, which includes the root clauses and the learned clauses. Returns + the array of integers representing the number of root clauses that are in + the UNSAT core.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Intp_ManUnsatCoreVerify( Sto_Man_t * pCnf, Vec_Int_t * vCore ) +{ + int fVerbose = 0; + int nConfMax = 1000000; + sat_solver * pSat; + Sto_Cls_t * pClause; + Vec_Ptr_t * vClauses; + int i, iClause, RetValue, clk = clock(); + // collect the clauses + vClauses = Vec_PtrAlloc( 1000 ); + Sto_ManForEachClauseRoot( pCnf, pClause ) + { + assert( Vec_PtrSize(vClauses) == pClause->Id ); + Vec_PtrPush( vClauses, pClause ); + } + // create new SAT solver + pSat = sat_solver_new(); +// sat_solver_setnvars( pSat, nSatVars ); + Vec_IntForEachEntry( vCore, iClause, i ) + { + pClause = Vec_PtrEntry( vClauses, iClause ); + if ( !sat_solver_addclause( pSat, pClause->pLits, pClause->pLits+pClause->nLits ) ) + { + printf( "The core verification problem is trivially UNSAT.\n" ); + break; + } + } + Vec_PtrFree( vClauses ); + // solve the problem + RetValue = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfMax, (sint64)0, (sint64)0, (sint64)0 ); + sat_solver_delete( pSat ); + if ( fVerbose ) + { + if ( RetValue == l_Undef ) + printf( "Conflict limit is reached. " ); + else if ( RetValue == l_True ) + printf( "UNSAT core verification FAILED. " ); + else + printf( "UNSAT core verification succeeded. " ); + PRT( "Time", clock() - clk ); + } + else + { + if ( RetValue == l_True ) + printf( "UNSAT core verification FAILED. \n" ); + } +} + /**Function************************************************************* Synopsis [Recursively computes the UNSAT core.] @@ -771,15 +894,13 @@ int Intp_ManProcessRoots( Intp_Man_t * p ) SeeAlso [] ***********************************************************************/ -void Intp_ManUnsatCore_rec( Vec_Int_t * vAnties, Vec_Int_t * vBreaks, int iThis, Vec_Int_t * vCore, int nRoots ) +void Intp_ManUnsatCore_rec( Vec_Int_t * vAnties, Vec_Int_t * vBreaks, int iThis, Vec_Int_t * vCore, int nRoots, Vec_Int_t * vVisited ) { int i, iStop, iStart; - // skip of this clause was visited - iStart = Vec_IntEntry( vBreaks, iThis ); - if ( iStart == -1 ) + // skip visited clauses + if ( Vec_IntEntry( vVisited, iThis ) ) return; - // mark this clause as visited - Vec_IntWriteEntry( vBreaks, iThis, -1 ); + Vec_IntWriteEntry( vVisited, iThis, 1 ); // add a root clause to the core if ( iThis < nRoots ) { @@ -787,9 +908,11 @@ void Intp_ManUnsatCore_rec( Vec_Int_t * vAnties, Vec_Int_t * vBreaks, int iThis, return; } // iterate through the clauses + iStart = Vec_IntEntry( vBreaks, iThis ); iStop = Vec_IntEntry( vBreaks, iThis+1 ); + assert( iStop != -1 ); for ( i = iStart; i < iStop; i++ ) - Intp_ManUnsatCore_rec( vAnties, vBreaks, Vec_IntEntry(vAnties, i), vCore, nRoots ); + Intp_ManUnsatCore_rec( vAnties, vBreaks, Vec_IntEntry(vAnties, i), vCore, nRoots, vVisited ); } /**Function************************************************************* @@ -809,6 +932,7 @@ void Intp_ManUnsatCore_rec( Vec_Int_t * vAnties, Vec_Int_t * vBreaks, int iThis, void * Intp_ManUnsatCore( Intp_Man_t * p, Sto_Man_t * pCnf, int fVerbose ) { Vec_Int_t * vCore; + Vec_Int_t * vVisited; Sto_Cls_t * pClause; int RetValue = 1; int clkTotal = clock(); @@ -859,6 +983,7 @@ void * Intp_ManUnsatCore( Intp_Man_t * p, Sto_Man_t * pCnf, int fVerbose ) if ( p->fProofWrite ) { fclose( p->pFile ); +// Sat_ProofChecker( "proof.cnf_" ); p->pFile = NULL; } @@ -874,10 +999,13 @@ p->timeTotal += clock() - clkTotal; // derive the UNSAT core vCore = Vec_IntAlloc( 1000 ); - Intp_ManUnsatCore_rec( p->vAnties, p->vBreaks, p->pCnf->pEmpty->Id, vCore, p->pCnf->nRoots ); + vVisited = Vec_IntStart( p->pCnf->pEmpty->Id+1 ); + Intp_ManUnsatCore_rec( p->vAnties, p->vBreaks, p->pCnf->pEmpty->Id, vCore, p->pCnf->nRoots, vVisited ); + Vec_IntFree( vVisited ); if ( fVerbose ) printf( "Root clauses = %d. Learned clauses = %d. UNSAT core size = %d.\n", p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, Vec_IntSize(vCore) ); + Intp_ManUnsatCoreVerify( p->pCnf, vCore ); return vCore; } diff --git a/src/sat/bsat/satStore.h b/src/sat/bsat/satStore.h index ef98ab93..f63703d3 100644 --- a/src/sat/bsat/satStore.h +++ b/src/sat/bsat/satStore.h @@ -74,7 +74,7 @@ struct Sto_Cls_t_ { Sto_Cls_t * pNext; // the next clause Sto_Cls_t * pNext0; // the next 0-watch - Sto_Cls_t * pNext1; // the next 0-watch + Sto_Cls_t * pNext1; // the next 1-watch int Id; // the clause ID unsigned fA : 1; // belongs to A unsigned fRoot : 1; // original clause diff --git a/todo.txt b/todo.txt index a7bb2727..29ce10dd 100644 --- a/todo.txt +++ b/todo.txt @@ -11,5 +11,10 @@ - area flow based AIG rewriting - cut frontier adjustment +- box-aware dch, lcorr, and scorr with optional deboxing +- mfs with boxes +- power-aware mapping +- full support of required times + -- cgit v1.2.3