From 6ad22b4d3b0446652919d95b15fefb374bddfac0 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 22 Nov 2006 08:01:00 -0800 Subject: Version abc61122 --- Makefile | 8 +- abc.dsp | 506 ++++---- abc.rc | 3 + src/aig/aig-alan.tar.gz | Bin 0 -> 27265 bytes src/aig/deco/deco.h | 703 +++++++++++ src/aig/deco/module.make | 1 + src/aig/ec/module.make | 1 + src/aig/hop/cudd2.c | 355 ++++++ src/aig/hop/cudd2.h | 82 ++ src/aig/hop/hop.h | 321 +++++ src/aig/hop/hopBalance.c | 391 ++++++ src/aig/hop/hopCheck.c | 110 ++ src/aig/hop/hopDfs.c | 399 ++++++ src/aig/hop/hopMan.c | 162 +++ src/aig/hop/hopMem.c | 115 ++ src/aig/hop/hopObj.c | 228 ++++ src/aig/hop/hopOper.c | 373 ++++++ src/aig/hop/hopTable.c | 266 ++++ src/aig/hop/hopUtil.c | 502 ++++++++ src/aig/hop/hop_.c | 48 + src/aig/hop/module.make | 9 + src/aig/ivy/attr.h | 414 ++++++ src/aig/ivy/ivy.h | 555 +++++++++ src/aig/ivy/ivyBalance.c | 404 ++++++ src/aig/ivy/ivyCanon.c | 144 +++ src/aig/ivy/ivyCheck.c | 273 ++++ src/aig/ivy/ivyCut.c | 987 +++++++++++++++ src/aig/ivy/ivyCutTrav.c | 473 +++++++ src/aig/ivy/ivyDfs.c | 493 ++++++++ src/aig/ivy/ivyDsd.c | 819 ++++++++++++ src/aig/ivy/ivyFanout.c | 309 +++++ src/aig/ivy/ivyFastMap.c | 1593 +++++++++++++++++++++++ src/aig/ivy/ivyFpga.c | 378 ++++++ src/aig/ivy/ivyFraig.c | 2704 ++++++++++++++++++++++++++++++++++++++++ src/aig/ivy/ivyHaig.c | 530 ++++++++ src/aig/ivy/ivyIsop.c | 328 +++++ src/aig/ivy/ivyMan.c | 546 ++++++++ src/aig/ivy/ivyMem.c | 115 ++ src/aig/ivy/ivyMulti.c | 301 +++++ src/aig/ivy/ivyMulti8.c | 427 +++++++ src/aig/ivy/ivyObj.c | 476 +++++++ src/aig/ivy/ivyOper.c | 293 +++++ src/aig/ivy/ivyResyn.c | 196 +++ src/aig/ivy/ivyRwr.c | 609 +++++++++ src/aig/ivy/ivyRwrAlg.c | 408 ++++++ src/aig/ivy/ivySeq.c | 1130 +++++++++++++++++ src/aig/ivy/ivyShow.c | 338 +++++ src/aig/ivy/ivyTable.c | 301 +++++ src/aig/ivy/ivyUtil.c | 738 +++++++++++ src/aig/ivy/ivy_.c | 48 + src/aig/ivy/module.make | 23 + src/aig/mem/mem.c | 588 +++++++++ src/aig/mem/mem.h | 71 ++ src/aig/mem/module.make | 1 + src/aig/rwt/module.make | 3 + src/aig/rwt/rwt.h | 155 +++ src/aig/rwt/rwtDec.c | 150 +++ src/aig/rwt/rwtMan.c | 358 ++++++ src/aig/rwt/rwtUtil.c | 665 ++++++++++ src/base/abc/abc.h | 37 +- src/base/abc/abcAig.c | 2 +- src/base/abc/abcCheck.c | 23 +- src/base/abc/abcDfs.c | 215 +++- src/base/abc/abcFanio.c | 4 + src/base/abc/abcFunc.c | 82 +- src/base/abc/abcLatch.c | 4 +- src/base/abc/abcLib.c | 4 +- src/base/abc/abcNetlist.c | 22 +- src/base/abc/abcNtk.c | 50 +- src/base/abc/abcObj.c | 30 +- src/base/abc/abcShow.c | 126 +- src/base/abc/abcSop.c | 5 +- src/base/abc/abcUtil.c | 29 +- src/base/abci/abc.c | 556 +++------ src/base/abci/abcAuto.c | 22 +- src/base/abci/abcClpBdd.c | 30 +- src/base/abci/abcCut.c | 3 + src/base/abci/abcDebug.c | 20 +- src/base/abci/abcDsd.c | 41 +- src/base/abci/abcFpgaFast.c | 6 +- src/base/abci/abcIf.c | 287 +++++ src/base/abci/abcIvy.c | 21 +- src/base/abci/abcLut.c | 2 +- src/base/abci/abcMini.c | 54 +- src/base/abci/abcNtbdd.c | 137 +- src/base/abci/abcPrint.c | 80 +- src/base/abci/abcProve.c | 2 +- src/base/abci/abcRefactor.c | 2 +- src/base/abci/abcRestruct.c | 2 +- src/base/abci/abcResub.c | 2 +- src/base/abci/abcRewrite.c | 2 +- src/base/abci/abcRr.c | 6 +- src/base/abci/abcSat.c | 2 +- src/base/abci/abcStrash.c | 55 +- src/base/abci/abcSweep.c | 38 +- src/base/abci/abcSymm.c | 12 +- src/base/abci/abcTiming.c | 4 +- src/base/abci/abcUnate.c | 23 +- src/base/abci/abcUnreach.c | 10 +- src/base/abci/module.make | 2 +- src/base/io/io.c | 14 +- src/base/io/io.h | 4 +- src/base/io/ioUtil.c | 2 +- src/base/io/ioWriteDot.c | 260 ++-- src/base/io/ioWritePla.c | 2 +- src/base/io/ioWriteVer.c | 8 +- src/base/main/libSupport.c | 4 +- src/base/ver/module.make | 4 + src/base/ver/ver.h | 114 ++ src/base/ver/verCore.c | 1092 ++++++++++++++++ src/base/ver/verFormula.c | 469 +++++++ src/base/ver/verParse.c | 115 ++ src/base/ver/verStream.c | 435 +++++++ src/base/ver/verWords.c | 48 + src/base/ver/ver_.c | 48 + src/map/fpga/fpga.h | 2 +- src/map/fpga/fpgaCut.c | 3 +- src/map/if/if.h | 255 ++++ src/map/if/ifCore.c | 47 + src/map/if/ifCut.c | 47 + src/map/if/ifMan.c | 250 ++++ src/map/if/ifMap.c | 391 ++++++ src/map/if/ifUtil.c | 229 ++++ src/map/if/if_.c | 47 + src/map/if/module.make | 4 + src/map/pga/module.make | 4 - src/map/pga/pga.h | 80 -- src/map/pga/pgaCore.c | 152 --- src/map/pga/pgaInt.h | 132 -- src/map/pga/pgaMan.c | 180 --- src/map/pga/pgaMatch.c | 378 ------ src/map/pga/pgaUtil.c | 320 ----- src/misc/vec/vec.h | 1 + src/misc/vec/vecAtt.h | 392 ++++++ src/opt/cut/abcCut.c | 2 + src/opt/dec/decAbc.c | 22 +- src/opt/ret/module.make | 3 +- src/opt/ret/retArea.c | 331 ++--- src/opt/ret/retCore.c | 26 +- src/opt/ret/retDelay.c | 24 +- src/opt/ret/retFlow.c | 370 +++++- src/opt/ret/retIncrem.c | 44 +- src/opt/ret/retInit.c | 1 - src/opt/ret/retInt.h | 6 +- src/opt/ret/retLvalue.c | 419 +++++++ src/sat/bsat/satSolver.c | 4 +- src/sat/fraig/fraigMan.c | 1 + src/temp/aig/aig.h | 321 ----- src/temp/aig/aigBalance.c | 391 ------ src/temp/aig/aigCheck.c | 110 -- src/temp/aig/aigDfs.c | 399 ------ src/temp/aig/aigMan.c | 162 --- src/temp/aig/aigMem.c | 115 -- src/temp/aig/aigObj.c | 228 ---- src/temp/aig/aigOper.c | 373 ------ src/temp/aig/aigTable.c | 266 ---- src/temp/aig/aigUtil.c | 502 -------- src/temp/aig/aig_.c | 48 - src/temp/aig/cudd2.c | 355 ------ src/temp/aig/cudd2.h | 82 -- src/temp/aig/module.make | 9 - src/temp/aig_free/aig.h | 321 ----- src/temp/aig_free/aigBalance.c | 391 ------ src/temp/aig_free/aigCheck.c | 110 -- src/temp/aig_free/aigDfs.c | 399 ------ src/temp/aig_free/aigMan.c | 162 --- src/temp/aig_free/aigMem.c | 115 -- src/temp/aig_free/aigObj.c | 228 ---- src/temp/aig_free/aigOper.c | 373 ------ src/temp/aig_free/aigTable.c | 266 ---- src/temp/aig_free/aigUtil.c | 513 -------- src/temp/aig_free/cudd2.c | 375 ------ src/temp/aig_free/cudd2.h | 83 -- src/temp/aig_free/st.c | 626 ---------- src/temp/aig_free/st.h | 96 -- src/temp/aig_free/subdir.mk | 87 -- src/temp/aig_free/vec.h | 82 -- src/temp/aig_free/vecFlt.h | 667 ---------- src/temp/aig_free/vecInt.h | 781 ------------ src/temp/aig_free/vecPtr.h | 587 --------- src/temp/aig_free/vecStr.h | 510 -------- src/temp/aig_free/vecVec.h | 289 ----- src/temp/deco/deco.h | 703 ----------- src/temp/deco/module.make | 1 - src/temp/ivy/ivy.h | 555 --------- src/temp/ivy/ivyBalance.c | 404 ------ src/temp/ivy/ivyCanon.c | 144 --- src/temp/ivy/ivyCheck.c | 273 ---- src/temp/ivy/ivyCut.c | 987 --------------- src/temp/ivy/ivyCutTrav.c | 473 ------- src/temp/ivy/ivyDfs.c | 493 -------- src/temp/ivy/ivyDsd.c | 819 ------------ src/temp/ivy/ivyFanout.c | 309 ----- src/temp/ivy/ivyFastMap.c | 1593 ----------------------- src/temp/ivy/ivyFraig.c | 2520 ------------------------------------- src/temp/ivy/ivyHaig.c | 530 -------- src/temp/ivy/ivyIsop.c | 328 ----- src/temp/ivy/ivyMan.c | 546 -------- src/temp/ivy/ivyMem.c | 115 -- src/temp/ivy/ivyMulti.c | 301 ----- src/temp/ivy/ivyMulti8.c | 427 ------- src/temp/ivy/ivyObj.c | 476 ------- src/temp/ivy/ivyOper.c | 293 ----- src/temp/ivy/ivyResyn.c | 196 --- src/temp/ivy/ivyRwr.c | 609 --------- src/temp/ivy/ivyRwrAlg.c | 408 ------ src/temp/ivy/ivySeq.c | 1130 ----------------- src/temp/ivy/ivyShow.c | 338 ----- src/temp/ivy/ivyTable.c | 301 ----- src/temp/ivy/ivyUtil.c | 738 ----------- src/temp/ivy/ivy_.c | 48 - src/temp/ivy/module.make | 23 - src/temp/mem/mem.c | 588 --------- src/temp/mem/mem.h | 71 -- src/temp/mem/module.make | 1 - src/temp/rwt/module.make | 3 - src/temp/rwt/rwt.h | 155 --- src/temp/rwt/rwtDec.c | 150 --- src/temp/rwt/rwtMan.c | 358 ------ src/temp/rwt/rwtUtil.c | 665 ---------- src/temp/ver/module.make | 4 - src/temp/ver/ver.h | 114 -- src/temp/ver/verCore.c | 1092 ---------------- src/temp/ver/verFormula.c | 469 ------- src/temp/ver/verParse.c | 115 -- src/temp/ver/verStream.c | 435 ------- src/temp/ver/verWords.c | 48 - src/temp/ver/ver_.c | 48 - 228 files changed, 28862 insertions(+), 33724 deletions(-) create mode 100644 src/aig/aig-alan.tar.gz create mode 100644 src/aig/deco/deco.h create mode 100644 src/aig/deco/module.make create mode 100644 src/aig/ec/module.make create mode 100644 src/aig/hop/cudd2.c create mode 100644 src/aig/hop/cudd2.h create mode 100644 src/aig/hop/hop.h create mode 100644 src/aig/hop/hopBalance.c create mode 100644 src/aig/hop/hopCheck.c create mode 100644 src/aig/hop/hopDfs.c create mode 100644 src/aig/hop/hopMan.c create mode 100644 src/aig/hop/hopMem.c create mode 100644 src/aig/hop/hopObj.c create mode 100644 src/aig/hop/hopOper.c create mode 100644 src/aig/hop/hopTable.c create mode 100644 src/aig/hop/hopUtil.c create mode 100644 src/aig/hop/hop_.c create mode 100644 src/aig/hop/module.make create mode 100644 src/aig/ivy/attr.h create mode 100644 src/aig/ivy/ivy.h create mode 100644 src/aig/ivy/ivyBalance.c create mode 100644 src/aig/ivy/ivyCanon.c create mode 100644 src/aig/ivy/ivyCheck.c create mode 100644 src/aig/ivy/ivyCut.c create mode 100644 src/aig/ivy/ivyCutTrav.c create mode 100644 src/aig/ivy/ivyDfs.c create mode 100644 src/aig/ivy/ivyDsd.c create mode 100644 src/aig/ivy/ivyFanout.c create mode 100644 src/aig/ivy/ivyFastMap.c create mode 100644 src/aig/ivy/ivyFpga.c create mode 100644 src/aig/ivy/ivyFraig.c create mode 100644 src/aig/ivy/ivyHaig.c create mode 100644 src/aig/ivy/ivyIsop.c create mode 100644 src/aig/ivy/ivyMan.c create mode 100644 src/aig/ivy/ivyMem.c create mode 100644 src/aig/ivy/ivyMulti.c create mode 100644 src/aig/ivy/ivyMulti8.c create mode 100644 src/aig/ivy/ivyObj.c create mode 100644 src/aig/ivy/ivyOper.c create mode 100644 src/aig/ivy/ivyResyn.c create mode 100644 src/aig/ivy/ivyRwr.c create mode 100644 src/aig/ivy/ivyRwrAlg.c create mode 100644 src/aig/ivy/ivySeq.c create mode 100644 src/aig/ivy/ivyShow.c create mode 100644 src/aig/ivy/ivyTable.c create mode 100644 src/aig/ivy/ivyUtil.c create mode 100644 src/aig/ivy/ivy_.c create mode 100644 src/aig/ivy/module.make create mode 100644 src/aig/mem/mem.c create mode 100644 src/aig/mem/mem.h create mode 100644 src/aig/mem/module.make create mode 100644 src/aig/rwt/module.make create mode 100644 src/aig/rwt/rwt.h create mode 100644 src/aig/rwt/rwtDec.c create mode 100644 src/aig/rwt/rwtMan.c create mode 100644 src/aig/rwt/rwtUtil.c create mode 100644 src/base/abci/abcIf.c create mode 100644 src/base/ver/module.make create mode 100644 src/base/ver/ver.h create mode 100644 src/base/ver/verCore.c create mode 100644 src/base/ver/verFormula.c create mode 100644 src/base/ver/verParse.c create mode 100644 src/base/ver/verStream.c create mode 100644 src/base/ver/verWords.c create mode 100644 src/base/ver/ver_.c create mode 100644 src/map/if/if.h create mode 100644 src/map/if/ifCore.c create mode 100644 src/map/if/ifCut.c create mode 100644 src/map/if/ifMan.c create mode 100644 src/map/if/ifMap.c create mode 100644 src/map/if/ifUtil.c create mode 100644 src/map/if/if_.c create mode 100644 src/map/if/module.make delete mode 100644 src/map/pga/module.make delete mode 100644 src/map/pga/pga.h delete mode 100644 src/map/pga/pgaCore.c delete mode 100644 src/map/pga/pgaInt.h delete mode 100644 src/map/pga/pgaMan.c delete mode 100644 src/map/pga/pgaMatch.c delete mode 100644 src/map/pga/pgaUtil.c create mode 100644 src/misc/vec/vecAtt.h create mode 100644 src/opt/ret/retLvalue.c delete mode 100644 src/temp/aig/aig.h delete mode 100644 src/temp/aig/aigBalance.c delete mode 100644 src/temp/aig/aigCheck.c delete mode 100644 src/temp/aig/aigDfs.c delete mode 100644 src/temp/aig/aigMan.c delete mode 100644 src/temp/aig/aigMem.c delete mode 100644 src/temp/aig/aigObj.c delete mode 100644 src/temp/aig/aigOper.c delete mode 100644 src/temp/aig/aigTable.c delete mode 100644 src/temp/aig/aigUtil.c delete mode 100644 src/temp/aig/aig_.c delete mode 100644 src/temp/aig/cudd2.c delete mode 100644 src/temp/aig/cudd2.h delete mode 100644 src/temp/aig/module.make delete mode 100644 src/temp/aig_free/aig.h delete mode 100644 src/temp/aig_free/aigBalance.c delete mode 100644 src/temp/aig_free/aigCheck.c delete mode 100644 src/temp/aig_free/aigDfs.c delete mode 100644 src/temp/aig_free/aigMan.c delete mode 100644 src/temp/aig_free/aigMem.c delete mode 100644 src/temp/aig_free/aigObj.c delete mode 100644 src/temp/aig_free/aigOper.c delete mode 100644 src/temp/aig_free/aigTable.c delete mode 100644 src/temp/aig_free/aigUtil.c delete mode 100644 src/temp/aig_free/cudd2.c delete mode 100644 src/temp/aig_free/cudd2.h delete mode 100644 src/temp/aig_free/st.c delete mode 100644 src/temp/aig_free/st.h delete mode 100644 src/temp/aig_free/subdir.mk delete mode 100644 src/temp/aig_free/vec.h delete mode 100644 src/temp/aig_free/vecFlt.h delete mode 100644 src/temp/aig_free/vecInt.h delete mode 100644 src/temp/aig_free/vecPtr.h delete mode 100644 src/temp/aig_free/vecStr.h delete mode 100644 src/temp/aig_free/vecVec.h delete mode 100644 src/temp/deco/deco.h delete mode 100644 src/temp/deco/module.make delete mode 100644 src/temp/ivy/ivy.h delete mode 100644 src/temp/ivy/ivyBalance.c delete mode 100644 src/temp/ivy/ivyCanon.c delete mode 100644 src/temp/ivy/ivyCheck.c delete mode 100644 src/temp/ivy/ivyCut.c delete mode 100644 src/temp/ivy/ivyCutTrav.c delete mode 100644 src/temp/ivy/ivyDfs.c delete mode 100644 src/temp/ivy/ivyDsd.c delete mode 100644 src/temp/ivy/ivyFanout.c delete mode 100644 src/temp/ivy/ivyFastMap.c delete mode 100644 src/temp/ivy/ivyFraig.c delete mode 100644 src/temp/ivy/ivyHaig.c delete mode 100644 src/temp/ivy/ivyIsop.c delete mode 100644 src/temp/ivy/ivyMan.c delete mode 100644 src/temp/ivy/ivyMem.c delete mode 100644 src/temp/ivy/ivyMulti.c delete mode 100644 src/temp/ivy/ivyMulti8.c delete mode 100644 src/temp/ivy/ivyObj.c delete mode 100644 src/temp/ivy/ivyOper.c delete mode 100644 src/temp/ivy/ivyResyn.c delete mode 100644 src/temp/ivy/ivyRwr.c delete mode 100644 src/temp/ivy/ivyRwrAlg.c delete mode 100644 src/temp/ivy/ivySeq.c delete mode 100644 src/temp/ivy/ivyShow.c delete mode 100644 src/temp/ivy/ivyTable.c delete mode 100644 src/temp/ivy/ivyUtil.c delete mode 100644 src/temp/ivy/ivy_.c delete mode 100644 src/temp/ivy/module.make delete mode 100644 src/temp/mem/mem.c delete mode 100644 src/temp/mem/mem.h delete mode 100644 src/temp/mem/module.make delete mode 100644 src/temp/rwt/module.make delete mode 100644 src/temp/rwt/rwt.h delete mode 100644 src/temp/rwt/rwtDec.c delete mode 100644 src/temp/rwt/rwtMan.c delete mode 100644 src/temp/rwt/rwtUtil.c delete mode 100644 src/temp/ver/module.make delete mode 100644 src/temp/ver/ver.h delete mode 100644 src/temp/ver/verCore.c delete mode 100644 src/temp/ver/verFormula.c delete mode 100644 src/temp/ver/verParse.c delete mode 100644 src/temp/ver/verStream.c delete mode 100644 src/temp/ver/verWords.c delete mode 100644 src/temp/ver/ver_.c diff --git a/Makefile b/Makefile index cf5e864f..3b37b2e6 100644 --- a/Makefile +++ b/Makefile @@ -6,13 +6,13 @@ CP := cp PROG := abc -MODULES := src/base/abc src/base/abci src/base/cmd src/base/io src/base/main \ +MODULES := src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/ver \ + src/aig/ivy src/aig/hop src/aig/rwt src/aig/deco src/mem/deco src/aig/ec \ src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/parse src/bdd/reo \ - src/map/fpga src/map/pga src/map/mapper src/map/mio src/map/super \ + src/map/fpga src/map/pga src/map/mapper src/map/mio src/map/super src/map/if \ src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/espresso src/misc/nm src/misc/vec src/misc/hash \ src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr src/opt/sim src/opt/ret \ - src/sat/asat src/sat/bsat src/sat/csat src/sat/msat src/sat/fraig \ - src/temp/ivy src/temp/aig src/temp/rwt src/temp/deco src/temp/mem src/temp/ver + src/sat/asat src/sat/bsat src/sat/csat src/sat/msat src/sat/fraig default: $(PROG) diff --git a/abc.dsp b/abc.dsp index f37efc65..c94c0e6d 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\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\bsat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\misc\hash" /I "src\temp\ivy" /I "src\temp\esop" /I "src\temp\rwt" /I "src\temp\deco" /I "src\temp\mem" /I "src\temp\aig" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\bsat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\if" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\misc\hash" /I "src\aig\ivy" /I "src\aig\hop" /I "src\aig\rwt" /I "src\aig\deco" /I "src\aig\mem" /I "src\temp\esop" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\bsat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\misc\hash" /I "src\temp\ivy" /I "src\temp\esop" /I "src\temp\rwt" /I "src\temp\deco" /I "src\temp\mem" /I "src\temp\aig" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\bsat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\if" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\misc\hash" /I "src\aig\ivy" /I "src\aig\hop" /I "src\aig\rwt" /I "src\aig\deco" /I "src\aig\mem" /I "src\temp\esop" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c # SUBTRACT CPP /X # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -238,6 +238,10 @@ SOURCE=.\src\base\abci\abcGen.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcIf.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcIvy.c # End Source File # Begin Source File @@ -270,10 +274,6 @@ SOURCE=.\src\base\abci\abcOrder.c # End Source File # Begin Source File -SOURCE=.\src\base\abci\abcPga.c -# End Source File -# Begin Source File - SOURCE=.\src\base\abci\abcPrint.c # End Source File # Begin Source File @@ -505,6 +505,226 @@ SOURCE=.\src\base\main\mainInt.h SOURCE=.\src\base\main\mainUtils.c # End Source File # End Group +# Begin Group "ver" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\ver\ver.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verFormula.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verParse.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verStream.c +# End Source File +# End Group +# End Group +# Begin Group "aig" + +# PROP Default_Filter "" +# Begin Group "hop" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\hop\hop.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopUtil.c +# End Source File +# End Group +# Begin Group "ivy" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\ivy\ivy.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCutTrav.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFastMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFpga.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFraig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyHaig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyIsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyResyn.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyRwr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivySeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyUtil.c +# End Source File +# End Group +# Begin Group "rwt" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\rwt\rwt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtUtil.c +# End Source File +# End Group +# Begin Group "deco" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\deco\deco.h +# End Source File +# End Group +# Begin Group "mem" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\mem\mem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\mem\mem.h +# End Source File +# End Group +# Begin Group "ec" + +# PROP Default_Filter "" +# End Group # End Group # Begin Group "bdd" @@ -1364,6 +1584,10 @@ SOURCE=.\src\opt\ret\retInit.c SOURCE=.\src\opt\ret\retInt.h # End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retLvalue.c +# End Source File # End Group # End Group # Begin Group "map" @@ -1577,32 +1801,32 @@ SOURCE=.\src\map\super\superInt.h SOURCE=.\src\map\super\superWrite.c # End Source File # End Group -# Begin Group "pga" +# Begin Group "if" # PROP Default_Filter "" # Begin Source File -SOURCE=.\src\map\pga\pga.h +SOURCE=.\src\map\if\if.h # End Source File # Begin Source File -SOURCE=.\src\map\pga\pgaCore.c +SOURCE=.\src\map\if\ifCore.c # End Source File # Begin Source File -SOURCE=.\src\map\pga\pgaInt.h +SOURCE=.\src\map\if\ifCut.c # End Source File # Begin Source File -SOURCE=.\src\map\pga\pgaMan.c +SOURCE=.\src\map\if\ifMan.c # End Source File # Begin Source File -SOURCE=.\src\map\pga\pgaMatch.c +SOURCE=.\src\map\if\ifMap.c # End Source File # Begin Source File -SOURCE=.\src\map\pga\pgaUtil.c +SOURCE=.\src\map\if\ifUtil.c # End Source File # End Group # End Group @@ -1774,6 +1998,10 @@ SOURCE=.\src\misc\vec\vec.h # End Source File # Begin Source File +SOURCE=.\src\misc\vec\vecAtt.h +# End Source File +# Begin Source File + SOURCE=.\src\misc\vec\vecFlt.h # End Source File # Begin Source File @@ -2025,258 +2253,6 @@ SOURCE=.\src\misc\hash\hashPtr.h # Begin Group "temp" # PROP Default_Filter "" -# Begin Group "ivy" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\ivy\ivy.h -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyCutTrav.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyDsd.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyFastMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyFraig.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyHaig.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyIsop.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyMulti.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyOper.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyResyn.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyRwr.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivySeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyShow.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ivy\ivyUtil.c -# End Source File -# End Group -# Begin Group "player" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\player\player.h -# End Source File -# Begin Source File - -SOURCE=.\src\temp\player\playerCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\player\playerMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\player\playerToAbc.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\player\playerUtil.c -# End Source File -# End Group -# Begin Group "esop" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\esop\esop.h -# End Source File -# Begin Source File - -SOURCE=.\src\temp\esop\esopMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\esop\esopMin.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\esop\esopUtil.c -# End Source File -# End Group -# Begin Group "rwt" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\rwt\rwt.h -# End Source File -# Begin Source File - -SOURCE=.\src\temp\rwt\rwtDec.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\rwt\rwtMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\rwt\rwtUtil.c -# End Source File -# End Group -# Begin Group "deco" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\deco\deco.h -# End Source File -# End Group -# Begin Group "mem" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\mem\mem.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\mem\mem.h -# End Source File -# End Group -# Begin Group "ver" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\ver\ver.h -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ver\verCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ver\verFormula.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ver\verParse.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\ver\verStream.c -# End Source File -# End Group -# Begin Group "aig" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\aig\aig.h -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigOper.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\aig\aigUtil.c -# End Source File -# End Group # End Group # End Group # Begin Group "Header Files" diff --git a/abc.rc b/abc.rc index abde3836..e4902714 100644 --- a/abc.rc +++ b/abc.rc @@ -43,6 +43,9 @@ alias psy print_symm alias pun print_unate alias q quit alias r read +alias r3 retime -M 3 +alias r3f retime -M 3 -f +alias r3b retime -M 3 -b alias ren renode alias rl read_blif alias rb read_bench diff --git a/src/aig/aig-alan.tar.gz b/src/aig/aig-alan.tar.gz new file mode 100644 index 00000000..b61827ad Binary files /dev/null and b/src/aig/aig-alan.tar.gz differ diff --git a/src/aig/deco/deco.h b/src/aig/deco/deco.h new file mode 100644 index 00000000..67126902 --- /dev/null +++ b/src/aig/deco/deco.h @@ -0,0 +1,703 @@ +/**CFile**************************************************************** + + FileName [deco.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [A simple decomposition tree/node data structure and its APIs.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __DEC_H__ +#define __DEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dec_Edge_t_ Dec_Edge_t; +struct Dec_Edge_t_ +{ + unsigned fCompl : 1; // the complemented bit + unsigned Node : 30; // the decomposition node pointed by the edge +}; + +typedef struct Dec_Node_t_ Dec_Node_t; +struct Dec_Node_t_ +{ + Dec_Edge_t eEdge0; // the left child of the node + Dec_Edge_t eEdge1; // the right child of the node + // other info + void * pFunc; // the function of the node (BDD or AIG) + unsigned Level : 14; // the level of this node in the global AIG + // printing info + unsigned fNodeOr : 1; // marks the original OR node + unsigned fCompl0 : 1; // marks the original complemented edge + unsigned fCompl1 : 1; // marks the original complemented edge + // latch info + unsigned nLat0 : 5; // the number of latches on the first edge + unsigned nLat1 : 5; // the number of latches on the second edge + unsigned nLat2 : 5; // the number of latches on the output edge +}; + +typedef struct Dec_Graph_t_ Dec_Graph_t; +struct Dec_Graph_t_ +{ + int fConst; // marks the constant 1 graph + int nLeaves; // the number of leaves + int nSize; // the number of nodes (including the leaves) + int nCap; // the number of allocated nodes + Dec_Node_t * pNodes; // the array of leaves and internal nodes + Dec_Edge_t eRoot; // the pointer to the topmost node +}; + +typedef struct Dec_Man_t_ Dec_Man_t; +struct Dec_Man_t_ +{ + void * pMvcMem; // memory manager for MVC cover (used for factoring) + Vec_Int_t * vCubes; // storage for cubes + Vec_Int_t * vLits; // storage for literals + // precomputation information about 4-variable functions + unsigned short * puCanons; // canonical forms + char * pPhases; // canonical phases + char * pPerms; // canonical permutations + unsigned char * pMap; // mapping of functions into class numbers +}; + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// interator throught the leaves +#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ + for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) +// interator throught the internal nodes +#define Dec_GraphForEachNode( pGraph, pAnd, i ) \ + for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates an edge pointing to the node in the given polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) +{ + Dec_Edge_t eEdge = { fCompl, Node }; + return eEdge; +} + +/**Function************************************************************* + + Synopsis [Converts the edge into unsigned integer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) +{ + return (eEdge.Node << 1) | eEdge.fCompl; +} + +/**Function************************************************************* + + Synopsis [Converts unsigned integer into the edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) +{ + return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); +} + +/**Function************************************************************* + + Synopsis [Converts the edge into unsigned integer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge ) +{ + return *(unsigned *)&eEdge; +} + +/**Function************************************************************* + + Synopsis [Converts unsigned integer into the edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge ) +{ + return *(Dec_Edge_t *)&Edge; +} + +/**Function************************************************************* + + Synopsis [Creates a graph with the given number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves ) +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->nLeaves = nLeaves; + pGraph->nSize = nLeaves; + pGraph->nCap = 2 * nLeaves + 50; + pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap ); + memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates constant 0 graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateConst0() +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->fConst = 1; + pGraph->eRoot.fCompl = 1; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates constant 1 graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateConst1() +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->fConst = 1; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates the literal graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) +{ + Dec_Graph_t * pGraph; + assert( 0 <= iLeaf && iLeaf < nLeaves ); + pGraph = Dec_GraphCreate( nLeaves ); + pGraph->eRoot.Node = iLeaf; + pGraph->eRoot.fCompl = fCompl; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates a graph with the given number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) +{ + FREE( pGraph->pNodes ); + free( pGraph ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst && pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst && !pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is complemented.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph ) +{ + return pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Checks if the graph is complemented.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphComplement( Dec_Graph_t * pGraph ) +{ + pGraph->eRoot.fCompl ^= 1; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph ) +{ + return pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the number of internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph ) +{ + return pGraph->nSize - pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i ) +{ + return pGraph->pNodes + i; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph ) +{ + return pGraph->pNodes + pGraph->nSize - 1; +} + +/**Function************************************************************* + + Synopsis [Returns the number of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) +{ + return pNode - pGraph->pNodes; +} + +/**Function************************************************************* + + Synopsis [Check if the graph represents elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph ) +{ + return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Check if the graph represents elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) +{ + return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the elementary variable elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph ) +{ + assert( Dec_GraphIsVar( pGraph ) ); + return Dec_GraphNode( pGraph, pGraph->eRoot.Node ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of the elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph ) +{ + assert( Dec_GraphIsVar( pGraph ) ); + return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Sets the root of the graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot ) +{ + pGraph->eRoot = eRoot; +} + +/**Function************************************************************* + + Synopsis [Appends a new node to the graph.] + + Description [This procedure is meant for internal use.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph ) +{ + Dec_Node_t * pNode; + if ( pGraph->nSize == pGraph->nCap ) + { + pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); + pGraph->nCap = 2 * pGraph->nCap; + } + pNode = pGraph->pNodes + pGraph->nSize++; + memset( pNode, 0, sizeof(Dec_Node_t) ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates an AND node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) +{ + Dec_Node_t * pNode; + // get the new node + pNode = Dec_GraphAppendNode( pGraph ); + // set the inputs and other info + pNode->eEdge0 = eEdge0; + pNode->eEdge1 = eEdge1; + pNode->fCompl0 = eEdge0.fCompl; + pNode->fCompl1 = eEdge1.fCompl; + return Dec_EdgeCreate( pGraph->nSize - 1, 0 ); +} + +/**Function************************************************************* + + Synopsis [Creates an OR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) +{ + Dec_Node_t * pNode; + // get the new node + pNode = Dec_GraphAppendNode( pGraph ); + // set the inputs and other info + pNode->eEdge0 = eEdge0; + pNode->eEdge1 = eEdge1; + pNode->fCompl0 = eEdge0.fCompl; + pNode->fCompl1 = eEdge1.fCompl; + // make adjustments for the OR gate + pNode->fNodeOr = 1; + pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; + pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; + return Dec_EdgeCreate( pGraph->nSize - 1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Creates an XOR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + if ( Type == 0 ) + { + // derive the first AND + eEdge0.fCompl ^= 1; + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + eEdge0.fCompl ^= 1; + // derive the second AND + eEdge1.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + } + else + { + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the second AND + eEdge0.fCompl ^= 1; + eEdge1.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eNode.fCompl ^= 1; + } + return eNode; +} + +/**Function************************************************************* + + Synopsis [Creates an XOR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + if ( Type == 0 ) + { + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); + // derive the second AND + eEdgeC.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + } + else + { + // complement the arguments + eEdgeT.fCompl ^= 1; + eEdgeE.fCompl ^= 1; + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); + // derive the second AND + eEdgeC.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eNode.fCompl ^= 1; + } + return eNode; +} + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/deco/module.make b/src/aig/deco/module.make new file mode 100644 index 00000000..d6d908e7 --- /dev/null +++ b/src/aig/deco/module.make @@ -0,0 +1 @@ +SRC += diff --git a/src/aig/ec/module.make b/src/aig/ec/module.make new file mode 100644 index 00000000..d6d908e7 --- /dev/null +++ b/src/aig/ec/module.make @@ -0,0 +1 @@ +SRC += diff --git a/src/aig/hop/cudd2.c b/src/aig/hop/cudd2.c new file mode 100644 index 00000000..28d13ce0 --- /dev/null +++ b/src/aig/hop/cudd2.c @@ -0,0 +1,355 @@ +/**CFile**************************************************************** + + FileName [cudd2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Recording AIGs for the BDD operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 3, 2006.] + + Revision [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" +#include "st.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_CuddMan_t_ Aig_CuddMan_t; +struct Aig_CuddMan_t_ +{ + Aig_Man_t * pAig; // internal AIG package + st_table * pTable; // hash table mapping BDD nodes into AIG nodes +}; + +// static Cudd AIG manager used in this experiment +static Aig_CuddMan_t * s_pCuddMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start AIG recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ) +{ + int v; + // start the BDD-to-AIG manager when the first BDD manager is allocated + if ( s_pCuddMan != NULL ) + return; + s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 ); + s_pCuddMan->pAig = Aig_ManStart(); + s_pCuddMan->pTable = st_init_table( st_ptrcmp, st_ptrhash ); + for ( v = 0; v < (int)numVars; v++ ) + Aig_ObjCreatePi( s_pCuddMan->pAig ); +} + +/**Function************************************************************* + + Synopsis [Stops AIG recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_Quit( void * pCudd ) +{ + assert( s_pCuddMan != NULL ); + Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif" ); + Aig_ManStop( s_pCuddMan->pAig ); + st_free_table( s_pCuddMan->pTable ); + free( s_pCuddMan ); + s_pCuddMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Aig_Obj_t * Cudd2_GetArg( void * pArg ) +{ + Aig_Obj_t * pNode; + assert( s_pCuddMan != NULL ); + if ( !st_lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) ) + { + printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" ); + return NULL; + } + return Aig_NotCond( pNode, Aig_IsComplement(pArg) ); +} + +/**Function************************************************************* + + Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult ) +{ + assert( s_pCuddMan != NULL ); + if ( st_is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) ) + return; + pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) ); + st_insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode ); +} + +/**Function************************************************************* + + Synopsis [Registers constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddOne( void * pCudd, void * pResult ) +{ + Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult ); +} + +/**Function************************************************************* + + Synopsis [Adds elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult ) +{ + int v; + assert( s_pCuddMan != NULL ); + for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ ) + Aig_ObjCreatePi( s_pCuddMan->pAig ); + Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode2 = Cudd2_GetArg( pArg2 ); + pNode = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Should be called after each containment check.] + + Description [Result should be 1 if Cudd2_bddLeq returned 1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) ); + Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); +} + +/**Function************************************************************* + + Synopsis [Should be called after each equality check.] + + Description [Result should be 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); + Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/cudd2.h b/src/aig/hop/cudd2.h new file mode 100644 index 00000000..69711c11 --- /dev/null +++ b/src/aig/hop/cudd2.h @@ -0,0 +1,82 @@ +/**CFile**************************************************************** + + FileName [cudd2.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 3, 2006.] + + Revision [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CUDD2_H__ +#define __CUDD2_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +// HA: Added for printing messages +#ifndef MSG +#define MSG(msg) (printf("%s = \n",(msg))); +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Cudd2_Init ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ); +extern void Cudd2_Quit ( void * pCudd ); +extern void Cudd2_bddOne ( void * pCudd, void * pResult ); +extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult ); +extern void Cudd2_bddAnd ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddOr ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddNand ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddNor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddXor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddXnor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddIte ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ); +extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ); +extern void Cudd2_bddLeq ( void * pCudd, void * pArg0, void * pArg1, int Result ); +extern void Cudd2_bddEqual ( void * pCudd, void * pArg0, void * pArg1, int Result ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/hop/hop.h b/src/aig/hop/hop.h new file mode 100644 index 00000000..a5d6e2e5 --- /dev/null +++ b/src/aig/hop/hop.h @@ -0,0 +1,321 @@ +/**CFile**************************************************************** + + FileName [hop.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hop.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __HOP_H__ +#define __HOP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Hop_Man_t_ Hop_Man_t; +typedef struct Hop_Obj_t_ Hop_Obj_t; +typedef int Hop_Edge_t; + +// object types +typedef enum { + AIG_NONE, // 0: non-existent object + AIG_CONST1, // 1: constant 1 + AIG_PI, // 2: primary input + AIG_PO, // 3: primary output + AIG_AND, // 4: AND node + AIG_EXOR, // 5: EXOR node + AIG_VOID // 6: unused object +} Hop_Type_t; + +// the AIG node +struct Hop_Obj_t_ // 4 words +{ + void * pData; // misc + Hop_Obj_t * pFanin0; // fanin + Hop_Obj_t * pFanin1; // fanin + unsigned long Type : 3; // object type + unsigned long fPhase : 1; // value under 000...0 pattern + unsigned long fMarkA : 1; // multipurpose mask + unsigned long fMarkB : 1; // multipurpose mask + unsigned long nRefs : 26; // reference count (level) +}; + +// the AIG manager +struct Hop_Man_t_ +{ + // AIG nodes + Vec_Ptr_t * vPis; // the array of PIs + Vec_Ptr_t * vPos; // the array of POs + Hop_Obj_t * pConst1; // the constant 1 node + Hop_Obj_t Ghost; // the ghost node + // AIG node counters + int nObjs[AIG_VOID];// the number of objects by type + int nCreated; // the number of created objects + int nDeleted; // the number of deleted objects + // stuctural hash table + Hop_Obj_t ** pTable; // structural hash table + int nTableSize; // structural hash table size + // various data members + void * pData; // the temporary data + int nTravIds; // the current traversal ID + int fRefCount; // enables reference counting + int fCatchExor; // enables EXOR nodes + // memory management + Vec_Ptr_t * vChunks; // allocated memory pieces + Vec_Ptr_t * vPages; // memory pages used by nodes + Hop_Obj_t * pListFree; // the list of free nodes + // timing statistics + int time1; + int time2; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AIG_MIN(a,b) (((a) < (b))? (a) : (b)) +#define AIG_MAX(a,b) (((a) > (b))? (a) : (b)) + +#ifndef PRT +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) +#endif + +static inline int Hop_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Hop_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Hop_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Hop_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Hop_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } + +static inline Hop_Obj_t * Hop_Regular( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) & ~01); } +static inline Hop_Obj_t * Hop_Not( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) ^ 01); } +static inline Hop_Obj_t * Hop_NotCond( Hop_Obj_t * p, int c ) { return (Hop_Obj_t *)((unsigned long)(p) ^ (c)); } +static inline int Hop_IsComplement( Hop_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } + +static inline Hop_Obj_t * Hop_ManConst0( Hop_Man_t * p ) { return Hop_Not(p->pConst1); } +static inline Hop_Obj_t * Hop_ManConst1( Hop_Man_t * p ) { return p->pConst1; } +static inline Hop_Obj_t * Hop_ManGhost( Hop_Man_t * p ) { return &p->Ghost; } +static inline Hop_Obj_t * Hop_ManPi( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPis, i); } + +static inline Hop_Edge_t Hop_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } +static inline int Hop_EdgeId( Hop_Edge_t Edge ) { return Edge >> 1; } +static inline int Hop_EdgeIsComplement( Hop_Edge_t Edge ) { return Edge & 1; } +static inline Hop_Edge_t Hop_EdgeRegular( Hop_Edge_t Edge ) { return (Edge >> 1) << 1; } +static inline Hop_Edge_t Hop_EdgeNot( Hop_Edge_t Edge ) { return Edge ^ 1; } +static inline Hop_Edge_t Hop_EdgeNotCond( Hop_Edge_t Edge, int fCond ) { return Edge ^ fCond; } + +static inline int Hop_ManPiNum( Hop_Man_t * p ) { return p->nObjs[AIG_PI]; } +static inline int Hop_ManPoNum( Hop_Man_t * p ) { return p->nObjs[AIG_PO]; } +static inline int Hop_ManAndNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]; } +static inline int Hop_ManExorNum( Hop_Man_t * p ) { return p->nObjs[AIG_EXOR]; } +static inline int Hop_ManNodeNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+p->nObjs[AIG_EXOR];} +static inline int Hop_ManGetCost( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+3*p->nObjs[AIG_EXOR]; } +static inline int Hop_ManObjNum( Hop_Man_t * p ) { return p->nCreated - p->nDeleted; } + +static inline Hop_Type_t Hop_ObjType( Hop_Obj_t * pObj ) { return pObj->Type; } +static inline int Hop_ObjIsNone( Hop_Obj_t * pObj ) { return pObj->Type == AIG_NONE; } +static inline int Hop_ObjIsConst1( Hop_Obj_t * pObj ) { assert(!Hop_IsComplement(pObj)); return pObj->Type == AIG_CONST1; } +static inline int Hop_ObjIsPi( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI; } +static inline int Hop_ObjIsPo( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PO; } +static inline int Hop_ObjIsAnd( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND; } +static inline int Hop_ObjIsExor( Hop_Obj_t * pObj ) { return pObj->Type == AIG_EXOR; } +static inline int Hop_ObjIsNode( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } +static inline int Hop_ObjIsTerm( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI || pObj->Type == AIG_PO || pObj->Type == AIG_CONST1; } +static inline int Hop_ObjIsHash( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } + +static inline int Hop_ObjIsMarkA( Hop_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Hop_ObjSetMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Hop_ObjClearMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 0; } + +static inline void Hop_ObjSetTravId( Hop_Obj_t * pObj, int TravId ) { pObj->pData = (void *)TravId; } +static inline void Hop_ObjSetTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)p->nTravIds; } +static inline void Hop_ObjSetTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)(p->nTravIds - 1); } +static inline int Hop_ObjIsTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds); } +static inline int Hop_ObjIsTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds - 1); } + +static inline int Hop_ObjTravId( Hop_Obj_t * pObj ) { return (int)pObj->pData; } +static inline int Hop_ObjPhase( Hop_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Hop_ObjRefs( Hop_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Hop_ObjRef( Hop_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Hop_ObjDeref( Hop_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline void Hop_ObjClearRef( Hop_Obj_t * pObj ) { pObj->nRefs = 0; } +static inline int Hop_ObjFaninC0( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin0); } +static inline int Hop_ObjFaninC1( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin1); } +static inline Hop_Obj_t * Hop_ObjFanin0( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin0); } +static inline Hop_Obj_t * Hop_ObjFanin1( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin1); } +static inline Hop_Obj_t * Hop_ObjChild0( Hop_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Hop_Obj_t * Hop_ObjChild1( Hop_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Hop_Obj_t * Hop_ObjChild0Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Hop_NotCond(Hop_ObjFanin0(pObj)->pData, Hop_ObjFaninC0(pObj)) : NULL; } +static inline Hop_Obj_t * Hop_ObjChild1Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Hop_NotCond(Hop_ObjFanin1(pObj)->pData, Hop_ObjFaninC1(pObj)) : NULL; } +static inline int Hop_ObjLevel( Hop_Obj_t * pObj ) { return pObj->nRefs; } +static inline int Hop_ObjLevelNew( Hop_Obj_t * pObj ) { return 1 + Hop_ObjIsExor(pObj) + AIG_MAX(Hop_ObjFanin0(pObj)->nRefs, Hop_ObjFanin1(pObj)->nRefs); } +static inline void Hop_ObjClean( Hop_Obj_t * pObj ) { memset( pObj, 0, sizeof(Hop_Obj_t) ); } +static inline int Hop_ObjWhatFanin( Hop_Obj_t * pObj, Hop_Obj_t * pFanin ) +{ + if ( Hop_ObjFanin0(pObj) == pFanin ) return 0; + if ( Hop_ObjFanin1(pObj) == pFanin ) return 1; + assert(0); return -1; +} +static inline int Hop_ObjFanoutC( Hop_Obj_t * pObj, Hop_Obj_t * pFanout ) +{ + if ( Hop_ObjFanin0(pFanout) == pObj ) return Hop_ObjFaninC0(pObj); + if ( Hop_ObjFanin1(pFanout) == pObj ) return Hop_ObjFaninC1(pObj); + assert(0); return -1; +} + +// create the ghost of the new node +static inline Hop_Obj_t * Hop_ObjCreateGhost( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) +{ + Hop_Obj_t * pGhost; + assert( Type != AIG_AND || !Hop_ObjIsConst1(Hop_Regular(p0)) ); + assert( p1 == NULL || !Hop_ObjIsConst1(Hop_Regular(p1)) ); + assert( Type == AIG_PI || Hop_Regular(p0) != Hop_Regular(p1) ); + pGhost = Hop_ManGhost(p); + pGhost->Type = Type; + pGhost->pFanin0 = p0 < p1? p0 : p1; + pGhost->pFanin1 = p0 < p1? p1 : p0; + return pGhost; +} + +// internal memory manager +static inline Hop_Obj_t * Hop_ManFetchMemory( Hop_Man_t * p ) +{ + extern void Hop_ManAddMemory( Hop_Man_t * p ); + Hop_Obj_t * pTemp; + if ( p->pListFree == NULL ) + Hop_ManAddMemory( p ); + pTemp = p->pListFree; + p->pListFree = *((Hop_Obj_t **)pTemp); + memset( pTemp, 0, sizeof(Hop_Obj_t) ); + return pTemp; +} +static inline void Hop_ManRecycleMemory( Hop_Man_t * p, Hop_Obj_t * pEntry ) +{ + pEntry->Type = AIG_NONE; // distinquishes dead node from live node + *((Hop_Obj_t **)pEntry) = p->pListFree; + p->pListFree = pEntry; +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Hop_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPis, pObj, i ) +// iterator over the primary outputs +#define Hop_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Hop_ManForEachNode( p, pObj, i ) \ + for ( i = 0; i < p->nTableSize; i++ ) \ + if ( ((pObj) = p->pTable[i]) == NULL ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== aigBalance.c ========================================================*/ +extern Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ); +extern Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ); +/*=== aigCheck.c ========================================================*/ +extern int Hop_ManCheck( Hop_Man_t * p ); +/*=== aigDfs.c ==========================================================*/ +extern Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ); +extern Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ); +extern int Hop_ManCountLevels( Hop_Man_t * p ); +extern void Hop_ManCreateRefs( Hop_Man_t * p ); +extern int Hop_DagSize( Hop_Obj_t * pObj ); +extern void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ); +extern Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars ); +extern Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ); +/*=== aigMan.c ==========================================================*/ +extern Hop_Man_t * Hop_ManStart(); +extern Hop_Man_t * Hop_ManDup( Hop_Man_t * p ); +extern void Hop_ManStop( Hop_Man_t * p ); +extern int Hop_ManCleanup( Hop_Man_t * p ); +extern void Hop_ManPrintStats( Hop_Man_t * p ); +/*=== aigMem.c ==========================================================*/ +extern void Hop_ManStartMemory( Hop_Man_t * p ); +extern void Hop_ManStopMemory( Hop_Man_t * p ); +/*=== aigObj.c ==========================================================*/ +extern Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ); +extern Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ); +extern Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ); +extern void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ); +extern void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ); +/*=== aigOper.c =========================================================*/ +extern Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ); +extern Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ); +extern Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ); +extern Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ); +extern Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ); +extern Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ); +extern Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ); +extern Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ); +/*=== aigTable.c ========================================================*/ +extern Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ); +extern void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern int Hop_TableCountEntries( Hop_Man_t * p ); +extern void Hop_TableProfile( Hop_Man_t * p ); +/*=== aigUtil.c =========================================================*/ +extern void Hop_ManIncrementTravId( Hop_Man_t * p ); +extern void Hop_ManCleanData( Hop_Man_t * p ); +extern void Hop_ObjCollectMulti( Hop_Obj_t * pFunc, Vec_Ptr_t * vSuper ); +extern int Hop_ObjIsMuxType( Hop_Obj_t * pObj ); +extern int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ); +extern Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pObj, Hop_Obj_t ** ppObjT, Hop_Obj_t ** ppObjE ); +extern void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); +extern void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ); +extern void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ); +extern void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/hop/hopBalance.c b/src/aig/hop/hopBalance.c new file mode 100644 index 00000000..73c90685 --- /dev/null +++ b/src/aig/hop/hopBalance.c @@ -0,0 +1,391 @@ +/**CFile**************************************************************** + + FileName [hopBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Algebraic AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); +static Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); +static int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); +static void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); +static void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs algebraic balancing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ) +{ + Hop_Man_t * pNew; + Hop_Obj_t * pObj, * pObjNew; + Vec_Vec_t * vStore; + int i; + // create the new manager + pNew = Hop_ManStart(); + pNew->fRefCount = 0; + // map the PI nodes + Hop_ManCleanData( p ); + Hop_ManConst1(p)->pData = Hop_ManConst1(pNew); + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = Hop_ObjCreatePi(pNew); + // balance the AIG + vStore = Vec_VecAlloc( 50 ); + Hop_ManForEachPo( p, pObj, i ) + { + pObjNew = Hop_NodeBalance_rec( pNew, Hop_ObjFanin0(pObj), vStore, 0, fUpdateLevel ); + Hop_ObjCreatePo( pNew, Hop_NotCond( pObjNew, Hop_ObjFaninC0(pObj) ) ); + } + Vec_VecFree( vStore ); + // remove dangling nodes +// Hop_ManCreateRefs( pNew ); +// if ( i = Hop_ManCleanup( pNew ) ) +// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); + // check the resulting AIG + if ( !Hop_ManCheck(pNew) ) + printf( "Hop_ManBalance(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the new node constructed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) +{ + Hop_Obj_t * pObjNew; + Vec_Ptr_t * vSuper; + int i; + assert( !Hop_IsComplement(pObjOld) ); + // return if the result is known + if ( pObjOld->pData ) + return pObjOld->pData; + assert( Hop_ObjIsNode(pObjOld) ); + // get the implication supergate + vSuper = Hop_NodeBalanceCone( pObjOld, vStore, Level ); + // check if supergate contains two nodes in the opposite polarity + if ( vSuper->nSize == 0 ) + return pObjOld->pData = Hop_ManConst0(pNew); + if ( Vec_PtrSize(vSuper) < 2 ) + printf( "BUG!\n" ); + // for each old node, derive the new well-balanced node + for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) + { + pObjNew = Hop_NodeBalance_rec( pNew, Hop_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); + vSuper->pArray[i] = Hop_NotCond( pObjNew, Hop_IsComplement(vSuper->pArray[i]) ); + } + // build the supergate + pObjNew = Hop_NodeBalanceBuildSuper( pNew, vSuper, Hop_ObjType(pObjOld), fUpdateLevel ); + // make sure the balanced node is not assigned +// assert( pObjOld->Level >= Hop_Regular(pObjNew)->Level ); + assert( pObjOld->pData == NULL ); + return pObjOld->pData = pObjNew; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeBalanceCone_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Hop_Regular(pObj)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Hop_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Hop_IsComplement(pObj) || Hop_ObjType(pObj) != Hop_ObjType(pRoot) || Hop_ObjRefs(pObj) > 1) ) + { + Vec_PtrPush( vSuper, pObj ); + Hop_Regular(pObj)->fMarkB = 1; + return 0; + } + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); + RetValue2 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Hop_IsComplement(pObj) ); + // extend the storage + if ( Vec_VecSize( vStore ) <= Level ) + Vec_VecPush( vStore, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStore, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Hop_NodeBalanceCone_rec( pObj, pObj, vNodes ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + Hop_Regular(pObj)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeCompareLevelsDecrease( Hop_Obj_t ** pp1, Hop_Obj_t ** pp2 ) +{ + int Diff = Hop_ObjLevel(Hop_Regular(*pp1)) - Hop_ObjLevel(Hop_Regular(*pp2)); + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Builds implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ) +{ + Hop_Obj_t * pObj1, * pObj2; + int LeftBound; + assert( vSuper->nSize > 1 ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, Hop_NodeCompareLevelsDecrease ); + // balance the nodes + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Hop_NodeBalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Hop_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR ); + // pull out the last two nodes + pObj1 = Vec_PtrPop(vSuper); + pObj2 = Vec_PtrPop(vSuper); + Hop_NodeBalancePushUniqueOrderByLevel( vSuper, Hop_Oper(p, pObj1, pObj2, Type) ); + } + return Vec_PtrEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Hop_Obj_t * pObjRight, * pObjLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pObjRight = Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pObjLeft = Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Hop_ObjLevel(Hop_Regular(pObjLeft)) != Hop_ObjLevel(Hop_Regular(pObjRight)) ) + break; + } + Current++; + // get the node, for which the equality holds + pObjLeft = Vec_PtrEntry( vSuper, Current ); + assert( Hop_ObjLevel(Hop_Regular(pObjLeft)) == Hop_ObjLevel(Hop_Regular(pObjRight)) ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) +{ + Hop_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); + pObj2 = Vec_PtrEntry( vSuper, RightBound ); + if ( Hop_Regular(pObj1) == p->pConst1 || Hop_Regular(pObj2) == p->pConst1 ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pObj3 = Vec_PtrEntry( vSuper, i ); + if ( Hop_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + pGhost = Hop_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND ); + if ( Hop_TableLookup( p, pGhost ) ) + { + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pObj1, * pObj2; + int i; + if ( Vec_PtrPushUnique(vStore, pObj) ) + return; + // find the p of the node + for ( i = vStore->nSize-1; i > 0; i-- ) + { + pObj1 = vStore->pArray[i ]; + pObj2 = vStore->pArray[i-1]; + if ( Hop_ObjLevel(Hop_Regular(pObj1)) <= Hop_ObjLevel(Hop_Regular(pObj2)) ) + break; + vStore->pArray[i ] = pObj2; + vStore->pArray[i-1] = pObj1; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hopCheck.c b/src/aig/hop/hopCheck.c new file mode 100644 index 00000000..44bac2d7 --- /dev/null +++ b/src/aig/hop/hopCheck.c @@ -0,0 +1,110 @@ +/**CFile**************************************************************** + + FileName [hopCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the consistency of the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCheck( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj, * pObj2; + int i; + // check primary inputs + Hop_ManForEachPi( p, pObj, i ) + { + if ( Hop_ObjFanin0(pObj) || Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); + return 0; + } + } + // check primary outputs + Hop_ManForEachPo( p, pObj, i ) + { + if ( !Hop_ObjFanin0(pObj) ) + { + printf( "Hop_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); + return 0; + } + if ( Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); + return 0; + } + } + // check internal nodes + Hop_ManForEachNode( p, pObj, i ) + { + if ( !Hop_ObjFanin0(pObj) || !Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); + return 0; + } + if ( Hop_ObjFanin0(pObj) >= Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); + return 0; + } + pObj2 = Hop_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + { + printf( "Hop_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); + return 0; + } + } + // count the total number of nodes + if ( Hop_ManObjNum(p) != 1 + Hop_ManPiNum(p) + Hop_ManPoNum(p) + Hop_ManAndNum(p) + Hop_ManExorNum(p) ) + { + printf( "Hop_ManCheck: The number of created nodes is wrong.\n" ); + return 0; + } + // count the number of nodes in the table + if ( Hop_TableCountEntries(p) != Hop_ManAndNum(p) + Hop_ManExorNum(p) ) + { + printf( "Hop_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } +// if ( !Hop_ManIsAcyclic(p) ) +// return 0; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hopDfs.c b/src/aig/hop/hopDfs.c new file mode 100644 index 00000000..49e5f221 --- /dev/null +++ b/src/aig/hop/hopDfs.c @@ -0,0 +1,399 @@ +/**CFile**************************************************************** + + FileName [hopDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [DFS traversal procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManDfs_rec( Hop_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ManDfs_rec( Hop_ObjFanin0(pObj), vNodes ); + Hop_ManDfs_rec( Hop_ObjFanin1(pObj), vNodes ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA(pObj); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + vNodes = Vec_PtrAlloc( Hop_ManNodeNum(p) ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ManDfs_rec( pObj, vNodes ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ObjClearMarkA(pObj); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + assert( !Hop_IsComplement(pNode) ); + vNodes = Vec_PtrAlloc( 16 ); + Hop_ManDfs_rec( pNode, vNodes ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Hop_ObjClearMarkA(pObj); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the max number of levels in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCountLevels( Hop_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i, LevelsMax, Level0, Level1; + // initialize the levels + Hop_ManConst1(p)->pData = NULL; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = NULL; + // compute levels in a DFS order + vNodes = Hop_ManDfs( p ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Level0 = (int)Hop_ObjFanin0(pObj)->pData; + Level1 = (int)Hop_ObjFanin1(pObj)->pData; + pObj->pData = (void *)(1 + Hop_ObjIsExor(pObj) + AIG_MAX(Level0, Level1)); + } + Vec_PtrFree( vNodes ); + // get levels of the POs + LevelsMax = 0; + Hop_ManForEachPo( p, pObj, i ) + LevelsMax = AIG_MAX( LevelsMax, (int)Hop_ObjFanin0(pObj)->pData ); + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Creates correct reference counters at each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManCreateRefs( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + if ( p->fRefCount ) + return; + p->fRefCount = 1; + // clear refs + Hop_ObjClearRef( Hop_ManConst1(p) ); + Hop_ManForEachPi( p, pObj, i ) + Hop_ObjClearRef( pObj ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ObjClearRef( pObj ); + Hop_ManForEachPo( p, pObj, i ) + Hop_ObjClearRef( pObj ); + // set refs + Hop_ManForEachNode( p, pObj, i ) + { + Hop_ObjRef( Hop_ObjFanin0(pObj) ); + Hop_ObjRef( Hop_ObjFanin1(pObj) ); + } + Hop_ManForEachPo( p, pObj, i ) + Hop_ObjRef( Hop_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeMark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeMark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeCleanAndMark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeCleanAndMark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeCleanAndMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ConeCountAndMark_rec( Hop_Obj_t * pObj ) +{ + int Counter; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return 0; + Counter = 1 + Hop_ConeCountAndMark_rec( Hop_ObjFanin0(pObj) ) + + Hop_ConeCountAndMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeUnmark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeUnmark_rec( Hop_ObjFanin1(pObj) ); + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_DagSize( Hop_Obj_t * pObj ) +{ + int Counter; + Counter = Hop_ConeCountAndMark_rec( Hop_Regular(pObj) ); + Hop_ConeUnmark_rec( Hop_Regular(pObj) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_Transfer_rec( Hop_Man_t * pDest, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_Transfer_rec( pDest, Hop_ObjFanin0(pObj) ); + Hop_Transfer_rec( pDest, Hop_ObjFanin1(pObj) ); + pObj->pData = Hop_And( pDest, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pRoot, int nVars ) +{ + Hop_Obj_t * pObj; + int i; + // solve simple cases + if ( pSour == pDest ) + return pRoot; + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Hop_NotCond( Hop_ManConst1(pDest), Hop_IsComplement(pRoot) ); + // set the PI mapping + Hop_ManForEachPi( pSour, pObj, i ) + { + if ( i == nVars ) + break; + pObj->pData = Hop_IthVar(pDest, i); + } + // transfer and set markings + Hop_Transfer_rec( pDest, Hop_Regular(pRoot) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_Compose_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFunc, Hop_Obj_t * pVar ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( Hop_ObjIsMarkA(pObj) ) + return; + if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) + { + pObj->pData = pObj == pVar ? pFunc : pObj; + return; + } + Hop_Compose_rec( p, Hop_ObjFanin0(pObj), pFunc, pVar ); + Hop_Compose_rec( p, Hop_ObjFanin1(pObj), pFunc, pVar ); + pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ) +{ + // quit if the PI variable is not defined + if ( iVar >= Hop_ManPiNum(p) ) + { + printf( "Hop_Compose(): The PI variable %d is not defined.\n", iVar ); + return NULL; + } + // recursively perform composition + Hop_Compose_rec( p, Hop_Regular(pRoot), pFunc, Hop_ManPi(p, iVar) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hopMan.c b/src/aig/hop/hopMan.c new file mode 100644 index 00000000..18b8618b --- /dev/null +++ b/src/aig/hop/hopMan.c @@ -0,0 +1,162 @@ +/**CFile**************************************************************** + + FileName [hopMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopMan.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Hop_ManStart() +{ + Hop_Man_t * p; + // start the manager + p = ALLOC( Hop_Man_t, 1 ); + memset( p, 0, sizeof(Hop_Man_t) ); + // perform initializations + p->nTravIds = 1; + p->fRefCount = 1; + p->fCatchExor = 0; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + // prepare the internal memory manager + Hop_ManStartMemory( p ); + // create the constant node + p->pConst1 = Hop_ManFetchMemory( p ); + p->pConst1->Type = AIG_CONST1; + p->pConst1->fPhase = 1; + p->nCreated = 1; + // start the table + p->nTableSize = 10007; + p->pTable = ALLOC( Hop_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStop( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + // make sure the nodes have clean marks + pObj = Hop_ManConst1(p); + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachPi( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachPo( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachNode( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // print time + if ( p->time1 ) { PRT( "time1", p->time1 ); } + if ( p->time2 ) { PRT( "time2", p->time2 ); } +// Hop_TableProfile( p ); + if ( p->vChunks ) Hop_ManStopMemory( p ); + if ( p->vPis ) Vec_PtrFree( p->vPis ); + if ( p->vPos ) Vec_PtrFree( p->vPos ); + free( p->pTable ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCleanup( Hop_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pNode; + int i, nNodesOld; + assert( p->fRefCount ); + nNodesOld = Hop_ManNodeNum(p); + // collect roots of dangling nodes + vNodes = Vec_PtrAlloc( 100 ); + Hop_ManForEachNode( p, pNode, i ) + if ( Hop_ObjRefs(pNode) == 0 ) + Vec_PtrPush( vNodes, pNode ); + // recursively remove dangling nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + Hop_ObjDelete_rec( p, pNode ); + Vec_PtrFree( vNodes ); + return nNodesOld - Hop_ManNodeNum(p); +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManPrintStats( Hop_Man_t * p ) +{ + printf( "PI/PO = %d/%d. ", Hop_ManPiNum(p), Hop_ManPoNum(p) ); + printf( "A = %7d. ", Hop_ManAndNum(p) ); + printf( "X = %5d. ", Hop_ManExorNum(p) ); + printf( "Cre = %7d. ", p->nCreated ); + printf( "Del = %7d. ", p->nDeleted ); + printf( "Lev = %3d. ", Hop_ManCountLevels(p) ); + printf( "\n" ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hopMem.c b/src/aig/hop/hopMem.c new file mode 100644 index 00000000..0665470a --- /dev/null +++ b/src/aig/hop/hopMem.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [hopMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Memory management for the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes +#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStartMemory( Hop_Man_t * p ) +{ + p->vChunks = Vec_PtrAlloc( 128 ); + p->vPages = Vec_PtrAlloc( 128 ); +} + +/**Function************************************************************* + + Synopsis [Stops the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStopMemory( Hop_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( p->vChunks, pMemory, i ) + free( pMemory ); + Vec_PtrFree( p->vChunks ); + Vec_PtrFree( p->vPages ); + p->pListFree = NULL; +} + +/**Function************************************************************* + + Synopsis [Allocates additional memory for the nodes.] + + Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. + Records the pointer to the AIG manager in the -1 entry.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManAddMemory( Hop_Man_t * p ) +{ + char * pMemory; + int i, nBytes; + assert( sizeof(Hop_Obj_t) <= 64 ); + assert( p->pListFree == NULL ); +// assert( (Hop_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); + // allocate new memory page + nBytes = sizeof(Hop_Obj_t) * (1<vChunks, pMemory ); + // align memory at the 32-byte boundary + pMemory = pMemory + 64 - (((int)pMemory) & 63); + // remember the manager in the first entry + Vec_PtrPush( p->vPages, pMemory ); + // break the memory down into nodes + p->pListFree = (Hop_Obj_t *)pMemory; + for ( i = 1; i <= IVY_PAGE_MASK; i++ ) + { + *((char **)pMemory) = pMemory + sizeof(Hop_Obj_t); + pMemory += sizeof(Hop_Obj_t); + } + *((char **)pMemory) = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hopObj.c b/src/aig/hop/hopObj.c new file mode 100644 index 00000000..037203fb --- /dev/null +++ b/src/aig/hop/hopObj.c @@ -0,0 +1,228 @@ +/**CFile**************************************************************** + + FileName [hopObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Adding/removing objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + pObj = Hop_ManFetchMemory( p ); + pObj->Type = AIG_PI; + Vec_PtrPush( p->vPis, pObj ); + p->nObjs[AIG_PI]++; + p->nCreated++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary output with the given driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ) +{ + Hop_Obj_t * pObj; + pObj = Hop_ManFetchMemory( p ); + pObj->Type = AIG_PO; + Vec_PtrPush( p->vPos, pObj ); + // add connections + pObj->pFanin0 = pDriver; + if ( p->fRefCount ) + Hop_ObjRef( Hop_Regular(pDriver) ); + else + pObj->nRefs = Hop_ObjLevel( Hop_Regular(pDriver) ); + // update node counters of the manager + p->nObjs[AIG_PO]++; + p->nCreated++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ) +{ + Hop_Obj_t * pObj; + assert( !Hop_IsComplement(pGhost) ); + assert( Hop_ObjIsNode(pGhost) ); + assert( pGhost == &p->Ghost ); + // get memory for the new object + pObj = Hop_ManFetchMemory( p ); + pObj->Type = pGhost->Type; + // add connections + Hop_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); + // update node counters of the manager + p->nObjs[Hop_ObjType(pObj)]++; + p->nCreated++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // add the first fanin + pObj->pFanin0 = pFan0; + pObj->pFanin1 = pFan1; + // increment references of the fanins and add their fanouts + if ( p->fRefCount ) + { + if ( pFan0 != NULL ) + Hop_ObjRef( Hop_ObjFanin0(pObj) ); + if ( pFan1 != NULL ) + Hop_ObjRef( Hop_ObjFanin1(pObj) ); + } + else + pObj->nRefs = Hop_ObjLevelNew( pObj ); + // add the node to the structural hash table + Hop_TableInsert( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // remove connections + if ( pObj->pFanin0 != NULL ) + Hop_ObjDeref(Hop_ObjFanin0(pObj)); + if ( pObj->pFanin1 != NULL ) + Hop_ObjDeref(Hop_ObjFanin1(pObj)); + // remove the node from the structural hash table + Hop_TableDelete( p, pObj ); + // add the first fanin + pObj->pFanin0 = NULL; + pObj->pFanin1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( !Hop_ObjIsTerm(pObj) ); + assert( Hop_ObjRefs(pObj) == 0 ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // remove connections + Hop_ObjDisconnect( p, pObj ); + // remove PIs/POs from the arrays + if ( Hop_ObjIsPi(pObj) ) + Vec_PtrRemove( p->vPis, pObj ); + // free the node + Hop_ManRecycleMemory( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Deletes the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pFanin0, * pFanin1; + assert( !Hop_IsComplement(pObj) ); + if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) + return; + assert( Hop_ObjIsNode(pObj) ); + pFanin0 = Hop_ObjFanin0(pObj); + pFanin1 = Hop_ObjFanin1(pObj); + Hop_ObjDelete( p, pObj ); + if ( pFanin0 && !Hop_ObjIsNone(pFanin0) && Hop_ObjRefs(pFanin0) == 0 ) + Hop_ObjDelete_rec( p, pFanin0 ); + if ( pFanin1 && !Hop_ObjIsNone(pFanin1) && Hop_ObjRefs(pFanin1) == 0 ) + Hop_ObjDelete_rec( p, pFanin1 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hopOper.c b/src/aig/hop/hopOper.c new file mode 100644 index 00000000..a31ca0f2 --- /dev/null +++ b/src/aig/hop/hopOper.c @@ -0,0 +1,373 @@ +/**CFile**************************************************************** + + FileName [hopOper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedure to detect an EXOR gate +static inline int Hop_ObjIsExorType( Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) +{ + if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) + return 0; + p0 = Hop_Regular(p0); + p1 = Hop_Regular(p1); + if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) + return 0; + if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) + return 0; + if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Hop_ObjChild0(p0); + *ppFan1 = Hop_ObjChild1(p0); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns i-th elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ) +{ + int v; + for ( v = Hop_ManPiNum(p); v <= i; v++ ) + Hop_ObjCreatePi( p ); + assert( i < Vec_PtrSize(p->vPis) ); + return Hop_ManPi( p, i ); +} + +/**Function************************************************************* + + Synopsis [Perform one operation.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) +{ + if ( Type == AIG_AND ) + return Hop_And( p, p0, p1 ); + if ( Type == AIG_EXOR ) + return Hop_Exor( p, p0, p1 ); + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ + Hop_Obj_t * pGhost, * pResult; +// Hop_Obj_t * pFan0, * pFan1; + // check trivial cases + if ( p0 == p1 ) + return p0; + if ( p0 == Hop_Not(p1) ) + return Hop_Not(p->pConst1); + if ( Hop_Regular(p0) == p->pConst1 ) + return p0 == p->pConst1 ? p1 : Hop_Not(p->pConst1); + if ( Hop_Regular(p1) == p->pConst1 ) + return p1 == p->pConst1 ? p0 : Hop_Not(p->pConst1); + // check if it can be an EXOR gate +// if ( Hop_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) +// return Hop_Exor( p, pFan0, pFan1 ); + // check the table + pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_AND ); + if ( pResult = Hop_TableLookup( p, pGhost ) ) + return pResult; + return Hop_ObjCreate( p, pGhost ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ +/* + Hop_Obj_t * pGhost, * pResult; + // check trivial cases + if ( p0 == p1 ) + return Hop_Not(p->pConst1); + if ( p0 == Hop_Not(p1) ) + return p->pConst1; + if ( Hop_Regular(p0) == p->pConst1 ) + return Hop_NotCond( p1, p0 == p->pConst1 ); + if ( Hop_Regular(p1) == p->pConst1 ) + return Hop_NotCond( p0, p1 == p->pConst1 ); + // check the table + pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_EXOR ); + if ( pResult = Hop_TableLookup( p, pGhost ) ) + return pResult; + return Hop_ObjCreate( p, pGhost ); +*/ + return Hop_Or( p, Hop_And(p, p0, Hop_Not(p1)), Hop_And(p, Hop_Not(p0), p1) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ + return Hop_Not( Hop_And( p, Hop_Not(p0), Hop_Not(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ) +{ +/* + Hop_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; + int Count0, Count1; + // consider trivial cases + if ( p0 == Hop_Not(p1) ) + return Hop_Exor( p, pC, p0 ); + // other cases can be added + // implement the first MUX (F = C * x1 + C' * x0) + + // check for constants here!!! + + pTempA1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, p1, AIG_AND) ); + pTempA2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), p0, AIG_AND) ); + if ( pTempA1 && pTempA2 ) + { + pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempA1), Hop_Not(pTempA2), AIG_AND) ); + if ( pTemp ) return Hop_Not(pTemp); + } + Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); + // implement the second MUX (F' = C * x1' + C' * x0') + pTempB1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, Hop_Not(p1), AIG_AND) ); + pTempB2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), Hop_Not(p0), AIG_AND) ); + if ( pTempB1 && pTempB2 ) + { + pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempB1), Hop_Not(pTempB2), AIG_AND) ); + if ( pTemp ) return pTemp; + } + Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); + // compare and decide which one to implement + if ( Count0 >= Count1 ) + { + pTempA1 = pTempA1? pTempA1 : Hop_And(p, pC, p1); + pTempA2 = pTempA2? pTempA2 : Hop_And(p, Hop_Not(pC), p0); + return Hop_Or( p, pTempA1, pTempA2 ); + } + pTempB1 = pTempB1? pTempB1 : Hop_And(p, pC, Hop_Not(p1)); + pTempB2 = pTempB2? pTempB2 : Hop_And(p, Hop_Not(pC), Hop_Not(p0)); + return Hop_Not( Hop_Or( p, pTempB1, pTempB2 ) ); +*/ + return Hop_Or( p, Hop_And(p, pC, p1), Hop_And(p, Hop_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ) +{ + return Hop_Or( p, Hop_Or(p, Hop_And(p, pA, pB), Hop_And(p, pA, pC)), Hop_And(p, pB, pC) ); +} + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Multi_rec( Hop_Man_t * p, Hop_Obj_t ** ppObjs, int nObjs, Hop_Type_t Type ) +{ + Hop_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Hop_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Hop_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Hop_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Multi( Hop_Man_t * p, Hop_Obj_t ** pArgs, int nArgs, Hop_Type_t Type ) +{ + assert( Type == AIG_AND || Type == AIG_EXOR ); + assert( nArgs > 0 ); + return Hop_Multi_rec( p, pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ) +{ + int i; + assert( vPairs->nSize > 0 ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Hop_Not( Hop_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); + vPairs->nSize = vPairs->nSize/2; + return Hop_Not( Hop_Multi_rec( p, (Hop_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst1( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_And( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_Or( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_Exor( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hopTable.c b/src/aig/hop/hopTable.c new file mode 100644 index 00000000..4ce81982 --- /dev/null +++ b/src/aig/hop/hopTable.c @@ -0,0 +1,266 @@ +/**CFile**************************************************************** + + FileName [hopTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Structural hashing table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006. ] + + Revision [$Id: hopTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing the node +static unsigned long Hop_Hash( Hop_Obj_t * pObj, int TableSize ) +{ + unsigned long Key = Hop_ObjIsExor(pObj) * 1699; + Key ^= (long)Hop_ObjFanin0(pObj) * 7937; + Key ^= (long)Hop_ObjFanin1(pObj) * 2971; + Key ^= Hop_ObjFaninC0(pObj) * 911; + Key ^= Hop_ObjFaninC1(pObj) * 353; + return Key % TableSize; +} + +// returns the place where this node is stored (or should be stored) +static Hop_Obj_t ** Hop_TableFind( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + int i; + assert( Hop_ObjChild0(pObj) && Hop_ObjChild1(pObj) ); + assert( Hop_ObjChild0(pObj) < Hop_ObjChild1(pObj) ); + for ( i = Hop_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) + if ( p->pTable[i] == pObj ) + break; + return p->pTable + i; +} + +static void Hop_TableResize( Hop_Man_t * p ); +static unsigned int Cudd_PrimeAig( unsigned int p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ) +{ + int i; + assert( !Hop_IsComplement(pGhost) ); + assert( Hop_ObjChild0(pGhost) && Hop_ObjChild1(pGhost) ); + assert( Hop_ObjChild0(pGhost) < Hop_ObjChild1(pGhost) ); + if ( p->fRefCount && (!Hop_ObjRefs(Hop_ObjFanin0(pGhost)) || !Hop_ObjRefs(Hop_ObjFanin1(pGhost))) ) + return NULL; + for ( i = Hop_Hash(pGhost, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) + { + if ( Hop_ObjChild0(p->pTable[i]) == Hop_ObjChild0(pGhost) && + Hop_ObjChild1(p->pTable[i]) == Hop_ObjChild1(pGhost) && + Hop_ObjType(p->pTable[i]) == Hop_ObjType(pGhost) ) + return p->pTable[i]; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds the new node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t ** ppPlace; + assert( !Hop_IsComplement(pObj) ); + assert( Hop_TableLookup(p, pObj) == NULL ); + if ( p->nTableSize < 2 * Hop_ManNodeNum(p) ) + Hop_TableResize( p ); + ppPlace = Hop_TableFind( p, pObj ); + assert( *ppPlace == NULL ); + *ppPlace = pObj; +} + +/**Function************************************************************* + + Synopsis [Deletes the node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pEntry, ** ppPlace; + int i; + assert( !Hop_IsComplement(pObj) ); + ppPlace = Hop_TableFind( p, pObj ); + assert( *ppPlace == pObj ); // node should be in the table + *ppPlace = NULL; + // rehash the adjacent entries + i = ppPlace - p->pTable; + for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) + { + pEntry = p->pTable[i]; + p->pTable[i] = 0; + Hop_TableInsert( p, pEntry ); + } +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_TableCountEntries( Hop_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + Counter += (p->pTable[i] != NULL); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [Typically this procedure should not be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableResize( Hop_Man_t * p ) +{ + Hop_Obj_t ** pTableOld, ** ppPlace; + int nTableSizeOld, Counter, nEntries, e, clk; +clk = clock(); + // save the old table + pTableOld = p->pTable; + nTableSizeOld = p->nTableSize; + // get the new table + p->nTableSize = Cudd_PrimeAig( 5 * Hop_ManNodeNum(p) ); + p->pTable = ALLOC( Hop_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); + // rehash the entries from the old table + Counter = 0; + for ( e = 0; e < nTableSizeOld; e++ ) + { + if ( pTableOld[e] == 0 ) + continue; + Counter++; + // get the place where this entry goes in the table table + ppPlace = Hop_TableFind( p, pTableOld[e] ); + assert( *ppPlace == NULL ); // should not be in the table + *ppPlace = pTableOld[e]; + } + nEntries = Hop_ManNodeNum(p); +// assert( Counter == nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( pTableOld ); +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Hop_TableProfile( Hop_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + { + if ( p->pTable[i] ) + Counter++; + else if ( Counter ) + { + printf( "%d ", Counter ); + Counter = 0; + } + } +} + +/**Function******************************************************************** + + Synopsis [Returns the next prime >= p.] + + Description [Copied from CUDD, for stand-aloneness.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +unsigned int Cudd_PrimeAig( unsigned int p) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hopUtil.c b/src/aig/hop/hopUtil.c new file mode 100644 index 00000000..738caa4a --- /dev/null +++ b/src/aig/hop/hopUtil.c @@ -0,0 +1,502 @@ +/**CFile**************************************************************** + + FileName [hopUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Various procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManIncrementTravId( Hop_Man_t * p ) +{ + if ( p->nTravIds >= (1<<30)-1 ) + Hop_ManCleanData( p ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Sets the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManCleanData( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + p->nTravIds = 1; + Hop_ManConst1(p)->pData = NULL; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = NULL; + Hop_ManForEachPo( p, pObj, i ) + pObj->pData = NULL; + Hop_ManForEachNode( p, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCollectMulti_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + if ( pRoot != pObj && (Hop_IsComplement(pObj) || Hop_ObjIsPi(pObj) || Hop_ObjType(pRoot) != Hop_ObjType(pObj)) ) + { + Vec_PtrPushUnique(vSuper, pObj); + return; + } + Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); + Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCollectMulti( Hop_Obj_t * pRoot, Vec_Ptr_t * vSuper ) +{ + assert( !Hop_IsComplement(pRoot) ); + Vec_PtrClear( vSuper ); + Hop_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ObjIsMuxType( Hop_Obj_t * pNode ) +{ + Hop_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Hop_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Hop_ObjIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Hop_ObjFaninC0(pNode) || !Hop_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Hop_ObjFanin0(pNode); + pNode1 = Hop_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Hop_ObjIsAnd(pNode0) || !Hop_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1))) || + (Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1))) || + (Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1))) || + (Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1))); +} + + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are inputs of the EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) +{ + Hop_Obj_t * p0, * p1; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) ) + return 0; + if ( Hop_ObjIsExor(pObj) ) + { + *ppFan0 = Hop_ObjChild0(pObj); + *ppFan1 = Hop_ObjChild1(pObj); + return 1; + } + assert( Hop_ObjIsAnd(pObj) ); + p0 = Hop_ObjChild0(pObj); + p1 = Hop_ObjChild1(pObj); + if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) + return 0; + p0 = Hop_Regular(p0); + p1 = Hop_Regular(p1); + if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) + return 0; + if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) + return 0; + if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Hop_ObjChild0(p0); + *ppFan1 = Hop_ObjChild1(p0); + return 1; +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pNode, Hop_Obj_t ** ppNodeT, Hop_Obj_t ** ppNodeE ) +{ + Hop_Obj_t * pNode0, * pNode1; + assert( !Hop_IsComplement(pNode) ); + assert( Hop_ObjIsMuxType(pNode) ); + // get children + pNode0 = Hop_ObjFanin0(pNode); + pNode1 = Hop_ObjFanin1(pNode); + + // find the control variable + if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Hop_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + return Hop_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + return Hop_ObjChild1(pNode0);//pNode1->p2; + } + } + else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Hop_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + return Hop_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + return Hop_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Hop_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + return Hop_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + return Hop_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Hop_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + return Hop_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + return Hop_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Prints Verilog formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) +{ + Vec_Ptr_t * vSuper; + Hop_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; + int fCompl, i; + // store the complemented attribute + fCompl = Hop_IsComplement(pObj); + pObj = Hop_Regular(pObj); + // constant case + if ( Hop_ObjIsConst1(pObj) ) + { + fprintf( pFile, "%d", !fCompl ); + return; + } + // PI case + if ( Hop_ObjIsPi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "~" : "", pObj->pData ); + return; + } + // EXOR case + if ( Hop_ObjIsExor(pObj) ) + { + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry( vLevels, Level ); + Hop_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " ^ " ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; + } + // MUX case + if ( Hop_ObjIsMuxType(pObj) ) + { + if ( Hop_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) + { + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 ); + fprintf( pFile, " ^ " ); + Hop_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + else + { + pFaninC = Hop_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Hop_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); + fprintf( pFile, " ? " ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin1, fCompl), vLevels, Level+1 ); + fprintf( pFile, " : " ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Hop_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "|" : "&" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ) +{ + assert( !Hop_IsComplement(pObj) ); + printf( "Node %p : ", pObj ); + if ( Hop_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Hop_ObjIsPi(pObj) ) + printf( "PI" ); + else + printf( "AND( %p%s, %p%s )", + Hop_ObjFanin0(pObj), (Hop_ObjFaninC0(pObj)? "\'" : " "), + Hop_ObjFanin1(pObj), (Hop_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Hop_ObjRefs(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + printf( "PIs: " ); + Hop_ManForEachPi( p, pObj, i ) + printf( " %p", pObj ); + printf( "\n" ); + vNodes = Hop_ManDfs( p ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Hop_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj, * pConst1 = NULL; + int i, nDigits, Counter = 0; + if ( Hop_ManPoNum(p) == 0 ) + { + printf( "Hop_ManDumpBlif(): AIG manager does not have POs.\n" ); + return; + } + // collect nodes in the DFS order + vNodes = Hop_ManDfs( p ); + // assign IDs to objects + Hop_ManConst1(p)->pData = (void *)Counter++; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = (void *)Counter++; + Hop_ManForEachPo( p, pObj, i ) + pObj->pData = (void *)Counter++; + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pData = (void *)Counter++; + nDigits = Extra_Base10Log( Counter ); + // write the file + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# BLIF file written by procedure Hop_ManDumpBlif() in ABC\n" ); + fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); + fprintf( pFile, ".model test\n" ); + // write PIs + fprintf( pFile, ".inputs" ); + Hop_ManForEachPi( p, pObj, i ) + fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); + fprintf( pFile, "\n" ); + // write POs + fprintf( pFile, ".outputs" ); + Hop_ManForEachPo( p, pObj, i ) + fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); + fprintf( pFile, "\n" ); + // write nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", + nDigits, (int)Hop_ObjFanin0(pObj)->pData, + nDigits, (int)Hop_ObjFanin1(pObj)->pData, + nDigits, (int)pObj->pData ); + fprintf( pFile, "%d%d 1\n", !Hop_ObjFaninC0(pObj), !Hop_ObjFaninC1(pObj) ); + } + // write POs + Hop_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, ".names n%0*d n%0*d\n", + nDigits, (int)Hop_ObjFanin0(pObj)->pData, + nDigits, (int)pObj->pData ); + fprintf( pFile, "%d 1\n", !Hop_ObjFaninC0(pObj) ); + if ( Hop_ObjIsConst1(Hop_ObjFanin0(pObj)) ) + pConst1 = Hop_ManConst1(p); + } + if ( pConst1 ) + fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)pConst1->pData ); + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + Vec_PtrFree( vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/hop_.c b/src/aig/hop/hop_.c new file mode 100644 index 00000000..468413fa --- /dev/null +++ b/src/aig/hop/hop_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [ivy_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/hop/module.make b/src/aig/hop/module.make new file mode 100644 index 00000000..b06d91fd --- /dev/null +++ b/src/aig/hop/module.make @@ -0,0 +1,9 @@ +SRC += src/aig/hop/hopBalance.c \ + src/aig/hop/hopCheck.c \ + src/aig/hop/hopDfs.c \ + src/aig/hop/hopMan.c \ + src/aig/hop/hopMem.c \ + src/aig/hop/hopObj.c \ + src/aig/hop/hopOper.c \ + src/aig/hop/hopTable.c \ + src/aig/hop/hopUtil.c diff --git a/src/aig/ivy/attr.h b/src/aig/ivy/attr.h new file mode 100644 index 00000000..5a760239 --- /dev/null +++ b/src/aig/ivy/attr.h @@ -0,0 +1,414 @@ +/**CFile**************************************************************** + + FileName [attr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network attributes.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: attr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __ATTR_H__ +#define __ATTR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Attr_ManStruct_t_ Attr_Man_t; +struct Attr_ManStruct_t_ +{ + // attribute info + int nAttrSize; // the size of each attribute in bytes + Extra_MmFixed_t * pManMem; // memory manager for attributes + int nAttrs; // the number of attributes allocated + void ** pAttrs; // the array of attributes + int fUseInt; // uses integer attributes + // attribute specific info + void * pManAttr; // the manager for this attribute + void (*pFuncFreeMan) (void *); // the procedure to call to free attribute-specific manager + void (*pFuncFreeObj) (void *, void *); // the procedure to call to free attribute-specific data +}; + +// at any time, an attribute of the given ID can be +// - not available (p->nAttrs < Id) +// - available but not allocated (p->nAttrs >= Id && p->pAttrs[Id] == NULL) +// - available and allocated (p->nAttrs >= Id && p->pAttrs[Id] != NULL) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the attribute manager.] + + Description [The manager is simple if it does not need memory manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManAlloc( int nAttrSize, int fManMem ) +{ + Attr_Man_t * p; + p = ALLOC( Attr_Man_t, 1 ); + memset( p, 0, sizeof(Attr_Man_t) ); + p->nAttrSize = nAttrSize; + if ( fManMem ) + p->pManMem = Extra_MmFixedStart( nAttrSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartInt( int nAttrs ) +{ + Attr_Man_t * p; + p = Attr_ManAlloc( sizeof(int), 0 ); + p->nAttrs = nAttrs; + p->pAttrs = (void **)ALLOC( int, nAttrs ); + memset( (int *)p->pAttrs, 0, sizeof(int) * nAttrs ); + p->fUseInt = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartPtr( int nAttrs ) +{ + Attr_Man_t * p; + p = Attr_ManAlloc( sizeof(void *), 0 ); + p->nAttrs = nAttrs; + p->pAttrs = ALLOC( void *, nAttrs ); + memset( p->pAttrs, 0, sizeof(void *) * nAttrs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for the fixed entry size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartPtrMem( int nAttrs, int nAttrSize ) +{ + Attr_Man_t * p; + int i; + p = Attr_ManAlloc( nAttrSize, 1 ); + p->nAttrs = nAttrs; + p->pAttrs = ALLOC( void *, nAttrs ); + for ( i = 0; i < p->nAttrs; i++ ) + { + p->pAttrs[i] = Extra_MmFixedEntryFetch( p->pManMem ); + memset( p->pAttrs[i], 0, nAttrSize ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Stop the attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManStop( Attr_Man_t * p ) +{ + // free the attributes of objects + if ( p->pFuncFreeObj ) + { + int i; + if ( p->fUseInt ) + { + for ( i = 0; i < p->nAttrs; i++ ) + if ( ((int *)p->pAttrs)[i] ) + p->pFuncFreeObj( p->pManAttr, (void *)((int *)p->pAttrs)[i] ); + } + else + { + for ( i = 0; i < p->nAttrs; i++ ) + if ( p->pAttrs[i] ) + p->pFuncFreeObj( p->pManAttr, p->pAttrs[i] ); + } + } + // free the attribute manager + if ( p->pManAttr && p->pFuncFreeMan ) + p->pFuncFreeMan( p->pManAttr ); + // free the memory manager + if ( p->pManMem ) + Extra_MmFixedStop( p->pManMem, 0 ); + // free the attribute manager + FREE( p->pAttrs ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Reads the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Attr_ManReadAttrInt( Attr_Man_t * p, int Id ) +{ + assert( p->fUseInt ); + if ( Id >= p->nAttrs ) + return 0; + return ((int *)p->pAttrs)[Id]; +} + +/**Function************************************************************* + + Synopsis [Reads the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Attr_ManReadAttrPtr( Attr_Man_t * p, int Id ) +{ + assert( !p->fUseInt ); + if ( Id >= p->nAttrs ) + return NULL; + return p->pAttrs[Id]; +} + +/**Function************************************************************* + + Synopsis [Writes the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManWriteAttrInt( Attr_Man_t * p, int Id, int Attr ) +{ + assert( p->fUseInt ); + ((int *)p->pAttrs)[Id] = Attr; +} + +/**Function************************************************************* + + Synopsis [Writes the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManWriteAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) +{ + assert( !p->fUseInt ); + assert( p->pManMem == NULL ); + p->pAttrs[Id] = pAttr; +} + +/**Function************************************************************* + + Synopsis [Returns or creates the pointer to the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Attr_ManFetchSpotInt( Attr_Man_t * p, int Id ) +{ + assert( p->fUseInt ); + if ( Id >= p->nAttrs ) + { + // save the old size + int i, nAttrsOld = p->nAttrs; + // get the new size + p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; + p->pAttrs = realloc( p->pAttrs, sizeof(int) * p->nAttrs ); + // fill in the empty spots + for ( i = nAttrsOld; i < p->nAttrs; i++ ) + ((int *)p->pAttrs)[Id] = 0; + } + return ((int *)p->pAttrs) + Id; +} + +/**Function************************************************************* + + Synopsis [Returns or creates the pointer to the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void ** Attr_ManFetchSpotPtr( Attr_Man_t * p, int Id ) +{ + assert( !p->fUseInt ); + if ( Id >= p->nAttrs ) + { + // save the old size + int i, nAttrsOld = p->nAttrs; + // get the new size + p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; + p->pAttrs = realloc( p->pAttrs, sizeof(void *) * p->nAttrs ); + // fill in the empty spots + for ( i = nAttrsOld; i < p->nAttrs; i++ ) + p->pAttrs[Id] = NULL; + } + // if memory manager is available but entry is not created, create it + if ( p->pManMem && p->pAttrs[Id] != NULL ) + { + p->pAttrs[Id] = Extra_MmFixedEntryFetch( p->pManMem ); + memset( p->pAttrs[Id], 0, p->nAttrSize ); + } + return p->pAttrs + Id; +} + + +/**Function************************************************************* + + Synopsis [Returns or creates the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Attr_ManFetchAttrInt( Attr_Man_t * p, int Id ) +{ + return *Attr_ManFetchSpotInt( p, Id ); +} + +/**Function************************************************************* + + Synopsis [Returns or creates the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Attr_ManFetchAttrPtr( Attr_Man_t * p, int Id ) +{ + return *Attr_ManFetchSpotPtr( p, Id ); +} + +/**Function************************************************************* + + Synopsis [Sets the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManSetAttrInt( Attr_Man_t * p, int Id, int Attr ) +{ + *Attr_ManFetchSpotInt( p, Id ) = Attr; +} + +/**Function************************************************************* + + Synopsis [Sets the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManSetAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) +{ + assert( p->pManMem == NULL ); + *Attr_ManFetchSpotPtr( p, Id ) = pAttr; +} + + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/ivy/ivy.h b/src/aig/ivy/ivy.h new file mode 100644 index 00000000..91d4d767 --- /dev/null +++ b/src/aig/ivy/ivy.h @@ -0,0 +1,555 @@ +/**CFile**************************************************************** + + FileName [ivy.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IVY_H__ +#define __IVY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_Man_t_ Ivy_Man_t; +typedef struct Ivy_Obj_t_ Ivy_Obj_t; +typedef int Ivy_Edge_t; +typedef struct Ivy_FraigParams_t_ Ivy_FraigParams_t; + +// object types +typedef enum { + IVY_NONE, // 0: non-existent object + IVY_PI, // 1: primary input (and constant 1 node) + IVY_PO, // 2: primary output + IVY_ASSERT, // 3: assertion + IVY_LATCH, // 4: sequential element + IVY_AND, // 5: AND node + IVY_EXOR, // 6: EXOR node + IVY_BUF, // 7: buffer (temporary) + IVY_VOID // 8: unused object +} Ivy_Type_t; + +// latch initial values +typedef enum { + IVY_INIT_NONE, // 0: not a latch + IVY_INIT_0, // 1: zero + IVY_INIT_1, // 2: one + IVY_INIT_DC // 3: don't-care +} Ivy_Init_t; + +// the AIG node +struct Ivy_Obj_t_ // 24 bytes (32-bit) or 32 bytes (64-bit) // 10 words - 16 words +{ + int Id; // integer ID + int TravId; // traversal ID + unsigned Type : 4; // object type + unsigned fMarkA : 1; // multipurpose mask + unsigned fMarkB : 1; // multipurpose mask + unsigned fExFan : 1; // set to 1 if last fanout added is EXOR + unsigned fPhase : 1; // value under 000...0 pattern + unsigned fFailTfo : 1; // the TFO of the failed node + unsigned Init : 2; // latch initial value + unsigned Level : 21; // logic level + int nRefs; // reference counter + Ivy_Obj_t * pFanin0; // fanin + Ivy_Obj_t * pFanin1; // fanin + Ivy_Obj_t * pFanout; // fanout + Ivy_Obj_t * pNextFan0; // next fanout of the first fanin + Ivy_Obj_t * pNextFan1; // next fanout of the second fanin + Ivy_Obj_t * pPrevFan0; // prev fanout of the first fanin + Ivy_Obj_t * pPrevFan1; // prev fanout of the second fanin + Ivy_Obj_t * pEquiv; // equivalent node +}; + +// the AIG manager +struct Ivy_Man_t_ +{ + // AIG nodes + Vec_Ptr_t * vPis; // the array of PIs + Vec_Ptr_t * vPos; // the array of POs + Vec_Ptr_t * vBufs; // the array of buffers + Vec_Ptr_t * vObjs; // the array of objects + Ivy_Obj_t * pConst1; // the constant 1 node + Ivy_Obj_t Ghost; // the ghost node + // AIG node counters + int nObjs[IVY_VOID];// the number of objects by type + int nCreated; // the number of created objects + int nDeleted; // the number of deleted objects + // stuctural hash table + int * pTable; // structural hash table + int nTableSize; // structural hash table size + // various data members + int fCatchExor; // set to 1 to detect EXORs + int nTravIds; // the traversal ID + int nLevelMax; // the maximum level + Vec_Int_t * vRequired; // required times + int fFanout; // fanout is allocated + void * pData; // the temporary data + void * pCopy; // the temporary data + Ivy_Man_t * pHaig; // history AIG if present + int nClassesSkip; // the number of skipped classes + // memory management + Vec_Ptr_t * vChunks; // allocated memory pieces + Vec_Ptr_t * vPages; // memory pages used by nodes + Ivy_Obj_t * pListFree; // the list of free nodes + // timing statistics + int time1; + int time2; +}; + +struct Ivy_FraigParams_t_ +{ + int nSimWords; // the number of words in the simulation info + double dSimSatur; // the ratio of refined classes when saturation is reached + int fPatScores; // enables simulation pattern scoring + int MaxScore; // max score after which resimulation is used + double dActConeRatio; // the ratio of cone to be bumped + double dActConeBumpMax; // the largest bump in activity + int fProve; // prove the miter outputs + int fVerbose; // verbose output + int fDoSparse; // skip sparse functions + int nBTLimitNode; // conflict limit at a node + int nBTLimitMiter; // conflict limit at an output +// int nBTLimitGlobal; // conflict limit global +// int nInsLimitNode; // inspection limit at a node +// int nInsLimitMiter; // inspection limit at an output +// int nInsLimitGlobal; // inspection limit global +}; + + +#define IVY_CUT_LIMIT 256 +#define IVY_CUT_INPUT 6 + +typedef struct Ivy_Cut_t_ Ivy_Cut_t; +struct Ivy_Cut_t_ +{ + short nSize; + short nSizeMax; + int pArray[IVY_CUT_INPUT]; + unsigned uHash; +}; + +typedef struct Ivy_Store_t_ Ivy_Store_t; +struct Ivy_Store_t_ +{ + int nCuts; + int nCutsM; + int nCutsMax; + int fSatur; + Ivy_Cut_t pCuts[IVY_CUT_LIMIT]; // storage for cuts +}; + +#define IVY_LEAF_MASK 255 +#define IVY_LEAF_BITS 8 + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_MIN(a,b) (((a) < (b))? (a) : (b)) +#define IVY_MAX(a,b) (((a) > (b))? (a) : (b)) + +static inline int Ivy_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Ivy_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Ivy_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Ivy_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Ivy_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } + +static inline Ivy_Obj_t * Ivy_Regular( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) & ~01); } +static inline Ivy_Obj_t * Ivy_Not( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ 01); } +static inline Ivy_Obj_t * Ivy_NotCond( Ivy_Obj_t * p, int c ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ (c)); } +static inline int Ivy_IsComplement( Ivy_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } + +static inline Ivy_Obj_t * Ivy_ManConst0( Ivy_Man_t * p ) { return Ivy_Not(p->pConst1); } +static inline Ivy_Obj_t * Ivy_ManConst1( Ivy_Man_t * p ) { return p->pConst1; } +static inline Ivy_Obj_t * Ivy_ManGhost( Ivy_Man_t * p ) { return &p->Ghost; } +static inline Ivy_Obj_t * Ivy_ManPi( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPis, i); } +static inline Ivy_Obj_t * Ivy_ManPo( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPos, i); } +static inline Ivy_Obj_t * Ivy_ManObj( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vObjs, i); } + +static inline Ivy_Edge_t Ivy_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } +static inline int Ivy_EdgeId( Ivy_Edge_t Edge ) { return Edge >> 1; } +static inline int Ivy_EdgeIsComplement( Ivy_Edge_t Edge ) { return Edge & 1; } +static inline Ivy_Edge_t Ivy_EdgeRegular( Ivy_Edge_t Edge ) { return (Edge >> 1) << 1; } +static inline Ivy_Edge_t Ivy_EdgeNot( Ivy_Edge_t Edge ) { return Edge ^ 1; } +static inline Ivy_Edge_t Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond ) { return Edge ^ fCond; } +static inline Ivy_Edge_t Ivy_EdgeFromNode( Ivy_Obj_t * pNode ) { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) ); } +static inline Ivy_Obj_t * Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); } + +static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << IVY_LEAF_BITS) | Lat; } +static inline int Ivy_LeafId( int Leaf ) { return Leaf >> IVY_LEAF_BITS; } +static inline int Ivy_LeafLat( int Leaf ) { return Leaf & IVY_LEAF_MASK; } + +static inline int Ivy_ManPiNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PI]; } +static inline int Ivy_ManPoNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PO]; } +static inline int Ivy_ManAssertNum( Ivy_Man_t * p ) { return p->nObjs[IVY_ASSERT]; } +static inline int Ivy_ManLatchNum( Ivy_Man_t * p ) { return p->nObjs[IVY_LATCH]; } +static inline int Ivy_ManAndNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]; } +static inline int Ivy_ManExorNum( Ivy_Man_t * p ) { return p->nObjs[IVY_EXOR]; } +static inline int Ivy_ManBufNum( Ivy_Man_t * p ) { return p->nObjs[IVY_BUF]; } +static inline int Ivy_ManObjNum( Ivy_Man_t * p ) { return p->nCreated - p->nDeleted; } +static inline int Ivy_ManObjIdMax( Ivy_Man_t * p ) { return Vec_PtrSize(p->vObjs)-1; } +static inline int Ivy_ManNodeNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR];} +static inline int Ivy_ManHashObjNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH]; } +static inline int Ivy_ManGetCost( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; } + +static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { return pObj->Type; } +static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { return pObj->Init; } +static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { return pObj->Id == 0; } +static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { return pObj->Id < 0; } +static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_NONE; } +static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI; } +static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO; } +static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_ASSERT; } +static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND; } +static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_EXOR; } +static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_BUF; } +static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; } +static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; } +static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; } + +static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 0; } + +static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } +static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } +static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } +static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds - 1); } + +static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { return pObj->Id; } +static inline int Ivy_ObjTravId( Ivy_Obj_t * pObj ) { return pObj->TravId; } +static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { return pObj->fExFan; } +static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; } +static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; } +static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin0); } +static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin1); } +static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin0); } +static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin1); } +static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Ivy_Obj_t * Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL; } +static inline Ivy_Obj_t * Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL; } +static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { return pObj->Level; } +static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); } +static inline int Ivy_ObjFaninPhase( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj)? !Ivy_Regular(pObj)->fPhase : pObj->fPhase; } + +static inline void Ivy_ObjClean( Ivy_Obj_t * pObj ) +{ + int IdSaved = pObj->Id; + memset( pObj, 0, sizeof(Ivy_Obj_t) ); + pObj->Id = IdSaved; +} +static inline void Ivy_ObjOverwrite( Ivy_Obj_t * pBase, Ivy_Obj_t * pData ) +{ + int IdSaved = pBase->Id; + memcpy( pBase, pData, sizeof(Ivy_Obj_t) ); + pBase->Id = IdSaved; +} +static inline int Ivy_ObjWhatFanin( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanin ) +{ + if ( Ivy_ObjFanin0(pObj) == pFanin ) return 0; + if ( Ivy_ObjFanin1(pObj) == pFanin ) return 1; + assert(0); return -1; +} +static inline int Ivy_ObjFanoutC( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + if ( Ivy_ObjFanin0(pFanout) == pObj ) return Ivy_ObjFaninC0(pObj); + if ( Ivy_ObjFanin1(pFanout) == pObj ) return Ivy_ObjFaninC1(pObj); + assert(0); return -1; +} + +// create the ghost of the new node +static inline Ivy_Obj_t * Ivy_ObjCreateGhost( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type, Ivy_Init_t Init ) +{ + Ivy_Obj_t * pGhost, * pTemp; + assert( Type != IVY_AND || !Ivy_ObjIsConst1(Ivy_Regular(p0)) ); + assert( p1 == NULL || !Ivy_ObjIsConst1(Ivy_Regular(p1)) ); + assert( Type == IVY_PI || Ivy_Regular(p0) != Ivy_Regular(p1) ); + assert( Type != IVY_LATCH || !Ivy_IsComplement(p0) ); +// assert( p1 == NULL || (!Ivy_ObjIsLatch(Ivy_Regular(p0)) || !Ivy_ObjIsLatch(Ivy_Regular(p1))) ); + pGhost = Ivy_ManGhost(p); + pGhost->Type = Type; + pGhost->Init = Init; + pGhost->pFanin0 = p0; + pGhost->pFanin1 = p1; + if ( p1 && Ivy_ObjFaninId0(pGhost) > Ivy_ObjFaninId1(pGhost) ) + pTemp = pGhost->pFanin0, pGhost->pFanin0 = pGhost->pFanin1, pGhost->pFanin1 = pTemp; + return pGhost; +} + +// get the complemented initial state +static Ivy_Init_t Ivy_InitNotCond( Ivy_Init_t Init, int fCompl ) +{ + assert( Init != IVY_INIT_NONE ); + if ( fCompl == 0 ) + return Init; + if ( Init == IVY_INIT_0 ) + return IVY_INIT_1; + if ( Init == IVY_INIT_1 ) + return IVY_INIT_0; + return IVY_INIT_DC; +} + +// get the initial state after forward retiming over AND gate +static Ivy_Init_t Ivy_InitAnd( Ivy_Init_t InitA, Ivy_Init_t InitB ) +{ + assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); + if ( InitA == IVY_INIT_0 || InitB == IVY_INIT_0 ) + return IVY_INIT_0; + if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) + return IVY_INIT_DC; + return IVY_INIT_1; +} + +// get the initial state after forward retiming over EXOR gate +static Ivy_Init_t Ivy_InitExor( Ivy_Init_t InitA, Ivy_Init_t InitB ) +{ + assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); + if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( InitA == IVY_INIT_0 && InitB == IVY_INIT_1 ) + return IVY_INIT_1; + if ( InitA == IVY_INIT_1 && InitB == IVY_INIT_0 ) + return IVY_INIT_1; + return IVY_INIT_0; +} + +// internal memory manager +static inline Ivy_Obj_t * Ivy_ManFetchMemory( Ivy_Man_t * p ) +{ + extern void Ivy_ManAddMemory( Ivy_Man_t * p ); + Ivy_Obj_t * pTemp; + if ( p->pListFree == NULL ) + Ivy_ManAddMemory( p ); + pTemp = p->pListFree; + p->pListFree = *((Ivy_Obj_t **)pTemp); + memset( pTemp, 0, sizeof(Ivy_Obj_t) ); + return pTemp; +} +static inline void Ivy_ManRecycleMemory( Ivy_Man_t * p, Ivy_Obj_t * pEntry ) +{ + pEntry->Type = IVY_NONE; // distinquishes dead node from live node + *((Ivy_Obj_t **)pEntry) = p->pListFree; + p->pListFree = pEntry; +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Ivy_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPis, pObj, i ) +// iterator over the primary outputs +#define Ivy_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Ivy_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else +// iterator over the combinational inputs +#define Ivy_ManForEachCi( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCi(pObj) ) {} else +// iterator over the combinational outputs +#define Ivy_ManForEachCo( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCo(pObj) ) {} else +// iterator over logic nodes (AND and EXOR gates) +#define Ivy_ManForEachNode( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsNode(pObj) ) {} else +// iterator over logic latches +#define Ivy_ManForEachLatch( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsLatch(pObj) ) {} else +// iterator over the nodes whose IDs are stored in the array +#define Ivy_ManForEachNodeVec( p, vIds, pObj, i ) \ + for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Ivy_ManObj(p, Vec_IntEntry(vIds,i))); i++ ) +// iterator over the fanouts of an object +#define Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, i ) \ + for ( i = 0, Ivy_ObjCollectFanouts(p, pObj, vArray); \ + i < Vec_PtrSize(vArray) && ((pFanout) = Vec_PtrEntry(vArray,i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== ivyBalance.c ========================================================*/ +extern Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ); +extern Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ); +/*=== ivyCanon.c ========================================================*/ +extern Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); +/*=== ivyCheck.c ========================================================*/ +extern int Ivy_ManCheck( Ivy_Man_t * p ); +extern int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ); +extern int Ivy_ManCheckFanouts( Ivy_Man_t * p ); +extern int Ivy_ManCheckChoices( Ivy_Man_t * p ); +/*=== ivyCut.c ==========================================================*/ +extern void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ); +extern Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); +/*=== ivyDfs.c ==========================================================*/ +extern Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ); +extern Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ); +extern void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ); +extern Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ); +extern Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ); +extern int Ivy_ManIsAcyclic( Ivy_Man_t * p ); +extern int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ); +/*=== ivyDsd.c ==========================================================*/ +extern int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ); +extern void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ); +extern unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ); +extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); +extern Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ); +/*=== ivyFanout.c ==========================================================*/ +extern void Ivy_ManStartFanout( Ivy_Man_t * p ); +extern void Ivy_ManStopFanout( Ivy_Man_t * p ); +extern void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); +extern void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); +extern void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ); +extern void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ); +extern Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +/*=== ivyFastMap.c =============================================================*/ +extern void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ); +extern void Ivy_FastMapStop( Ivy_Man_t * pAig ); +extern void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ); +extern void Ivy_FastMapReverseLevel( Ivy_Man_t * pAig ); +/*=== ivyFraig.c ==========================================================*/ +extern int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ); +extern Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +extern Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +extern void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ); +/*=== ivyHaig.c ==========================================================*/ +extern void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ); +extern void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ); +extern void Ivy_ManHaigStop( Ivy_Man_t * p ); +extern void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ); +extern void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ); +extern void Ivy_ManHaigSimulate( Ivy_Man_t * p ); +/*=== ivyIsop.c ==========================================================*/ +extern int Ivy_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vCover, int fTryBoth ); +/*=== ivyMan.c ==========================================================*/ +extern Ivy_Man_t * Ivy_ManStart(); +extern Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ); +extern Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ); +extern Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ); +extern void Ivy_ManStop( Ivy_Man_t * p ); +extern int Ivy_ManCleanup( Ivy_Man_t * p ); +extern int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ); +extern void Ivy_ManPrintStats( Ivy_Man_t * p ); +extern void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ); +/*=== ivyMem.c ==========================================================*/ +extern void Ivy_ManStartMemory( Ivy_Man_t * p ); +extern void Ivy_ManStopMemory( Ivy_Man_t * p ); +/*=== ivyMulti.c ==========================================================*/ +extern Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_Multi1( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol ); +/*=== ivyObj.c ==========================================================*/ +extern Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ); +extern Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ); +extern Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ); +extern void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ); +extern void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ); +extern void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); +extern void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); +extern void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ); +extern void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ); +/*=== ivyOper.c =========================================================*/ +extern Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ); +extern Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ); +extern Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ); +extern Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); +/*=== ivyResyn.c =========================================================*/ +extern Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); +extern Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); +extern Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ); +/*=== ivyRewrite.c =========================================================*/ +extern int Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); +extern int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); +extern int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ); +/*=== ivySeq.c =========================================================*/ +extern int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ); +/*=== ivyShow.c =========================================================*/ +extern void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); +/*=== ivyTable.c ========================================================*/ +extern Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ); +extern int Ivy_TableCountEntries( Ivy_Man_t * p ); +extern void Ivy_TableProfile( Ivy_Man_t * p ); +/*=== ivyUtil.c =========================================================*/ +extern void Ivy_ManIncrementTravId( Ivy_Man_t * p ); +extern void Ivy_ManCleanTravId( Ivy_Man_t * p ); +extern unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ); +extern void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ); +extern Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ); +extern int Ivy_ManLevels( Ivy_Man_t * p ); +extern void Ivy_ManResetLevels( Ivy_Man_t * p ); +extern int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ); +extern int Ivy_ObjIsMuxType( Ivy_Obj_t * pObj ); +extern Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObjT, Ivy_Obj_t ** ppObjE ); +extern Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ); +extern void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ); +extern void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/ivy/ivyBalance.c b/src/aig/ivy/ivyBalance.c new file mode 100644 index 00000000..5627039a --- /dev/null +++ b/src/aig/ivy/ivyBalance.c @@ -0,0 +1,404 @@ +/**CFile**************************************************************** + + FileName [ivyBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Algebraic AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); +static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); +static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); +static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); +static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs algebraic balancing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ) +{ + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj, * pDriver; + Vec_Vec_t * vStore; + int i, NewNodeId; + // clean the old manager + Ivy_ManCleanTravId( p ); + // create the new manager + pNew = Ivy_ManStart(); + // map the nodes + Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) ); + Ivy_ManForEachPi( p, pObj, i ) + pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) ); + // if HAIG is defined, trasfer the pointers to the PIs/latches +// if ( p->pHaig ) +// Ivy_ManHaigTrasfer( p, pNew ); + // balance the AIG + vStore = Vec_VecAlloc( 50 ); + Ivy_ManForEachPo( p, pObj, i ) + { + pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) ); + NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel ); + NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) ); + Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) ); + } + Vec_VecFree( vStore ); + if ( i = Ivy_ManCleanup( pNew ) ) + { +// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); + } + // check the resulting AIG + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManBalance(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) +{ + int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the ID of new node constructed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) +{ + Ivy_Obj_t * pObjNew; + Vec_Ptr_t * vSuper; + int i, NewNodeId; + assert( !Ivy_IsComplement(pObjOld) ); + assert( !Ivy_ObjIsBuf(pObjOld) ); + // return if the result is known + if ( Ivy_ObjIsConst1(pObjOld) ) + return pObjOld->TravId; + if ( pObjOld->TravId ) + return pObjOld->TravId; + assert( Ivy_ObjIsNode(pObjOld) ); + // get the implication supergate + vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level ); + if ( vSuper->nSize == 0 ) + { // it means that the supergate contains two nodes in the opposite polarity + pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) ); + return pObjOld->TravId; + } + if ( vSuper->nSize < 2 ) + printf( "BUG!\n" ); + // for each old node, derive the new well-balanced node + for ( i = 0; i < vSuper->nSize; i++ ) + { + NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); + NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(vSuper->pArray[i]) ); + vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId ); + } + // build the supergate + pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel ); + vSuper->nSize = 0; + // make sure the balanced node is not assigned + assert( pObjOld->TravId == 0 ); + pObjOld->TravId = Ivy_EdgeFromNode( pObjNew ); +// assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level ); + return pObjOld->TravId; +} + +/**Function************************************************************* + + Synopsis [Builds implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ) +{ + Ivy_Obj_t * pObj1, * pObj2; + int LeftBound; + assert( vSuper->nSize > 1 ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, Ivy_NodeCompareLevelsDecrease ); + // balance the nodes + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR ); + // pull out the last two nodes + pObj1 = Vec_PtrPop(vSuper); + pObj2 = Vec_PtrPop(vSuper); + Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) ); + } + return Vec_PtrEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Ivy_Regular(pObj)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Ivy_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1) ) + { + Vec_PtrPush( vSuper, pObj ); + Ivy_Regular(pObj)->fMarkB = 1; + return 0; + } + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper ); + RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Ivy_IsComplement(pObj) ); + // extend the storage + if ( Vec_VecSize( vStore ) <= Level ) + Vec_VecPush( vStore, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStore, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + Ivy_Regular(pObj)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Ivy_Obj_t * pObjRight, * pObjLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pObjRight = Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pObjLeft = Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level ) + break; + } + Current++; + // get the node, for which the equality holds + pObjLeft = Vec_PtrEntry( vSuper, Current ); + assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) +{ + Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); + pObj2 = Vec_PtrEntry( vSuper, RightBound ); + if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pObj3 = Vec_PtrEntry( vSuper, i ); + if ( Ivy_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE ); + if ( Ivy_TableLookup( p, pGhost ) ) + { + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pObj1, * pObj2; + int i; + if ( Vec_PtrPushUnique(vStore, pObj) ) + return; + // find the p of the node + for ( i = vStore->nSize-1; i > 0; i-- ) + { + pObj1 = vStore->pArray[i ]; + pObj2 = vStore->pArray[i-1]; + if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level ) + break; + vStore->pArray[i ] = pObj2; + vStore->pArray[i-1] = pObj1; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyCanon.c b/src/aig/ivy/ivyCanon.c new file mode 100644 index 00000000..5768b87e --- /dev/null +++ b/src/aig/ivy/ivyCanon.c @@ -0,0 +1,144 @@ +/**CFile**************************************************************** + + FileName [ivyCanon.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Finding canonical form of objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCanon.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Ivy_Obj_t * Ivy_TableLookupPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1, int fCompl0, int fCompl1, Ivy_Type_t Type ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) +{ + Ivy_Obj_t * pResult, * pLat0, * pLat1; + Ivy_Init_t Init, Init0, Init1; + int fCompl0, fCompl1; + Ivy_Type_t Type; + assert( Ivy_ObjIsNode(pGhost) ); + assert( Ivy_ObjIsAnd(pGhost) || (!Ivy_ObjFaninC0(pGhost) && !Ivy_ObjFaninC1(pGhost)) ); + assert( Ivy_ObjFaninId0(pGhost) != 0 && Ivy_ObjFaninId1(pGhost) != 0 ); + // consider the case when the pair is canonical + if ( !Ivy_ObjIsLatch(Ivy_ObjFanin0(pGhost)) || !Ivy_ObjIsLatch(Ivy_ObjFanin1(pGhost)) ) + { + if ( pResult = Ivy_TableLookup( p, pGhost ) ) + return pResult; + return Ivy_ObjCreate( p, pGhost ); + } + /// remember the latches + pLat0 = Ivy_ObjFanin0(pGhost); + pLat1 = Ivy_ObjFanin1(pGhost); + // remember type and compls + Type = Ivy_ObjType(pGhost); + fCompl0 = Ivy_ObjFaninC0(pGhost); + fCompl1 = Ivy_ObjFaninC1(pGhost); + // call recursively + pResult = Ivy_Oper( p, Ivy_NotCond(Ivy_ObjFanin0(pLat0), fCompl0), Ivy_NotCond(Ivy_ObjFanin0(pLat1), fCompl1), Type ); + // build latch on top of this + Init0 = Ivy_InitNotCond( Ivy_ObjInit(pLat0), fCompl0 ); + Init1 = Ivy_InitNotCond( Ivy_ObjInit(pLat1), fCompl1 ); + Init = (Type == IVY_AND)? Ivy_InitAnd(Init0, Init1) : Ivy_InitExor(Init0, Init1); + return Ivy_Latch( p, pResult, Init ); +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_Obj_t * pGhost, * pResult; + pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_AND, IVY_INIT_NONE ); + pResult = Ivy_CanonPair_rec( p, pGhost ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_Obj_t * pGhost, * pResult; + int fCompl = Ivy_IsComplement(pObj0) ^ Ivy_IsComplement(pObj1); + pObj0 = Ivy_Regular(pObj0); + pObj1 = Ivy_Regular(pObj1); + pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_EXOR, IVY_INIT_NONE ); + pResult = Ivy_CanonPair_rec( p, pGhost ); + return Ivy_NotCond( pResult, fCompl ); +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) +{ + Ivy_Obj_t * pGhost, * pResult; + int fCompl = Ivy_IsComplement(pObj); + pObj = Ivy_Regular(pObj); + pGhost = Ivy_ObjCreateGhost( p, pObj, NULL, IVY_LATCH, Ivy_InitNotCond(Init, fCompl) ); + pResult = Ivy_TableLookup( p, pGhost ); + if ( pResult == NULL ) + pResult = Ivy_ObjCreate( p, pGhost ); + return Ivy_NotCond( pResult, fCompl ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyCheck.c b/src/aig/ivy/ivyCheck.c new file mode 100644 index 00000000..55448f19 --- /dev/null +++ b/src/aig/ivy/ivyCheck.c @@ -0,0 +1,273 @@ +/**CFile**************************************************************** + + FileName [ivyCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the consistency of the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheck( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj, * pObj2; + int i; + Ivy_ManForEachObj( p, pObj, i ) + { + // skip deleted nodes + if ( Ivy_ObjId(pObj) != i ) + { + printf( "Ivy_ManCheck: Node with ID %d is listed as number %d in the array of objects.\n", pObj->Id, i ); + return 0; + } + // consider the constant node and PIs + if ( i == 0 || Ivy_ObjIsPi(pObj) ) + { + if ( Ivy_ObjFaninId0(pObj) || Ivy_ObjFaninId1(pObj) || Ivy_ObjLevel(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has non-standard constant or PI node with ID \"%d\".\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsPo(pObj) ) + { + if ( Ivy_ObjFaninId1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has non-standard PO node with ID \"%d\".\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsBuf(pObj) ) + { + if ( Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The buffer with ID \"%d\" contains second fanin.\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsLatch(pObj) ) + { + if ( Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The latch with ID \"%d\" contains second fanin.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjInit(pObj) == IVY_INIT_NONE ) + { + printf( "Ivy_ManCheck: The latch with ID \"%d\" does not have initial state.\n", pObj->Id ); + return 0; + } + pObj2 = Ivy_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + printf( "Ivy_ManCheck: Latch with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); + continue; + } + // consider the AND node + if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has internal node \"%d\" with a NULL fanin.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjFaninId0(pObj) >= Ivy_ObjFaninId1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has node \"%d\" with a wrong ordering of fanins.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjLevel(pObj) != Ivy_ObjLevelNew(pObj) ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has level %d but should have level %d.\n", pObj->Id, Ivy_ObjLevel(pObj), Ivy_ObjLevelNew(pObj) ); + pObj2 = Ivy_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + printf( "Ivy_ManCheck: Node with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); + if ( Ivy_ObjRefs(pObj) == 0 ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has no fanouts.\n", pObj->Id ); + // check fanouts + if ( p->fFanout && Ivy_ObjRefs(pObj) != Ivy_ObjFanoutNum(p, pObj) ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has mismatch between the number of fanouts and refs.\n", pObj->Id ); + } + // count the number of nodes in the table + if ( Ivy_TableCountEntries(p) != Ivy_ManAndNum(p) + Ivy_ManExorNum(p) + Ivy_ManLatchNum(p) ) + { + printf( "Ivy_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } +// if ( !Ivy_ManCheckFanouts(p) ) +// return 0; + if ( !Ivy_ManIsAcyclic(p) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, Counter = 0; + Ivy_ManForEachObj( p, pObj, i ) + if ( Ivy_ObjIsNode(pObj) ) + Counter += (Ivy_ObjRefs(pObj) == 0); + if ( Counter ) + printf( "Sequential AIG has %d dangling nodes.\n", Counter ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Verifies the fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckFanouts( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vFanouts; + Ivy_Obj_t * pObj, * pFanout, * pFanin; + int i, k, RetValue = 1; + if ( !p->fFanout ) + return 1; + vFanouts = Vec_PtrAlloc( 100 ); + // make sure every fanin is a fanout + Ivy_ManForEachObj( p, pObj, i ) + { + pFanin = Ivy_ObjFanin0(pObj); + if ( pFanin == NULL ) + continue; + Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) + if ( pFanout == pObj ) + break; + if ( k == Vec_PtrSize(vFanouts) ) + { + printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); + RetValue = 0; + } + + pFanin = Ivy_ObjFanin1(pObj); + if ( pFanin == NULL ) + continue; + Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) + if ( pFanout == pObj ) + break; + if ( k == Vec_PtrSize(vFanouts) ) + { + printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); + RetValue = 0; + } + // check that the previous fanout has the same fanin + if ( pObj->pPrevFan0 ) + { + if ( Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) ) + { + printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan0->Id ); + RetValue = 0; + } + } + // check that the previous fanout has the same fanin + if ( pObj->pPrevFan1 ) + { + if ( Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) ) + { + printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan1->Id ); + RetValue = 0; + } + } + } + // make sure every fanout is a fanin + Ivy_ManForEachObj( p, pObj, i ) + { + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, k ) + if ( Ivy_ObjFanin0(pFanout) != pObj && Ivy_ObjFanin1(pFanout) != pObj ) + { + printf( "Node %d is a fanout of node %d but the fanin is not there.\n", pFanout->Id, pObj->Id ); + RetValue = 0; + } + } + Vec_PtrFree( vFanouts ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Checks that each choice node has exactly one node with fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckChoices( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj, * pTemp; + int i; + Ivy_ManForEachObj( p->pHaig, pObj, i ) + { + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + // count the number of nodes in the loop + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp && pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + if ( Ivy_ObjRefs(pTemp) > 1 ) + printf( "Node %d has member %d in its equiv class with %d fanouts.\n", pObj->Id, pTemp->Id, Ivy_ObjRefs(pTemp) ); + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyCut.c b/src/aig/ivy/ivyCut.c new file mode 100644 index 00000000..d918c96c --- /dev/null +++ b/src/aig/ivy/ivyCut.c @@ -0,0 +1,987 @@ +/**CFile**************************************************************** + + FileName [ivyCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Computes reconvergence driven sequential cut.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCut.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Ivy_NodeCutHashValue( int NodeId ) { return 1 << (NodeId % 31); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeGetLeafCostOne( Ivy_Man_t * p, int Leaf, Vec_Int_t * vInside ) +{ + Ivy_Obj_t * pNode; + int nLatches, FaninLeaf, Cost; + // make sure leaf is not a contant node + assert( Leaf > 0 ); + // get the node + pNode = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); + // cannot expand over the PI node + if ( Ivy_ObjIsPi(pNode) || Ivy_ObjIsConst1(pNode) ) + return 999; + // get the number of latches + nLatches = Ivy_LeafLat(Leaf) + Ivy_ObjIsLatch(pNode); + if ( nLatches > 15 ) + return 999; + // get the first fanin + FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); + Cost = FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); + // quit if this is the one fanin node + if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + return Cost; + assert( Ivy_ObjIsNode(pNode) ); + // get the second fanin + FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); + Cost += FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); + return Cost; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks only at their immediate + predecessors (this is why it is called a one-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSeqFindCut_int( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSizeLimit ) +{ + Ivy_Obj_t * pNode; + int CostBest, CostCur, Leaf, LeafBest, Next, nLatches, i; + int LeavesBest[10]; + int Counter; + + // add random selection of the best fanin!!! + + // find the best fanin + CostBest = 99; + LeafBest = -1; + Counter = -1; +//printf( "Evaluating fanins of the cut:\n" ); + Vec_IntForEachEntry( vFront, Leaf, i ) + { + CostCur = Ivy_NodeGetLeafCostOne( p, Leaf, vInside ); +//printf( " Fanin %s has cost %d.\n", Ivy_ObjName(pNode), CostCur ); + if ( CostBest > CostCur ) + { + CostBest = CostCur; + LeafBest = Leaf; + LeavesBest[0] = Leaf; + Counter = 1; + } + else if ( CostBest == CostCur ) + LeavesBest[Counter++] = Leaf; + + if ( CostBest <= 1 ) // can be if ( CostBest <= 1 ) + break; + } + if ( CostBest == 99 ) + return 0; +// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); + + assert( CostBest < 3 ); + if ( Vec_IntSize(vFront) - 1 + CostBest > nSizeLimit ) + return 0; +// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); + + assert( Counter > 0 ); +printf( "%d", Counter ); + + LeafBest = LeavesBest[rand() % Counter]; + + // remove the node from the array + assert( LeafBest >= 0 ); + Vec_IntRemove( vFront, LeafBest ); +//printf( "Removing fanin %s.\n", Ivy_ObjName(pNode) ); + + // get the node and its latches + pNode = Ivy_ManObj( p, Ivy_LeafId(LeafBest) ); + nLatches = Ivy_LeafLat(LeafBest) + Ivy_ObjIsLatch(pNode); + assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ); + + // add the left child to the fanins + Next = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); + if ( Next && Vec_IntFind(vInside, Next) == -1 ) + { +//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); + Vec_IntPush( vFront, Next ); + Vec_IntPush( vInside, Next ); + } + + // quit if this is the one fanin node + if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + return 1; + assert( Ivy_ObjIsNode(pNode) ); + + // add the right child to the fanins + Next = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); + if ( Next && Vec_IntFind(vInside, Next) == -1 ) + { +//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); + Vec_IntPush( vFront, Next ); + Vec_IntPush( vInside, Next ); + } + assert( Vec_IntSize(vFront) <= nSizeLimit ); + // keep doing this + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes one sequential cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ) +{ + assert( !Ivy_IsComplement(pRoot) ); + assert( Ivy_ObjIsNode(pRoot) ); + assert( Ivy_ObjFaninId0(pRoot) ); + assert( Ivy_ObjFaninId1(pRoot) ); + + // start the cut + Vec_IntClear( vFront ); + Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); + Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); + + // start the visited nodes + Vec_IntClear( vInside ); + Vec_IntPush( vInside, Ivy_LeafCreate(pRoot->Id, 0) ); + Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); + Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); + + // compute the cut + while ( Ivy_ManSeqFindCut_int( p, vFront, vInside, nSize ) ); + assert( Vec_IntSize(vFront) <= nSize ); +} + + + + + +/**Function************************************************************* + + Synopsis [Computing Boolean cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume, Ivy_Obj_t * pPivot ) +{ + int RetValue0, RetValue1; + if ( pObj == pPivot ) + { + Vec_PtrPushUnique( vLeaves, pObj ); + Vec_PtrPushUnique( vVolume, pObj ); + return 1; + } + if ( pObj->fMarkA ) + return 0; + +// assert( !Ivy_ObjIsCi(pObj) ); + if ( Ivy_ObjIsCi(pObj) ) + return 0; + + if ( Ivy_ObjIsBuf(pObj) ) + { + RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); + if ( !RetValue0 ) + return 0; + Vec_PtrPushUnique( vVolume, pObj ); + return 1; + } + assert( Ivy_ObjIsNode(pObj) ); + RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); + RetValue1 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin1(pObj), vLeaves, vVolume, pPivot ); + if ( !RetValue0 && !RetValue1 ) + return 0; + // add new leaves + if ( !RetValue0 ) + { + Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin0(pObj) ); + Vec_PtrPushUnique( vVolume, Ivy_ObjFanin0(pObj) ); + } + if ( !RetValue1 ) + { + Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin1(pObj) ); + Vec_PtrPushUnique( vVolume, Ivy_ObjFanin1(pObj) ); + } + Vec_PtrPushUnique( vVolume, pObj ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the cost of one node (how many new nodes are added.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCutCost( Ivy_Obj_t * pObj ) +{ + int Cost; + // make sure the node is in the construction zone + assert( pObj->fMarkA == 1 ); + // cannot expand over the PI node + if ( Ivy_ObjIsCi(pObj) ) + return 999; + // always expand over the buffer + if ( Ivy_ObjIsBuf(pObj) ) + return !Ivy_ObjFanin0(pObj)->fMarkA; + // get the cost of the cone + Cost = (!Ivy_ObjFanin0(pObj)->fMarkA) + (!Ivy_ObjFanin1(pObj)->fMarkA); + // return the number of nodes to be added to the leaves if this node is removed + return Cost; +} + +/**Function************************************************************* + + Synopsis [Computing Boolean cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolume, Vec_Ptr_t * vLeaves ) +{ + Ivy_Obj_t * pObj, * pFaninC, * pFanin0, * pFanin1, * pPivot; + int RetValue, LevelLimit, Lev, k; + assert( !Ivy_IsComplement(pRoot) ); + // clear the frontier and collect the nodes + Vec_PtrClear( vFront ); + Vec_PtrClear( vVolume ); + if ( Ivy_ObjIsMuxType(pRoot) ) + pFaninC = Ivy_ObjRecognizeMux( pRoot, &pFanin0, &pFanin1 ); + else + { + pFaninC = NULL; + pFanin0 = Ivy_ObjFanin0(pRoot); + pFanin1 = Ivy_ObjFanin1(pRoot); + } + // start cone A + pFanin0->fMarkA = 1; + Vec_PtrPush( vFront, pFanin0 ); + Vec_PtrPush( vVolume, pFanin0 ); + // start cone B + pFanin1->fMarkB = 1; + Vec_PtrPush( vFront, pFanin1 ); + Vec_PtrPush( vVolume, pFanin1 ); + // iteratively expand until the common node (pPivot) is found or limit is reached + assert( Ivy_ObjLevel(pRoot) == Ivy_ObjLevelNew(pRoot) ); + pPivot = NULL; + LevelLimit = IVY_MAX( Ivy_ObjLevel(pRoot) - 10, 1 ); + for ( Lev = Ivy_ObjLevel(pRoot) - 1; Lev >= LevelLimit; Lev-- ) + { + while ( 1 ) + { + // find the next node to expand on this level + Vec_PtrForEachEntry( vFront, pObj, k ) + if ( (int)pObj->Level == Lev ) + break; + if ( k == Vec_PtrSize(vFront) ) + break; + assert( (int)pObj->Level <= Lev ); + assert( pObj->fMarkA ^ pObj->fMarkB ); + // remove the old node + Vec_PtrRemove( vFront, pObj ); + + // expand this node + pFanin0 = Ivy_ObjFanin0(pObj); + if ( !pFanin0->fMarkA && !pFanin0->fMarkB ) + { + Vec_PtrPush( vFront, pFanin0 ); + Vec_PtrPush( vVolume, pFanin0 ); + } + // mark the new nodes + if ( pObj->fMarkA ) + pFanin0->fMarkA = 1; + if ( pObj->fMarkB ) + pFanin0->fMarkB = 1; + + if ( Ivy_ObjIsBuf(pObj) ) + { + if ( pFanin0->fMarkA && pFanin0->fMarkB ) + { + pPivot = pFanin0; + break; + } + continue; + } + + // expand this node + pFanin1 = Ivy_ObjFanin1(pObj); + if ( !pFanin1->fMarkA && !pFanin1->fMarkB ) + { + Vec_PtrPush( vFront, pFanin1 ); + Vec_PtrPush( vVolume, pFanin1 ); + } + // mark the new nodes + if ( pObj->fMarkA ) + pFanin1->fMarkA = 1; + if ( pObj->fMarkB ) + pFanin1->fMarkB = 1; + + // consider if it is time to quit + if ( pFanin0->fMarkA && pFanin0->fMarkB ) + { + pPivot = pFanin0; + break; + } + if ( pFanin1->fMarkA && pFanin1->fMarkB ) + { + pPivot = pFanin1; + break; + } + } + if ( pPivot != NULL ) + break; + } + if ( pPivot == NULL ) + return 0; + // if the MUX control is defined, it should not be + if ( pFaninC && !pFaninC->fMarkA && !pFaninC->fMarkB ) + Vec_PtrPush( vFront, pFaninC ); + // clean the markings + Vec_PtrForEachEntry( vVolume, pObj, k ) + pObj->fMarkA = pObj->fMarkB = 0; + + // mark the nodes on the frontier (including the pivot) + Vec_PtrForEachEntry( vFront, pObj, k ) + pObj->fMarkA = 1; + // cut exists, collect all the nodes on the shortest path to the pivot + Vec_PtrClear( vLeaves ); + Vec_PtrClear( vVolume ); + RetValue = Ivy_ManFindBoolCut_rec( p, pRoot, vLeaves, vVolume, pPivot ); + assert( RetValue == 1 ); + // unmark the nodes on the frontier (including the pivot) + Vec_PtrForEachEntry( vFront, pObj, k ) + pObj->fMarkA = 0; + + // mark the nodes in the volume + Vec_PtrForEachEntry( vVolume, pObj, k ) + pObj->fMarkA = 1; + // expand the cut without increasing its size + while ( 1 ) + { + Vec_PtrForEachEntry( vLeaves, pObj, k ) + if ( Ivy_ManFindBoolCutCost(pObj) < 2 ) + break; + if ( k == Vec_PtrSize(vLeaves) ) + break; + // the node can be expanded + // remove the old node + Vec_PtrRemove( vLeaves, pObj ); + // expand this node + pFanin0 = Ivy_ObjFanin0(pObj); + if ( !pFanin0->fMarkA ) + { + pFanin0->fMarkA = 1; + Vec_PtrPush( vVolume, pFanin0 ); + Vec_PtrPush( vLeaves, pFanin0 ); + } + if ( Ivy_ObjIsBuf(pObj) ) + continue; + // expand this node + pFanin1 = Ivy_ObjFanin1(pObj); + if ( !pFanin1->fMarkA ) + { + pFanin1->fMarkA = 1; + Vec_PtrPush( vVolume, pFanin1 ); + Vec_PtrPush( vLeaves, pFanin1 ); + } + } + // unmark the nodes in the volume + Vec_PtrForEachEntry( vVolume, pObj, k ) + pObj->fMarkA = 0; + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsBool( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vFront, * vVolume, * vLeaves; + Ivy_Obj_t * pObj;//, * pTemp; + int i, RetValue;//, k; + vFront = Vec_PtrAlloc( 100 ); + vVolume = Vec_PtrAlloc( 100 ); + vLeaves = Vec_PtrAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + if ( Ivy_ObjIsMuxType(pObj) ) + { + printf( "m" ); + continue; + } + if ( Ivy_ObjIsExor(pObj) ) + printf( "x" ); + RetValue = Ivy_ManFindBoolCut( p, pObj, vFront, vVolume, vLeaves ); + if ( RetValue == 0 ) + printf( "- " ); + else + printf( "%d ", Vec_PtrSize(vLeaves) ); +/* + printf( "( " ); + Vec_PtrForEachEntry( vFront, pTemp, k ) + printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); + printf( ")\n" ); +*/ + } + printf( "\n" ); + Vec_PtrFree( vFront ); + Vec_PtrFree( vVolume ); + Vec_PtrFree( vLeaves ); +} + + + +/**Function************************************************************* + + Synopsis [Find the hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) +{ + int i; +// for ( i = 1; i < pCut->nSize; i++ ) +// assert( pCut->pArray[i-1] < pCut->pArray[i] ); + pCut->uHash = 0; + for ( i = 0; i < pCut->nSize; i++ ) + pCut->uHash |= (1 << (pCut->pArray[i] % 31)); + return pCut->uHash; +} + +/**Function************************************************************* + + Synopsis [Removes one node to the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld ) +{ + int i, k; + for ( i = k = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] != iOld ) + pCut->pArray[k++] = pCut->pArray[i]; + assert( k == pCut->nSize - 1 ); + pCut->nSize--; +} + +/**Function************************************************************* + + Synopsis [Adds one node to the cut.] + + Description [Returns 1 if the cuts is still okay.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew ) +{ + int i; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == iNew ) + return 1; + // check if there is room + if ( pCut->nSize == pCut->nSizeMax ) + return 0; + // add the new one + for ( i = pCut->nSize - 1; i >= 0; i-- ) + if ( pCut->pArray[i] > iNew ) + pCut->pArray[i+1] = pCut->pArray[i]; + else + { + assert( pCut->pArray[i] < iNew ); + break; + } + pCut->pArray[i+1] = iNew; + pCut->nSize++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) +{ + int i; + if ( pCut->nSize < pCut->nSizeMax ) + return 1; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_NodeCutHashValue( IdNew0 ); + } + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_NodeCutHashValue( IdNew1 ); + } + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_NodeCutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_NodeCutHashValue( IdNew0 ); + } + if ( IdNew1 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_NodeCutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); +// for ( i = 1; i < pCutNew->nSize; i++ ) +// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < pDom->nSize; i++ ) + { + for ( k = 0; k < pCut->nSize; k++ ) + if ( pDom->pArray[i] == pCut->pArray[k] ) + break; + if ( k == pCut->nSize ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize == pCutNew->nSize ) + { + if ( pCut->uHash == pCutNew->uHash ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + continue; + } + if ( pCut->nSize < pCutNew->nSize ) + { + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) + return 1; + continue; + } + // check potential containment of other cut + + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) + { + // remove the current cut +// --pCutStore->nCuts; +// for ( k = i; k < pCutStore->nCuts; k++ ) +// pCutStore->pCuts[k] = pCutStore->pCuts[k+1]; +// i--; + pCut->nSize = 0; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore ) +{ + Ivy_Cut_t * pCut; + int i, k; + for ( i = k = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + pCutStore->pCuts[k++] = *pCut; + } + pCutStore->nCuts = k; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodePrintCut( Ivy_Cut_t * pCut ) +{ + int i; + assert( pCut->nSize > 0 ); + printf( "%d : {", pCut->nSize ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d", pCut->pArray[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore ) +{ + int i; + printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); + for ( i = 0; i < pCutStore->nCuts; i++ ) + Ivy_NodePrintCut( pCutStore->pCuts + i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Obj_t * Ivy_ObjRealFanin( Ivy_Obj_t * pObj ) +{ + if ( !Ivy_ObjIsBuf(pObj) ) + return pObj; + return Ivy_ObjRealFanin( Ivy_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; + Ivy_Obj_t * pLeaf; + int i, k, iLeaf0, iLeaf1; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // start the trivial cut + pCutNew->uHash = 0; + pCutNew->nSize = 1; + pCutNew->nSizeMax = nLeaves; + pCutNew->pArray[0] = pObj->Id; + Ivy_NodeCutHash( pCutNew ); + // add the trivial cut + Ivy_NodeCutFindOrAdd( pCutStore, pCutNew ); + assert( pCutStore->nCuts == 1 ); + + // explore the cuts + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + // expand this cut + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + for ( k = 0; k < pCut->nSize; k++ ) + { + pLeaf = Ivy_ManObj( p, pCut->pArray[k] ); + if ( Ivy_ObjIsCi(pLeaf) ) + continue; +/* + *pCutNew = *pCut; + Ivy_NodeCutShrink( pCutNew, pLeaf->Id ); + if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) ) + continue; + if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) ) + continue; + Ivy_NodeCutHash( pCutNew ); +*/ + iLeaf0 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin0(pLeaf)) ); + iLeaf1 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin1(pLeaf)) ); + if ( !Ivy_NodeCutPrescreen( pCut, iLeaf0, iLeaf1 ) ) + continue; + if ( iLeaf0 > iLeaf1 ) + Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf1, iLeaf0 ); + else + Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ); + Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew ); + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + Ivy_NodeCompactCuts( pCutStore ); +// Ivy_NodePrintCuts( pCutStore ); + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsAll( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; + int clk = clock(); + nNodeTotal = nNodeOver = 0; + nCutsTotal = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + nCutsCut = Ivy_NodeFindCutsAll( p, pObj, 5 )->nCuts; + nCutsTotal += nCutsCut; + nNodeOver += (nCutsCut == IVY_CUT_LIMIT); + nNodeTotal++; + } + printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", + nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + PRT( "Time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyCutTrav.c b/src/aig/ivy/ivyCutTrav.c new file mode 100644 index 00000000..ea57c9f5 --- /dev/null +++ b/src/aig/ivy/ivyCutTrav.c @@ -0,0 +1,473 @@ +/**CFile**************************************************************** + + FileName [ivyCutTrav.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ); +static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ); +static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, + Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Vec_Ptr_t * vCuts, * vCuts0, * vCuts1; + unsigned * pBitCut; + Ivy_Obj_t * pLeaf; + Ivy_Cut_t * pCut; + int i, k, nWords, nNodes; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // find the given number of nodes in the TFI + Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront ); + nNodes = Vec_PtrSize(vNodes); +// assert( nNodes <= nNodeLimit ); + + // make sure vBitCuts has enough room + Vec_VecExpand( vBitCuts, nNodes-1 ); + Vec_VecClear( vBitCuts ); + + // prepare the memory manager + Vec_IntClear( vStore ); + Vec_IntGrow( vStore, 64000 ); + + // set elementary cuts for the leaves + nWords = Extra_BitWordNum( nNodes ); + Vec_PtrForEachEntry( vFront, pLeaf, i ) + { + assert( Ivy_ObjTravId(pLeaf) < nNodes ); + // get the new bitcut + pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); + // set it as the cut of this leaf + Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); + } + + // compute the cuts for each node + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + { + // skip the leaves + vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) ); + if ( Vec_PtrSize(vCuts) > 0 ) + continue; + // add elementary cut + pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); + // set it as the cut of this leaf + Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); + // get the fanin cuts + vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) ); + vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) ); + assert( Vec_PtrSize(vCuts0) > 0 ); + assert( Vec_PtrSize(vCuts1) > 0 ); + // merge the cuts + Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore ); + } + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // collect the cuts of the root node + vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) ); + Vec_PtrForEachEntry( vCuts, pBitCut, i ) + { + pCut = pCutStore->pCuts + pCutStore->nCuts++; + pCut->nSize = 0; + pCut->nSizeMax = nLeaves; + pCut->uHash = 0; + for ( k = 0; k < nNodes; k++ ) + if ( Extra_TruthHasBit(pBitCut, k) ) + pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( Vec_PtrEntry(vNodes, k) ); + assert( pCut->nSize <= nLeaves ); + if ( pCutStore->nCuts == pCutStore->nCutsMax ) + break; + } + + // clean the travIds + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + pLeaf->TravId = 0; + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [Creates elementary bit-cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) +{ + unsigned * pBitCut; + pBitCut = Vec_IntFetch( vStore, nWords ); + memset( pBitCut, 0, 4 * nWords ); + Extra_TruthSetBit( pBitCut, NodeId ); + return pBitCut; +} + +/**Function************************************************************* + + Synopsis [Compares the node by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 ) +{ + Ivy_Obj_t * pObj1 = *ppObj1; + Ivy_Obj_t * pObj2 = *ppObj2; + if ( pObj1->Level < pObj2->Level ) + return -1; + if ( pObj1->Level > pObj2->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Mark all nodes up to the given depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth ) +{ + if ( Ivy_ObjIsCi(pObj) || Depth == 0 ) + return; + Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 ); + Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 ); + pObj->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Collect the marked nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( !pObj->fMarkA ) + return; + Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes ); + Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pTemp, * pFanin; + int i, nNodes; + // mark nodes up to the given depth + Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 ); + // collect the marked nodes + Vec_PtrClear( vFront ); + Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront ); + // find the fanins that are not marked + Vec_PtrClear( vNodes ); + Vec_PtrForEachEntry( vFront, pTemp, i ) + { + pFanin = Ivy_ObjFanin0(pTemp); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + } + pFanin = Ivy_ObjFanin1(pTemp); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + } + } + // remember the number of nodes in the frontier + nNodes = Vec_PtrSize( vNodes ); + // add the remaining nodes + Vec_PtrForEachEntry( vFront, pTemp, i ) + Vec_PtrPush( vNodes, pTemp ); + // unmark the nodes + Vec_PtrForEachEntry( vNodes, pTemp, i ) + { + pTemp->fMarkA = 0; + pTemp->TravId = i; + } + // collect the frontier nodes + Vec_PtrClear( vFront ); + Vec_PtrForEachEntryStop( vNodes, pTemp, i, nNodes ) + Vec_PtrPush( vFront, pTemp ); +// printf( "%d ", Vec_PtrSize(vNodes) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pLeaf, * pPivot, * pFanin; + int LevelMax, i; + assert( Ivy_ObjIsNode(pObj) ); + // clear arrays + Vec_PtrClear( vNodes ); + Vec_PtrClear( vFront ); + // add the root + pObj->fMarkA = 1; + Vec_PtrPush( vNodes, pObj ); + Vec_PtrPush( vFront, pObj ); + // expand node with maximum level + LevelMax = pObj->Level; + do { + // get the node to expand + pPivot = NULL; + Vec_PtrForEachEntryReverse( vFront, pLeaf, i ) + { + if ( (int)pLeaf->Level == LevelMax ) + { + pPivot = pLeaf; + break; + } + } + // decrease level if we did not find the node + if ( pPivot == NULL ) + { + if ( --LevelMax == 0 ) + break; + continue; + } + // the node to expand is found + // remove it from frontier + Vec_PtrRemove( vFront, pPivot ); + // add fanins + pFanin = Ivy_ObjFanin0(pPivot); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + Vec_PtrPush( vFront, pFanin ); + } + pFanin = Ivy_ObjFanin1(pPivot); + if ( pFanin && !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + Vec_PtrPush( vFront, pFanin ); + } + // quit if we collected enough nodes + } while ( Vec_PtrSize(vNodes) < nNodeLimit ); + + // sort nodes by level + Vec_PtrSort( vNodes, Ivy_CompareNodesByLevel ); + // make sure the nodes are ordered in the increasing number of levels + pFanin = Vec_PtrEntry( vNodes, 0 ); + pPivot = Vec_PtrEntryLast( vNodes ); + assert( pFanin->Level <= pPivot->Level ); + + // clean the marks and remember node numbers in the TravId + Vec_PtrForEachEntry( vNodes, pFanin, i ) + { + pFanin->fMarkA = 0; + pFanin->TravId = i; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords ) +{ + int w; + for ( w = nWords-1; w >= 0; w-- ) + pOut[w] = pIn0[w] | pIn1[w]; +} +static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords ) +{ + int w; + for ( w = nWords-1; w >= 0; w-- ) + if ( pIn1[w] & ~pIn2[w] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Merges two sets of bit-cuts at a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, + int nLeaves, int nWords, Vec_Int_t * vStore ) +{ + unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest; + int i, k, c, w, Counter; + // iterate through the cut pairs + Vec_PtrForEachEntry( vCuts0, pBitCut0, i ) + Vec_PtrForEachEntry( vCuts1, pBitCut1, k ) + { + // skip infeasible cuts + Counter = 0; + for ( w = 0; w < nWords; w++ ) + { + Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] ); + if ( Counter > nLeaves ) + break; + } + if ( Counter > nLeaves ) + continue; + // the new cut is feasible - create it + pBitCutTest = Vec_IntFetch( vStore, nWords ); + Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords ); + // filter contained cuts; try to find containing cut + w = 0; + Vec_PtrForEachEntry( vCuts, pBitCut, c ) + { + if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) ) + break; + if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) ) + continue; + Vec_PtrWriteEntry( vCuts, w++, pBitCut ); + } + if ( c != Vec_PtrSize(vCuts) ) + continue; + Vec_PtrShrink( vCuts, w ); + // add the cut + Vec_PtrPush( vCuts, pBitCutTest ); + } +} + +/**Function************************************************************* + + Synopsis [Compute the set of all cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsTravAll( Ivy_Man_t * p ) +{ + Ivy_Store_t * pStore; + Ivy_Obj_t * pObj; + Vec_Ptr_t * vNodes, * vFront; + Vec_Int_t * vStore; + Vec_Vec_t * vBitCuts; + int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; + int clk = clock(); + + vNodes = Vec_PtrAlloc( 100 ); + vFront = Vec_PtrAlloc( 100 ); + vStore = Vec_IntAlloc( 100 ); + vBitCuts = Vec_VecAlloc( 100 ); + + nNodeTotal = nNodeOver = 0; + nCutsTotal = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts ); + nCutsCut = pStore->nCuts; + nCutsTotal += nCutsCut; + nNodeOver += (nCutsCut == IVY_CUT_LIMIT); + nNodeTotal++; + } + printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", + nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + PRT( "Time", clock() - clk ); + + Vec_PtrFree( vNodes ); + Vec_PtrFree( vFront ); + Vec_IntFree( vStore ); + Vec_VecFree( vBitCuts ); + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyDfs.c b/src/aig/ivy/ivyDfs.c new file mode 100644 index 00000000..c27cba31 --- /dev/null +++ b/src/aig/ivy/ivyDfs.c @@ -0,0 +1,493 @@ +/**CFile**************************************************************** + + FileName [ivyDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [DFS collection procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManDfs_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Ivy_ObjIsMarkA(pObj) ) + return; + Ivy_ObjSetMarkA(pObj); + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + { + if ( p->pHaig == NULL && pObj->pEquiv ) + Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); + return; + } +//printf( "visiting node %d\n", pObj->Id ); +/* + if ( pObj->Id == 87 || pObj->Id == 90 ) + { + int y = 0; + } +*/ + assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + if ( !Ivy_ObjIsBuf(pObj) ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin1(pObj), vNodes ); + if ( p->pHaig == NULL && pObj->pEquiv ) + Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); + Vec_IntPush( vNodes, pObj->Id ); + +//printf( "adding node %d with fanins %d and %d and equiv %d (refs = %d)\n", +// pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id, +// pObj->pEquiv? Ivy_Regular(pObj->pEquiv)->Id: -1, Ivy_ObjRefs(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes; + Ivy_Obj_t * pObj; + int i; + assert( Ivy_ManLatchNum(p) == 0 ); + // make sure the nodes are not marked + Ivy_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // collect the nodes + vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + // unmark the collected nodes +// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +// Ivy_ObjClearMarkA(pObj); + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + // make sure network does not have dangling nodes + assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ) +{ + Vec_Int_t * vNodes, * vLatches; + Ivy_Obj_t * pObj; + int i; +// assert( Ivy_ManLatchNum(p) > 0 ); + // make sure the nodes are not marked + Ivy_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // collect the latches + vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); + Ivy_ManForEachLatch( p, pObj, i ) + Vec_IntPush( vLatches, pObj->Id ); + // collect the nodes + vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + // unmark the collected nodes +// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +// Ivy_ObjClearMarkA(pObj); + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + // make sure network does not have dangling nodes +// assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); + +// temporary!!! + + if ( pvLatches == NULL ) + Vec_IntFree( vLatches ); + else + *pvLatches = vLatches; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone ) +{ + if ( pObj->fMarkA ) + return; + if ( Ivy_ObjIsBuf(pObj) ) + { + Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); + Vec_PtrPush( vCone, pObj ); + return; + } + assert( Ivy_ObjIsNode(pObj) ); + Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); + Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone ); + Vec_PtrPushUnique( vCone, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) +{ + Ivy_Obj_t * pTemp; + int i; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // mark the nodes + Vec_PtrForEachEntry( vFront, pTemp, i ) + Ivy_Regular(pTemp)->fMarkA = 1; + assert( pObj->fMarkA == 0 ); + // collect the cone + Vec_PtrClear( vCone ); + Ivy_ManCollectCone_rec( pObj, vCone ); + // unmark the nodes + Vec_PtrForEachEntry( vFront, pTemp, i ) + Ivy_Regular(pTemp)->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the nodes by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ) +{ + Vec_Vec_t * vNodes; + Ivy_Obj_t * pObj; + int i; + vNodes = Vec_VecAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + assert( !Ivy_ObjIsBuf(pObj) ); + if ( Ivy_ObjIsNode(pObj) ) + Vec_VecPush( vNodes, pObj->Level, pObj ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes required levels for each node.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + Vec_Int_t * vLevelsR; + Vec_Vec_t * vNodes; + int i, k, Level, LevelMax; + assert( p->vRequired == NULL ); + // start the required times + vLevelsR = Vec_IntStart( Ivy_ManObjIdMax(p) + 1 ); + // iterate through the nodes in the reverse order + vNodes = Ivy_ManLevelize( p ); + Vec_VecForEachEntryReverseReverse( vNodes, pObj, i, k ) + { + Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj); + if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level ) + Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level ); + if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level ) + Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level ); + } + Vec_VecFree( vNodes ); + // convert it into the required times + LevelMax = Ivy_ManLevels( p ); +//printf( "max %5d\n",LevelMax ); + Ivy_ManForEachObj( p, pObj, i ) + { + Level = Vec_IntEntry( vLevelsR, pObj->Id ); + Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level ); +//printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level ); + } + p->vRequired = vLevelsR; + return vLevelsR; +} + +/**Function************************************************************* + + Synopsis [Recursively detects combinational loops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManIsAcyclic_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + // skip the node if it is already visited + if ( Ivy_ObjIsTravIdPrevious(p, pObj) ) + return 1; + // check if the node is part of the combinational loop + if ( Ivy_ObjIsTravIdCurrent(p, pObj) ) + { + fprintf( stdout, "Manager contains combinational loop!\n" ); + fprintf( stdout, "Node \"%d\" is encountered twice on the following path:\n", Ivy_ObjId(pObj) ); + fprintf( stdout, " %d", Ivy_ObjId(pObj) ); + return 0; + } + // mark this node as a node on the current path + Ivy_ObjSetTravIdCurrent( p, pObj ); + // explore equivalent nodes if pObj is the main node + if ( p->pHaig == NULL && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + // traverse the fanin's cone searching for the loop + if ( !Ivy_ManIsAcyclic_rec(p, pTemp) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> (%d", Ivy_ObjId(pObj) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + fprintf( stdout, " %d", Ivy_ObjId(pTemp) ); + fprintf( stdout, ")" ); + return 0; + } + } + } + // quite if it is a CI node + if ( Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) + { + // mark this node as a visited node + Ivy_ObjSetTravIdPrevious( p, pObj ); + return 1; + } + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + // traverse the fanin's cone searching for the loop + if ( !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); + return 0; + } + // traverse the fanin's cone searching for the loop + if ( Ivy_ObjIsNode(pObj) && !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin1(pObj)) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); + return 0; + } + // mark this node as a visited node + Ivy_ObjSetTravIdPrevious( p, pObj ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Detects combinational loops.] + + Description [This procedure is based on the idea suggested by Donald Chai. + As we traverse the network and visit the nodes, we need to distinquish + three types of nodes: (1) those that are visited for the first time, + (2) those that have been visited in this traversal but are currently not + on the traversal path, (3) those that have been visited and are currently + on the travesal path. When the node of type (3) is encountered, it means + that there is a combinational loop. To mark the three types of nodes, + two new values of the traversal IDs are used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManIsAcyclic( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int fAcyclic, i; + // set the traversal ID for this DFS ordering + Ivy_ManIncrementTravId( p ); + Ivy_ManIncrementTravId( p ); + // pObj->TravId == pNet->nTravIds means "pObj is on the path" + // pObj->TravId == pNet->nTravIds - 1 means "pObj is visited but is not on the path" + // pObj->TravId < pNet->nTravIds - 1 means "pObj is not visited" + // traverse the network to detect cycles + fAcyclic = 1; + Ivy_ManForEachCo( p, pObj, i ) + { + // traverse the output logic cone + if ( fAcyclic = Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) + continue; + // stop as soon as the first loop is detected + fprintf( stdout, " (cone of %s \"%d\")\n", Ivy_ObjIsLatch(pObj)? "latch" : "PO", Ivy_ObjId(pObj) ); + break; + } + return fAcyclic; +} + +/**Function************************************************************* + + Synopsis [Sets the levels of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSetLevels_rec( Ivy_Obj_t * pObj, int fHaig ) +{ + // quit if the node is visited + if ( Ivy_ObjIsMarkA(pObj) ) + return pObj->Level; + Ivy_ObjSetMarkA(pObj); + // quit if this is a CI + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); + // get levels of the fanins + Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); + if ( !Ivy_ObjIsBuf(pObj) ) + Ivy_ManSetLevels_rec( Ivy_ObjFanin1(pObj), fHaig ); + // get level of the node + if ( Ivy_ObjIsBuf(pObj) ) + pObj->Level = 1 + Ivy_ObjFanin0(pObj)->Level; + else if ( Ivy_ObjIsNode(pObj) ) + pObj->Level = Ivy_ObjLevelNew( pObj ); + else assert( 0 ); + // get level of other choices + if ( fHaig && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { + Ivy_Obj_t * pTemp; + unsigned LevelMax = pObj->Level; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + Ivy_ManSetLevels_rec( pTemp, fHaig ); + LevelMax = IVY_MAX( LevelMax, pTemp->Level ); + } + // get this level + pObj->Level = LevelMax; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + pTemp->Level = LevelMax; + } + return pObj->Level; +} + +/**Function************************************************************* + + Synopsis [Sets the levels of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ) +{ + Ivy_Obj_t * pObj; + int i, LevelMax; + // check if CIs have choices + if ( fHaig ) + { + Ivy_ManForEachCi( p, pObj, i ) + if ( pObj->pEquiv ) + printf( "CI %d has a choice, which will not be visualized.\n", pObj->Id ); + } + // clean the levels + Ivy_ManForEachObj( p, pObj, i ) + pObj->Level = 0; + // compute the levels + LevelMax = 0; + Ivy_ManForEachCo( p, pObj, i ) + { + Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); + LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); + } + // compute levels of nodes without fanout + Ivy_ManForEachObj( p, pObj, i ) + if ( (Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj)) && Ivy_ObjRefs(pObj) == 0 ) + { + Ivy_ManSetLevels_rec( pObj, fHaig ); + LevelMax = IVY_MAX( LevelMax, (int)pObj->Level ); + } + // clean the marks + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + return LevelMax; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyDsd.c b/src/aig/ivy/ivyDsd.c new file mode 100644 index 00000000..3b8a2e68 --- /dev/null +++ b/src/aig/ivy/ivyDsd.c @@ -0,0 +1,819 @@ +/**CFile**************************************************************** + + FileName [ivyDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Disjoint-support decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyDsd.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// decomposition types +typedef enum { + IVY_DEC_PI, // 0: var + IVY_DEC_CONST1, // 1: CONST1 + IVY_DEC_BUF, // 2: BUF + IVY_DEC_AND, // 3: AND + IVY_DEC_EXOR, // 4: EXOR + IVY_DEC_MUX, // 5: MUX + IVY_DEC_MAJ, // 6: MAJ + IVY_DEC_PRIME // 7: undecomposable +} Ivy_DecType_t; + +typedef struct Ivy_Dec_t_ Ivy_Dec_t; +struct Ivy_Dec_t_ +{ + unsigned Type : 4; // the node type (PI, CONST1, AND, EXOR, MUX, PRIME) + unsigned fCompl : 1; // shows if node is complemented (root node only) + unsigned nFans : 3; // the number of fanins + unsigned Fan0 : 4; // fanin 0 + unsigned Fan1 : 4; // fanin 1 + unsigned Fan2 : 4; // fanin 2 + unsigned Fan3 : 4; // fanin 3 + unsigned Fan4 : 4; // fanin 4 + unsigned Fan5 : 4; // fanin 5 +}; + +static inline int Ivy_DecToInt( Ivy_Dec_t Node ) { return *((int *)&Node); } +static inline Ivy_Dec_t Ivy_IntToDec( int Node ) { return *((Ivy_Dec_t *)&Node); } +static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *((int *)pNode) = 0; } + + +static unsigned s_Masks[6][2] = { + { 0x55555555, 0xAAAAAAAA }, + { 0x33333333, 0xCCCCCCCC }, + { 0x0F0F0F0F, 0xF0F0F0F0 }, + { 0x00FF00FF, 0xFF00FF00 }, + { 0x0000FFFF, 0xFFFF0000 }, + { 0x00000000, 0xFFFFFFFF } +}; + +static inline int Ivy_TruthWordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} + +static inline int Ivy_TruthCofactorIsConst( unsigned uTruth, int Var, int Cof, int Const ) +{ + if ( Const == 0 ) + return (uTruth & s_Masks[Var][Cof]) == 0; + else + return (uTruth & s_Masks[Var][Cof]) == s_Masks[Var][Cof]; +} + +static inline int Ivy_TruthCofactorIsOne( unsigned uTruth, int Var ) +{ + return (uTruth & s_Masks[Var][0]) == 0; +} + +static inline unsigned Ivy_TruthCofactor( unsigned uTruth, int Var ) +{ + unsigned uCofactor = uTruth & s_Masks[Var >> 1][(Var & 1) == 0]; + int Shift = (1 << (Var >> 1)); + if ( Var & 1 ) + return uCofactor | (uCofactor << Shift); + return uCofactor | (uCofactor >> Shift); +} + +static inline unsigned Ivy_TruthCofactor2( unsigned uTruth, int Var0, int Var1 ) +{ + return Ivy_TruthCofactor( Ivy_TruthCofactor(uTruth, Var0), Var1 ); +} + +// returns 1 if the truth table depends on this var (var is regular interger var) +static inline int Ivy_TruthDepends( unsigned uTruth, int Var ) +{ + return Ivy_TruthCofactor(uTruth, Var << 1) != Ivy_TruthCofactor(uTruth, (Var << 1) | 1); +} + +static inline void Ivy_DecSetVar( Ivy_Dec_t * pNode, int iNum, unsigned Var ) +{ + assert( iNum >= 0 && iNum <= 5 ); + switch( iNum ) + { + case 0: pNode->Fan0 = Var; break; + case 1: pNode->Fan1 = Var; break; + case 2: pNode->Fan2 = Var; break; + case 3: pNode->Fan3 = Var; break; + case 4: pNode->Fan4 = Var; break; + case 5: pNode->Fan5 = Var; break; + } +} + +static inline unsigned Ivy_DecGetVar( Ivy_Dec_t * pNode, int iNum ) +{ + assert( iNum >= 0 && iNum <= 5 ); + switch( iNum ) + { + case 0: return pNode->Fan0; + case 1: return pNode->Fan1; + case 2: return pNode->Fan2; + case 3: return pNode->Fan3; + case 4: return pNode->Fan4; + case 5: return pNode->Fan5; + } + return ~0; +} + +static int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ); +static int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ); + +//int nTruthDsd; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes DSD of truth table of 5 variables or less.] + + Description [Returns 1 if the function is a constant or is fully + DSD decomposable using AND/EXOR/MUX gates.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int i, RetValue; + // set the PI variables + Vec_IntClear( vTree ); + for ( i = 0; i < 5; i++ ) + Vec_IntPush( vTree, 0 ); + // check if it is a constant + if ( uTruth == 0 || ~uTruth == 0 ) + { + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_CONST1; + Node.fCompl = (uTruth == 0); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return 1; + } + // perform the decomposition + RetValue = Ivy_TruthDecompose_rec( uTruth, vTree ); + if ( RetValue == -1 ) + return 0; + // get the topmost node + if ( (RetValue >> 1) < 5 ) + { // add buffer + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_BUF; + Node.fCompl = (RetValue & 1); + Node.Fan0 = ((RetValue >> 1) << 1); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + } + else if ( RetValue & 1 ) + { // check if the topmost node has to be complemented + Node = Ivy_IntToDec( Vec_IntPop(vTree) ); + assert( Node.fCompl == 0 ); + Node.fCompl = (RetValue & 1); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + } + if ( uTruth != Ivy_TruthDsdCompute(vTree) ) + printf( "Verification failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes DSD of truth table.] + + Description [Returns the number of topmost decomposition node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int Supp[5], Vars0[5], Vars1[5], Vars2[5], * pVars; + int nSupp, Count0, Count1, Count2, nVars, RetValue, fCompl, i; + unsigned uTruthCof, uCof0, uCof1; + + // get constant confactors + Count0 = Count1 = Count2 = nSupp = 0; + for ( i = 0; i < 5; i++ ) + { + if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 0) ) + Vars0[Count0++] = (i << 1) | 0; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 0) ) + Vars0[Count0++] = (i << 1) | 1; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 1) ) + Vars1[Count1++] = (i << 1) | 0; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 1) ) + Vars1[Count1++] = (i << 1) | 1; + else + { + uCof0 = Ivy_TruthCofactor( uTruth, (i << 1) | 1 ); + uCof1 = Ivy_TruthCofactor( uTruth, (i << 1) | 0 ); + if ( uCof0 == ~uCof1 ) + Vars2[Count2++] = (i << 1) | 0; + else if ( uCof0 != uCof1 ) + Supp[nSupp++] = i; + } + } + assert( Count0 == 0 || Count1 == 0 ); + assert( Count0 == 0 || Count2 == 0 ); + assert( Count1 == 0 || Count2 == 0 ); + + // consider the case of a single variable + if ( Count0 == 1 && nSupp == 0 ) + return Vars0[0]; + + // consider more complex decompositions + if ( Count0 == 0 && Count1 == 0 && Count2 == 0 ) + return Ivy_TruthRecognizeMuxMaj( uTruth, Supp, nSupp, vTree ); + + // extract the nodes + Ivy_DecClear( &Node ); + if ( Count0 > 0 ) + nVars = Count0, pVars = Vars0, Node.Type = IVY_DEC_AND, fCompl = 0; + else if ( Count1 > 0 ) + nVars = Count1, pVars = Vars1, Node.Type = IVY_DEC_AND, fCompl = 1, uTruth = ~uTruth; + else if ( Count2 > 0 ) + nVars = Count2, pVars = Vars2, Node.Type = IVY_DEC_EXOR, fCompl = 0; + else + assert( 0 ); + Node.nFans = nVars+(nSupp>0); + + // compute cofactor + uTruthCof = uTruth; + for ( i = 0; i < nVars; i++ ) + { + uTruthCof = Ivy_TruthCofactor( uTruthCof, pVars[i] ); + Ivy_DecSetVar( &Node, i, pVars[i] ); + } + + if ( Node.Type == IVY_DEC_EXOR ) + fCompl ^= ((Node.nFans & 1) == 0); + + if ( nSupp > 0 ) + { + assert( uTruthCof != 0 && ~uTruthCof != 0 ); + // call recursively + RetValue = Ivy_TruthDecompose_rec( uTruthCof, vTree ); + // quit if non-decomposable + if ( RetValue == -1 ) + return -1; + // remove the complement from the child if the node is EXOR + if ( Node.Type == IVY_DEC_EXOR && (RetValue & 1) ) + { + fCompl ^= 1; + RetValue ^= 1; + } + // set the new decomposition + Ivy_DecSetVar( &Node, nVars, RetValue ); + } + else if ( Node.Type == IVY_DEC_EXOR ) + fCompl ^= (uTruthCof == 0); + + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns a non-negative number if the truth table is a MUX.] + + Description [If the truth table is a MUX, returns the variable as follows: + first, control variable; second, positive cofactor; third, negative cofactor.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int i, k, RetValue0, RetValue1; + unsigned uCof0, uCof1, Num; + char Count[3]; + assert( nSupp >= 3 ); + // start the node + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_MUX; + Node.nFans = 3; + // try each of the variables + for ( i = 0; i < nSupp; i++ ) + { + // get the cofactors with respect to these variables + uCof0 = Ivy_TruthCofactor( uTruth, (pSupp[i] << 1) | 1 ); + uCof1 = Ivy_TruthCofactor( uTruth, pSupp[i] << 1 ); + // go through all other variables and make sure + // each of them belongs to the support of one cofactor + for ( k = 0; k < nSupp; k++ ) + { + if ( k == i ) + continue; + if ( Ivy_TruthDepends(uCof0, pSupp[k]) && Ivy_TruthDepends(uCof1, pSupp[k]) ) + break; + } + if ( k < nSupp ) + continue; + // MUX decomposition exists + RetValue0 = Ivy_TruthDecompose_rec( uCof0, vTree ); + if ( RetValue0 == -1 ) + break; + RetValue1 = Ivy_TruthDecompose_rec( uCof1, vTree ); + if ( RetValue1 == -1 ) + break; + // both of them exist; create the node + Ivy_DecSetVar( &Node, 0, pSupp[i] << 1 ); + Ivy_DecSetVar( &Node, 1, RetValue1 ); + Ivy_DecSetVar( &Node, 2, RetValue0 ); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | 0; + } + // check majority gate + if ( nSupp > 3 ) + return -1; + if ( Ivy_TruthWordCountOnes(uTruth) != 16 ) + return -1; + // this is a majority gate; determine polarity + Node.Type = IVY_DEC_MAJ; + Count[0] = Count[1] = Count[2] = 0; + for ( i = 0; i < 8; i++ ) + { + Num = 0; + for ( k = 0; k < 3; k++ ) + if ( i & (1 << k) ) + Num |= (1 << pSupp[k]); + assert( Num < 32 ); + if ( (uTruth & (1 << Num)) == 0 ) + continue; + for ( k = 0; k < 3; k++ ) + if ( i & (1 << k) ) + Count[k]++; + } + assert( Count[0] == 1 || Count[0] == 3 ); + assert( Count[1] == 1 || Count[1] == 3 ); + assert( Count[2] == 1 || Count[2] == 3 ); + Ivy_DecSetVar( &Node, 0, (pSupp[0] << 1)|(Count[0] == 1) ); + Ivy_DecSetVar( &Node, 1, (pSupp[1] << 1)|(Count[1] == 1) ); + Ivy_DecSetVar( &Node, 2, (pSupp[2] << 1)|(Count[2] == 1) ); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | 0; +} + + +/**Function************************************************************* + + Synopsis [Computes truth table of decomposition tree for verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_TruthDsdCompute_rec( int iNode, Vec_Int_t * vTree ) +{ + unsigned uTruthChild, uTruthTotal; + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + return s_Masks[5][ !Node.fCompl ]; + if ( Node.Type == IVY_DEC_PI ) + return s_Masks[iNode][ !Node.fCompl ]; + if ( Node.Type == IVY_DEC_BUF ) + { + uTruthTotal = Ivy_TruthDsdCompute_rec( Node.Fan0 >> 1, vTree ); + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + if ( Node.Type == IVY_DEC_AND ) + { + uTruthTotal = s_Masks[5][1]; + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + uTruthChild = Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); + uTruthTotal = (Var & 1)? uTruthTotal & ~uTruthChild : uTruthTotal & uTruthChild; + } + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + if ( Node.Type == IVY_DEC_EXOR ) + { + uTruthTotal = 0; + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + uTruthTotal ^= Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); + assert( (Var & 1) == 0 ); + } + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + assert( Node.fCompl == 0 ); + if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + unsigned uTruthChildC, uTruthChild1, uTruthChild0; + int VarC, Var1, Var0; + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + uTruthChildC = Ivy_TruthDsdCompute_rec( VarC >> 1, vTree ); + uTruthChild1 = Ivy_TruthDsdCompute_rec( Var1 >> 1, vTree ); + uTruthChild0 = Ivy_TruthDsdCompute_rec( Var0 >> 1, vTree ); + assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); + uTruthChildC = (VarC & 1)? ~uTruthChildC : uTruthChildC; + uTruthChild1 = (Var1 & 1)? ~uTruthChild1 : uTruthChild1; + uTruthChild0 = (Var0 & 1)? ~uTruthChild0 : uTruthChild0; + if ( Node.Type == IVY_DEC_MUX ) + return (uTruthChildC & uTruthChild1) | (~uTruthChildC & uTruthChild0); + else + return (uTruthChildC & uTruthChild1) | (uTruthChildC & uTruthChild0) | (uTruthChild1 & uTruthChild0); + } + assert( 0 ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Computes truth table of decomposition tree for verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ) +{ + return Ivy_TruthDsdCompute_rec( Vec_IntSize(vTree)-1, vTree ); +} + +/**Function************************************************************* + + Synopsis [Prints the decomposition tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdPrint_rec( FILE * pFile, int iNode, Vec_Int_t * vTree ) +{ + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + fprintf( pFile, "Const1%s", (Node.fCompl? "\'" : "") ); + else if ( Node.Type == IVY_DEC_PI ) + fprintf( pFile, "%c%s", 'a' + iNode, (Node.fCompl? "\'" : "") ); + else if ( Node.Type == IVY_DEC_BUF ) + { + Ivy_TruthDsdPrint_rec( pFile, Node.Fan0 >> 1, vTree ); + fprintf( pFile, "%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_AND ) + { + fprintf( pFile, "AND(" ); + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); + fprintf( pFile, "%s", (Var & 1)? "\'" : "" ); + if ( i != (int)Node.nFans-1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_EXOR ) + { + fprintf( pFile, "EXOR(" ); + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); + if ( i != (int)Node.nFans-1 ) + fprintf( pFile, "," ); + assert( (Var & 1) == 0 ); + } + fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + int VarC, Var1, Var0; + assert( Node.fCompl == 0 ); + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + fprintf( pFile, "%s", (Node.Type == IVY_DEC_MUX)? "MUX(" : "MAJ(" ); + Ivy_TruthDsdPrint_rec( pFile, VarC >> 1, vTree ); + fprintf( pFile, "%s", (VarC & 1)? "\'" : "" ); + fprintf( pFile, "," ); + Ivy_TruthDsdPrint_rec( pFile, Var1 >> 1, vTree ); + fprintf( pFile, "%s", (Var1 & 1)? "\'" : "" ); + fprintf( pFile, "," ); + Ivy_TruthDsdPrint_rec( pFile, Var0 >> 1, vTree ); + fprintf( pFile, "%s", (Var0 & 1)? "\'" : "" ); + fprintf( pFile, ")" ); + } + else assert( 0 ); +} + + +/**Function************************************************************* + + Synopsis [Prints the decomposition tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ) +{ + fprintf( pFile, "F = " ); + Ivy_TruthDsdPrint_rec( pFile, Vec_IntSize(vTree)-1, vTree ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Implement DSD in the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ManDsdConstruct_rec( Ivy_Man_t * p, Vec_Int_t * vFront, int iNode, Vec_Int_t * vTree ) +{ + Ivy_Obj_t * pResult, * pChild, * pNodes[16]; + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + return Ivy_NotCond( Ivy_ManConst1(p), Node.fCompl ); + if ( Node.Type == IVY_DEC_PI ) + { + pResult = Ivy_ManObj( p, Vec_IntEntry(vFront, iNode) ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + if ( Node.Type == IVY_DEC_BUF ) + { + pResult = Ivy_ManDsdConstruct_rec( p, vFront, Node.Fan0 >> 1, vTree ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + if ( Node.Type == IVY_DEC_AND || Node.Type == IVY_DEC_EXOR ) + { + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + assert( Node.Type == IVY_DEC_AND || (Var & 1) == 0 ); + pChild = Ivy_ManDsdConstruct_rec( p, vFront, Var >> 1, vTree ); + pChild = Ivy_NotCond( pChild, (Var & 1) ); + pNodes[i] = pChild; + } + +// Ivy_MultiEval( pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); + + pResult = Ivy_Multi( p, pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + assert( Node.fCompl == 0 ); + if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + int VarC, Var1, Var0; + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + pNodes[0] = Ivy_ManDsdConstruct_rec( p, vFront, VarC >> 1, vTree ); + pNodes[1] = Ivy_ManDsdConstruct_rec( p, vFront, Var1 >> 1, vTree ); + pNodes[2] = Ivy_ManDsdConstruct_rec( p, vFront, Var0 >> 1, vTree ); + assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); + pNodes[0] = Ivy_NotCond( pNodes[0], (VarC & 1) ); + pNodes[1] = Ivy_NotCond( pNodes[1], (Var1 & 1) ); + pNodes[2] = Ivy_NotCond( pNodes[2], (Var0 & 1) ); + if ( Node.Type == IVY_DEC_MUX ) + return Ivy_Mux( p, pNodes[0], pNodes[1], pNodes[2] ); + else + return Ivy_Maj( p, pNodes[0], pNodes[1], pNodes[2] ); + } + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Implement DSD in the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ) +{ + int Entry, i; + // implement latches on the frontier (TEMPORARY!!!) + Vec_IntForEachEntry( vFront, Entry, i ) + Vec_IntWriteEntry( vFront, i, Ivy_LeafId(Entry) ); + // recursively construct the tree + return Ivy_ManDsdConstruct_rec( p, vFront, Vec_IntSize(vTree)-1, vTree ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdComputePrint( unsigned uTruth ) +{ + static Vec_Int_t * vTree = NULL; + if ( vTree == NULL ) + vTree = Vec_IntAlloc( 12 ); + if ( Ivy_TruthDsd( uTruth, vTree ) ) + Ivy_TruthDsdPrint( stdout, vTree ); + else + printf( "Undecomposable\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTestOne( unsigned uTruth ) +{ + static int Counter = 0; + static Vec_Int_t * vTree = NULL; + // decompose + if ( vTree == NULL ) + vTree = Vec_IntAlloc( 12 ); + + if ( !Ivy_TruthDsd( uTruth, vTree ) ) + { +// printf( "Undecomposable\n" ); + } + else + { +// nTruthDsd++; + printf( "%5d : ", Counter++ ); + Extra_PrintBinary( stdout, &uTruth, 32 ); + printf( " " ); + Ivy_TruthDsdPrint( stdout, vTree ); + if ( uTruth != Ivy_TruthDsdCompute(vTree) ) + printf( "Verification failed.\n" ); + } +// Vec_IntFree( vTree ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + + pFile = fopen( "npn4.txt", "r" ); + for ( i = 0; i < 222; i++ ) +// pFile = fopen( "npn5.txt", "r" ); +// for ( i = 0; i < 616126; i++ ) + { + fscanf( pFile, "%s", Buffer ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); +// Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); + uTruth |= (uTruth << 16); +// uTruth = ~uTruth; + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest3() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + + pFile = fopen( "npn3.txt", "r" ); + for ( i = 0; i < 14; i++ ) + { + fscanf( pFile, "%s", Buffer ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 3 ); + uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24); + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest5() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + +// pFile = fopen( "npn4.txt", "r" ); +// for ( i = 0; i < 222; i++ ) + pFile = fopen( "npn5.txt", "r" ); + for ( i = 0; i < 616126; i++ ) + { + fscanf( pFile, "%s", Buffer ); +// Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); +// uTruth |= (uTruth << 16); +// uTruth = ~uTruth; + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyFanout.c b/src/aig/ivy/ivyFanout.c new file mode 100644 index 00000000..3930186a --- /dev/null +++ b/src/aig/ivy/ivyFanout.c @@ -0,0 +1,309 @@ +/**CFile**************************************************************** + + FileName [ivyFanout.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Representation of the fanouts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFanout.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// getting hold of the next fanout of the node +static inline Ivy_Obj_t * Ivy_ObjNextFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( pFanout == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return pFanout->pNextFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return pFanout->pNextFan1; +} + +// getting hold of the previous fanout of the node +static inline Ivy_Obj_t * Ivy_ObjPrevFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( pFanout == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return pFanout->pPrevFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return pFanout->pPrevFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return &pFanout->pNextFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return &pFanout->pNextFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return &pFanout->pPrevFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return &pFanout->pPrevFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjPrevNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + pTemp = Ivy_ObjPrevFanout(pObj, pFanout); + if ( pTemp == NULL ) + return &pObj->pFanout; + if ( Ivy_ObjFanin0(pTemp) == pObj ) + return &pTemp->pNextFan0; + assert( Ivy_ObjFanin1(pTemp) == pObj ); + return &pTemp->pNextFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjNextPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + pTemp = Ivy_ObjNextFanout(pObj, pFanout); + if ( pTemp == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pTemp) == pObj ) + return &pTemp->pPrevFan0; + assert( Ivy_ObjFanin1(pTemp) == pObj ); + return &pTemp->pPrevFan1; +} + +// iterator through the fanouts of the node +#define Ivy_ObjForEachFanoutInt( pObj, pFanout ) \ + for ( pFanout = (pObj)->pFanout; pFanout; \ + pFanout = Ivy_ObjNextFanout(pObj, pFanout) ) + +// safe iterator through the fanouts of the node +#define Ivy_ObjForEachFanoutIntSafe( pObj, pFanout, pFanout2 ) \ + for ( pFanout = (pObj)->pFanout, \ + pFanout2 = Ivy_ObjNextFanout(pObj, pFanout); \ + pFanout; \ + pFanout = pFanout2, \ + pFanout2 = Ivy_ObjNextFanout(pObj, pFanout) ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the fanout representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStartFanout( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( !p->fFanout ); + p->fFanout = 1; + Ivy_ManForEachObj( p, pObj, i ) + { + if ( Ivy_ObjFanin0(pObj) ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); + if ( Ivy_ObjFanin1(pObj) ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Stops the fanout representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStopFanout( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->fFanout ); + p->fFanout = 0; + Ivy_ManForEachObj( p, pObj, i ) + pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Add the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) +{ + assert( p->fFanout ); + if ( pFanin->pFanout ) + { + *Ivy_ObjNextFanoutPlace(pFanin, pFanout) = pFanin->pFanout; + *Ivy_ObjPrevFanoutPlace(pFanin, pFanin->pFanout) = pFanout; + } + pFanin->pFanout = pFanout; +} + +/**Function************************************************************* + + Synopsis [Removes the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t ** ppPlace1, ** ppPlace2, ** ppPlaceN; + assert( pFanin->pFanout != NULL ); + + ppPlace1 = Ivy_ObjNextFanoutPlace(pFanin, pFanout); + ppPlaceN = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanout); + assert( *ppPlaceN == pFanout ); + if ( ppPlaceN ) + *ppPlaceN = *ppPlace1; + + ppPlace2 = Ivy_ObjPrevFanoutPlace(pFanin, pFanout); + ppPlaceN = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanout); + assert( ppPlaceN == NULL || *ppPlaceN == pFanout ); + if ( ppPlaceN ) + *ppPlaceN = *ppPlace2; + + *ppPlace1 = NULL; + *ppPlace2 = NULL; +} + +/**Function************************************************************* + + Synopsis [Replaces the fanout of pOld to be pFanoutNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ) +{ + Ivy_Obj_t ** ppPlace; + ppPlace = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanoutOld); + assert( *ppPlace == pFanoutOld ); + if ( ppPlace ) + *ppPlace = pFanoutNew; + ppPlace = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanoutOld); + assert( ppPlace == NULL || *ppPlace == pFanoutOld ); + if ( ppPlace ) + *ppPlace = pFanoutNew; + // assuming that pFanoutNew already points to the next fanout +} + +/**Function************************************************************* + + Synopsis [Starts iteration through the fanouts.] + + Description [Copies the currently available fanouts into the array.] + + SideEffects [Can be used while the fanouts are being removed.] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ) +{ + Ivy_Obj_t * pFanout; + assert( p->fFanout ); + assert( !Ivy_IsComplement(pObj) ); + Vec_PtrClear( vArray ); + Ivy_ObjForEachFanoutInt( pObj, pFanout ) + Vec_PtrPush( vArray, pFanout ); +} + +/**Function************************************************************* + + Synopsis [Reads one fanout.] + + Description [Returns fanout if there is only one fanout.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + return pObj->pFanout; +} + +/**Function************************************************************* + + Synopsis [Reads one fanout.] + + Description [Returns fanout if there is only one fanout.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + int Counter = 0; + Ivy_ObjForEachFanoutInt( pObj, pFanout ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyFastMap.c b/src/aig/ivy/ivyFastMap.c new file mode 100644 index 00000000..c4a043f2 --- /dev/null +++ b/src/aig/ivy/ivyFastMap.c @@ -0,0 +1,1593 @@ +/**CFile**************************************************************** + + FileName [ivyFastMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Fast FPGA mapping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_INFINITY 10000 + +typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t; +struct Ivy_SuppMan_t_ +{ + int nLimit; // the limit on the number of inputs + int nObjs; // the number of entries + int nSize; // size of each entry in bytes + char * pMem; // memory allocated + Vec_Vec_t * vLuts; // the array of nodes used in the mapping +}; + +typedef struct Ivy_Supp_t_ Ivy_Supp_t; +struct Ivy_Supp_t_ +{ + char nSize; // the number of support nodes + char fMark; // multipurpose mask + char fMark2; // multipurpose mask + char fMark3; // multipurpose mask + int nRefs; // the number of references + short Delay; // the delay of the node + short DelayR; // the reverse delay of the node + int pArray[0]; // the support nodes +}; + +static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize); +} +static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->fMark = 0; + pSupp->Delay = 0; + pSupp->nSize = 1; + pSupp->pArray[0] = pObj->Id; + return pSupp; +} + +static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr ); +static int Ivy_FastMapDelay( Ivy_Man_t * pAig ); +static int Ivy_FastMapArea( Ivy_Man_t * pAig ); +static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); +static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); +static int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ); +static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ); +static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ); +static int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ); +static int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); + + +extern int s_MappingTime; +extern int s_MappingMem; + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fast K-LUT mapping of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ) +{ + Ivy_SuppMan_t * pMan; + Ivy_Obj_t * pObj; + int i, Delay, Area, clk, clkTotal = clock(); + // start the memory for supports + pMan = ALLOC( Ivy_SuppMan_t, 1 ); + memset( pMan, 0, sizeof(Ivy_SuppMan_t) ); + pMan->nLimit = nLimit; + pMan->nObjs = Ivy_ManObjIdMax(pAig) + 1; + pMan->nSize = sizeof(Ivy_Supp_t) + nLimit * sizeof(int); + pMan->pMem = (char *)malloc( pMan->nObjs * pMan->nSize ); + memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize ); + pMan->vLuts = Vec_VecAlloc( 100 ); + pAig->pData = pMan; +clk = clock(); + // set the PI mapping + Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) ); + Ivy_ManForEachPi( pAig, pObj, i ) + Ivy_ObjSuppStart( pAig, pObj ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNode( pAig, pObj, nLimit ); + // find the best arrival time and area + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Delay oriented mapping: " ); + +// 2-1-2 (doing 2-1-2-1-2 improves 0.5%) + + if ( fRecovery ) + { +clk = clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // remap the nodes + Ivy_FastMapRecover( pAig, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " ); + +clk = clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNodeArea( pAig, pObj, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 1 : " ); + +clk = clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // remap the nodes + Ivy_FastMapRecover( pAig, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " ); + } + + + s_MappingTime = clock() - clkTotal; + s_MappingMem = pMan->nObjs * pMan->nSize; +/* + { + Vec_Ptr_t * vNodes; + vNodes = Vec_PtrAlloc( 100 ); + Vec_VecForEachEntry( pMan->vLuts, pObj, i, k ) + Vec_PtrPush( vNodes, pObj ); + Ivy_ManShow( pAig, 0, vNodes ); + Vec_PtrFree( vNodes ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Cleans memory used for decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapStop( Ivy_Man_t * pAig ) +{ + Ivy_SuppMan_t * p = pAig->pData; + Vec_VecFree( p->vLuts ); + free( p->pMem ); + free( p ); + pAig->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Prints statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr ) +{ + printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area ); + PRT( "Time", Time ); +} + +/**Function************************************************************* + + Synopsis [Computes delay after LUT mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapDelay( Ivy_Man_t * pAig ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pObj; + int i, DelayMax = 0; + Ivy_ManForEachPo( pAig, pObj, i ) + { + pObj = Ivy_ObjFanin0(pObj); + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pSupp = Ivy_ObjSupp( pAig, pObj ); + if ( DelayMax < pSupp->Delay ) + DelayMax = pSupp->Delay; + } + return DelayMax; +} + +/**Function************************************************************* + + Synopsis [Computes area after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts ) +{ + Ivy_Supp_t * pSupp; + int i, Counter; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // skip visited nodes and PIs + if ( pSupp->fMark || pSupp->nSize == 1 ) + return 0; + pSupp->fMark = 1; + // compute the area of this node + Counter = 0; + for ( i = 0; i < pSupp->nSize; i++ ) + Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts ); + // add the node to the array of LUTs + Vec_VecPush( vLuts, pSupp->Delay, pObj ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Computes area after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapArea( Ivy_Man_t * pAig ) +{ + Vec_Vec_t * vLuts; + Ivy_Obj_t * pObj; + int i, Counter = 0; + // get the array to store the nodes + vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; + Vec_VecClear( vLuts ); + // explore starting from each node + Ivy_ManForEachPo( pAig, pObj, i ) + Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts ); + // clean the marks + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_ObjSupp( pAig, pObj )->fMark = 0; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj ) +{ + return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj ) +{ + return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntSelectSort( int * pArray, int nSize ) +{ + int temp, i, j, best_i; + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( pArray[j] < pArray[best_i] ) + best_i = j; + temp = pArray[i]; + pArray[i] = pArray[best_i]; + pArray[best_i] = temp; + } +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntRemoveDup( int * pArray, int nSize ) +{ + int i, k; + if ( nSize < 2 ) + return nSize; + for ( i = k = 1; i < nSize; i++ ) + if ( pArray[i] != pArray[i-1] ) + pArray[k++] = pArray[i]; + return k; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + static int Store[32], StoreSize; + static char Supp0[16], Supp1[16]; + static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; + static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; + Ivy_Obj_t * pFanin0, * pFanin1; + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int RetValue, DelayOld; + assert( nLimit <= 32 ); + assert( Ivy_ObjIsNode(pObj) ); + // get the fanins + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); + pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->fMark == 0 ); + // get the old delay of the node + DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); + assert( DelayOld <= pSupp->DelayR ); + // copy the current cut + memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); + StoreSize = pSupp->nSize; + // get the fanin support + if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR ) + { + pSupp0 = pTemp0; + pSupp0->nSize = 1; + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // get the fanin support + if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR ) + { + pSupp1 = pTemp1; + pSupp1->nSize = 1; + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + // check the resulting delay + pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); + if ( pSupp->Delay > pSupp->DelayR ) + { + pSupp->nSize = StoreSize; + memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); + pSupp->Delay = DelayOld; + } +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + static int Store[32], StoreSize; + static char Supp0[16], Supp1[16]; + static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; + static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; + Ivy_Obj_t * pFanin0, * pFanin1; + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int RetValue, DelayOld, RefsOld; + int AreaBef, AreaAft; + assert( nLimit <= 32 ); + assert( Ivy_ObjIsNode(pObj) ); + // get the fanins + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); + pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->fMark == 0 ); + + // get the area + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); +// if ( AreaBef == 1 ) +// return; + + // deref the cut if the node is refed + if ( pSupp->nRefs != 0 ) + Ivy_FastMapNodeDeref( pAig, pObj ); + + // get the old delay of the node + DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); + assert( DelayOld <= pSupp->DelayR ); + // copy the current cut + memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); + StoreSize = pSupp->nSize; + // get the fanin support + if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR ) +// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results + { + pSupp0 = pTemp0; + pSupp0->nSize = 1; + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // get the fanin support + if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR ) +// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR ) + { + pSupp1 = pTemp1; + pSupp1->nSize = 1; + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + + // check the resulting delay + pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); + + RefsOld = pSupp->nRefs; pSupp->nRefs = 0; + AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + pSupp->nRefs = RefsOld; + + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) +// if ( pSupp->Delay > pSupp->DelayR ) + { + pSupp->nSize = StoreSize; + memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); + pSupp->Delay = DelayOld; +// printf( "-" ); + } +// else +// printf( "+" ); + + if ( pSupp->nRefs != 0 ) + Ivy_FastMapNodeRef( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int fFaninParam = 2; + int RetValue; + assert( Ivy_ObjIsNode(pObj) ); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->fMark = 0; + // get the delays + if ( pSupp0->Delay == pSupp1->Delay ) + pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay; + else if ( pSupp0->Delay > pSupp1->Delay ) + { + pSupp->Delay = pSupp0->Delay; + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + else // if ( pSupp0->Delay < pSupp1->Delay ) + { + pSupp->Delay = pSupp1->Delay; + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->Delay++; + if ( fFaninParam == 2 ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + else if ( fFaninParam == 3 ) + { + Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + pSupp->nSize = 0; + // process the first fanin + if ( Ivy_ObjIsNodeInt1(pFanin0) ) + { + pFaninA = Ivy_ObjFanin0(pFanin0); + pFaninB = Ivy_ObjFanin1(pFanin0); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); + else + { + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); + // process the second fanin + if ( Ivy_ObjIsNodeInt1(pFanin1) ) + { + pFaninA = Ivy_ObjFanin0(pFanin1); + pFaninB = Ivy_ObjFanin1(pFanin1); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); + else + { + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); + // sort the fanins + Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); + pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); + assert( pSupp->pArray[0] < pSupp->pArray[1] ); + } + else if ( fFaninParam == 4 ) + { + Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + pSupp->nSize = 0; + // consider the case when exactly one of them is internal + if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) ) + { + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); + if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit ) + { + pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp1->pArray[0] = Ivy_ObjId(pFanin1); + // merge the cuts + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + assert( RetValue ); + assert( pSupp->nSize > 1 ); + return; + } + if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit ) + { + pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 ); + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp0->pArray[0] = Ivy_ObjId(pFanin0); + // merge the cuts + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + assert( RetValue ); + assert( pSupp->nSize > 1 ); + return; + } + } + // process the first fanin + if ( Ivy_ObjIsNodeInt1(pFanin0) ) + { + pFaninA = Ivy_ObjFanin0(pFanin0); + pFaninB = Ivy_ObjFanin1(pFanin0); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); + else + { + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); + // process the second fanin + if ( Ivy_ObjIsNodeInt1(pFanin1) ) + { + pFaninA = Ivy_ObjFanin0(pFanin1); + pFaninB = Ivy_ObjFanin1(pFanin1); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); + else + { + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); + // sort the fanins + Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); + pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); + assert( pSupp->pArray[0] < pSupp->pArray[1] ); + assert( pSupp->nSize > 1 ); + } + } + assert( pSupp->Delay > 0 ); +} + +/**Function************************************************************* + + Synopsis [Merges two supports] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ) +{ + int i, k, c; + assert( pSupp0->nSize >= pSupp1->nSize ); + // the case of the largest cut sizes + if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit ) + { + for ( i = 0; i < pSupp0->nSize; i++ ) + if ( pSupp0->pArray[i] != pSupp1->pArray[i] ) + return 0; + for ( i = 0; i < pSupp0->nSize; i++ ) + pSupp->pArray[i] = pSupp0->pArray[i]; + pSupp->nSize = pSupp0->nSize; + return 1; + } + // the case when one of the cuts is the largest + if ( pSupp0->nSize == nLimit ) + { + for ( i = 0; i < pSupp1->nSize; i++ ) + { + for ( k = pSupp0->nSize - 1; k >= 0; k-- ) + if ( pSupp0->pArray[k] == pSupp1->pArray[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < pSupp0->nSize; i++ ) + pSupp->pArray[i] = pSupp0->pArray[i]; + pSupp->nSize = pSupp0->nSize; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < nLimit; c++ ) + { + if ( k == pSupp1->nSize ) + { + if ( i == pSupp0->nSize ) + { + pSupp->nSize = c; + return 1; + } + pSupp->pArray[c] = pSupp0->pArray[i++]; + continue; + } + if ( i == pSupp0->nSize ) + { + if ( k == pSupp1->nSize ) + { + pSupp->nSize = c; + return 1; + } + pSupp->pArray[c] = pSupp1->pArray[k++]; + continue; + } + if ( pSupp0->pArray[i] < pSupp1->pArray[k] ) + { + pSupp->pArray[c] = pSupp0->pArray[i++]; + continue; + } + if ( pSupp0->pArray[i] > pSupp1->pArray[k] ) + { + pSupp->pArray[c] = pSupp1->pArray[k++]; + continue; + } + pSupp->pArray[c] = pSupp0->pArray[i++]; + k++; + } + if ( i < pSupp0->nSize || k < pSupp1->nSize ) + return 0; + pSupp->nSize = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Creates integer vector with the support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + vLeaves->nCap = 8; + vLeaves->nSize = pSupp->nSize; + vLeaves->pArray = pSupp->pArray; +} + +/**Function************************************************************* + + Synopsis [Sets the required times of the intermediate nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) ) + return; + Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR ); + Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR ); +// assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY ); + pSupp->DelayR = DelayR; +} + +/**Function************************************************************* + + Synopsis [Computes the required times for each node.] + + Description [Sets reference counters for each node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ) +{ + Vec_Vec_t * vLuts; + Vec_Ptr_t * vNodes; + Ivy_Obj_t * pObj; + Ivy_Supp_t * pSupp, * pSuppF; + int i, k, c; + // clean the required times + Ivy_ManForEachPi( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->DelayR = IVY_INFINITY; + pSupp->nRefs = 0; + } + Ivy_ManForEachNode( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->DelayR = IVY_INFINITY; + pSupp->nRefs = 0; + } + // set the required times of the POs + Ivy_ManForEachPo( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp->DelayR = Delay; + pSupp->nRefs++; + } + // get the levelized nodes used in the mapping + vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; + // propagate the required times + Vec_VecForEachLevelReverse( vLuts, vNodes, i ) + Vec_PtrForEachEntry( vNodes, pObj, k ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs > 0 ); + for ( c = 0; c < pSupp->nSize; c++ ) + { + pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); + pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 ); + pSuppF->nRefs++; + } + } +/* + // print out some of the required times + Ivy_ManForEachPi( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + printf( "%d ", pSupp->DelayR ); + } + printf( "\n" ); +*/ + + if ( fSetInter ) + { + // set the required times of the intermediate nodes + Vec_VecForEachLevelReverse( vLuts, vNodes, i ) + Vec_PtrForEachEntry( vNodes, pObj, k ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR ); + } + // make sure that all required times are assigned + Ivy_ManForEachNode( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->DelayR < IVY_INFINITY ); + } + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ) +{ + Vec_Ptr_t * vFront, * vFrontOld; + Ivy_Obj_t * pObj; + int i; + vFront = Vec_PtrAlloc( nLimit ); + vFrontOld = Vec_PtrAlloc( nLimit ); + Ivy_ManCleanTravId( pAig ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld ); + Vec_PtrFree( vFrontOld ); + Vec_PtrFree( vFront ); +} + +/**Function************************************************************* + + Synopsis [Computes the delay of the cut rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + int c, Delay = 0; + pSupp = Ivy_ObjSupp( pAig, pObj ); + for ( c = 0; c < pSupp->nSize; c++ ) + { + pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); + Delay = IVY_MAX( Delay, pSuppF->Delay ); + } + return 1 + Delay; +} + + +/**function************************************************************* + + synopsis [References the cut.] + + description [This procedure is similar to the procedure NodeReclaim.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + Ivy_Obj_t * pNodeChild; + int aArea, i; + // start the area of this cut + aArea = 1; + // go through the children + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nSize > 1 ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); + pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); + assert( pSuppF->nRefs >= 0 ); + if ( pSuppF->nRefs++ > 0 ) + continue; + if ( pSuppF->nSize == 1 ) + continue; + aArea += Ivy_FastMapNodeRef( pAig, pNodeChild ); + } + return aArea; +} + +/**function************************************************************* + + synopsis [Dereferences the cut.] + + description [This procedure is similar to the procedure NodeRecusiveDeref.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + Ivy_Obj_t * pNodeChild; + int aArea, i; + // start the area of this cut + aArea = 1; + // go through the children + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nSize > 1 ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); + pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); + assert( pSuppF->nRefs > 0 ); + if ( --pSuppF->nRefs > 0 ) + continue; + if ( pSuppF->nSize == 1 ) + continue; + aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild ); + } + return aArea; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + int aResult, aResult2; + if ( Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsNode(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs > 0 ); + aResult = Ivy_FastMapNodeDeref( pAig, pObj ); + aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); + assert( aResult == aResult2 ); + return aResult; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + int aResult, aResult2; + if ( Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsNode(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs == 0 ); + aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); + aResult = Ivy_FastMapNodeDeref( pAig, pObj ); + assert( aResult == aResult2 ); + return aResult; +} + + + + +/**Function************************************************************* + + Synopsis [Counts the number of nodes with no external fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront ) +{ + Ivy_Supp_t * pSuppF; + Ivy_Obj_t * pFanin; + int i, Counter = 0; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( pSuppF->nRefs == 0 ) + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) ) + return; + assert( Ivy_ObjIsNode(pObj) ); + Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) ); + Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) ); + Ivy_ObjSetTravIdCurrent(pAig, pObj); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the number of fanins will grow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanin0, * pFanin1; + assert( Ivy_ObjIsNode(pObj) ); + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1); +} + +/**Function************************************************************* + + Synopsis [Returns the increase in the number of fanins with no external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSuppF; + Ivy_Obj_t * pFanin; + int Counter = 0; + assert( Ivy_ObjIsNode(pObj) ); + // check if the node has external refs + pSuppF = Ivy_ObjSupp( pAig, pObj ); + if ( pSuppF->nRefs == 0 ) + Counter--; + // increment the number of fanins without external refs + pFanin = Ivy_ObjFanin0(pObj); + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) + Counter++; + // increment the number of fanins without external refs + pFanin = Ivy_ObjFanin1(pObj); + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Updates the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + assert( Ivy_ObjIsNode(pObj) ); + Vec_PtrRemove( vFront, pObj ); + pFanin = Ivy_ObjFanin0(pObj); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) + { + Ivy_ObjSetTravIdCurrent(pAig, pFanin); + Vec_PtrPush( vFront, pFanin ); + } + pFanin = Ivy_ObjFanin1(pObj); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) + { + Ivy_ObjSetTravIdCurrent(pAig, pFanin); + Vec_PtrPush( vFront, pFanin ); + } +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) ) + return 1; + if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) ) + return 1; + if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) ) + return 1; + assert( Vec_PtrSize(vFront) <= nLimit ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) ); +} + +/**Function************************************************************* + + Synopsis [Prepares node mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pFanin; + int i; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // expand the cut downwards from the given place + Vec_PtrClear( vFront ); + Vec_PtrClear( vFrontOld ); + Ivy_ManIncrementTravId( pAig ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]); + Vec_PtrPush( vFront, pFanin ); + Vec_PtrPush( vFrontOld, pFanin ); + Ivy_ObjSetTravIdCurrent( pAig, pFanin ); + } + // mark the nodes in the cone + Ivy_FastMapMark_rec( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pFanin; + int i; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // deref node's cut + Ivy_FastMapNodeDeref( pAig, pObj ); + // update the node's cut + pSupp->nSize = Vec_PtrSize(vFront); + Vec_PtrForEachEntry( vFront, pFanin, i ) + pSupp->pArray[i] = pFanin->Id; + // ref the new cut + Ivy_FastMapNodeRef( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + pSupp = Ivy_ObjSupp( pAig, pObj ); +// if ( pSupp->nRefs == 0 ) +// return; + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + // get the area + if ( AreaBef == 1 ) + return; + + if ( pSupp->nRefs == 0 ) + { + pSupp->nRefs = 1000000; + Ivy_FastMapNodeRef( pAig, pObj ); + } + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + } + if ( pSupp->nRefs == 1000000 ) + { + pSupp->nRefs = 0; + Ivy_FastMapNodeDeref( pAig, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + int DelayOld; + pSupp = Ivy_ObjSupp( pAig, pObj ); + DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + assert( pSupp->Delay <= pSupp->DelayR ); + if ( pSupp->nRefs == 0 ) + return; + // get the area + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); +// if ( AreaBef == 1 ) +// return; + if ( pObj->Id == 102 ) + { + int x = 0; + } + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + Ivy_FastMapNodeDeref( pAig, pObj ); + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeRef( pAig, pObj ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + pSupp->Delay = DelayOld; + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + int DelayOld; + pSupp = Ivy_ObjSupp( pAig, pObj ); + DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + assert( pSupp->Delay <= pSupp->DelayR ); +// if ( pSupp->nRefs == 0 ) +// return; +// AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + // get the area + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaBef == 1 ) + return; + + if ( pSupp->nRefs == 0 ) + { + pSupp->nRefs = 1000000; + Ivy_FastMapNodeRef( pAig, pObj ); + } + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + pSupp->Delay = DelayOld; + } + if ( pSupp->nRefs == 1000000 ) + { + pSupp->nRefs = 0; + Ivy_FastMapNodeDeref( pAig, pObj ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyFpga.c b/src/aig/ivy/ivyFpga.c new file mode 100644 index 00000000..122cc0e2 --- /dev/null +++ b/src/aig/ivy/ivyFpga.c @@ -0,0 +1,378 @@ +/**CFile**************************************************************** + + FileName [ivyFpga.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Prepares the AIG package to work as an FPGA mapper.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFpga.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" +#include "attr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_FpgaMan_t_ Ivy_FpgaMan_t; +typedef struct Ivy_FpgaObj_t_ Ivy_FpgaObj_t; +typedef struct Ivy_FpgaCut_t_ Ivy_FpgaCut_t; + +// manager +struct Ivy_FpgaMan_t_ +{ + Ivy_Man_t * pManIvy; // the AIG manager + Attr_Man_t * pManAttr; // the attribute manager + int nLutSize; // the LUT size + int nCutsMax; // the max number of cuts + int nEntrySize; // the size of the entry + int nEntryBase; // the size of the entry minus cut leaf arrays + int fVerbose; // the verbosity flag + // temporary cut storage + Ivy_FpgaCut_t * pCutStore; // the temporary cuts +}; + +// priority cut +struct Ivy_FpgaCut_t_ +{ + float Delay; // the delay of the cut + float AreaFlow; // the area flow of the cut + float Area; // the area of the cut + int nLeaves; // the number of leaves + int * pLeaves; // the array of fanins +}; + +// node extension +struct Ivy_FpgaObj_t_ +{ + unsigned Type : 4; // type + unsigned nCuts : 28; // the number of cuts + int Id; // integer ID + int nRefs; // the number of references + Ivy_FpgaObj_t * pFanin0; // the first fanin + Ivy_FpgaObj_t * pFanin1; // the second fanin + float Required; // required time of the onde + Ivy_FpgaCut_t * pCut; // the best cut + Ivy_FpgaCut_t Cuts[0]; // the cuts of the node +}; + + +static Ivy_FpgaMan_t * Ivy_ManFpgaPrepare( Ivy_Man_t * p, int nLutSize, int nCutsMax, int fVerbose ); +static void Ivy_ManFpgaUndo( Ivy_FpgaMan_t * pFpga ); +static void Ivy_ObjFpgaCreate( Ivy_FpgaMan_t * pFpga, int ObjId ); +static void Ivy_ManFpgaDelay( Ivy_FpgaMan_t * pFpga ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManFpga( Ivy_Man_t * p, int nLutSize, int nCutsMax, int fVerbose ) +{ + Ivy_FpgaMan_t * pFpga; + pFpga = Ivy_ManFpgaPrepare( p, nLutSize, nCutsMax, fVerbose ); + Ivy_ManFpgaDelay( pFpga ); + Ivy_ManFpgaUndo( pFpga ); +} + +/**Function************************************************************* + + Synopsis [Prepares manager for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_FpgaMan_t * Ivy_ManFpgaPrepare( Ivy_Man_t * p, int nLutSize, int nCutsMax, int fVerbose ) +{ + Ivy_FpgaMan_t * pFpga; + Ivy_Obj_t * pObj; + int i; + pFpga = ALLOC( Ivy_FpgaMan_t, 1 ); + memset( pFpga, 0, sizeof(Ivy_FpgaMan_t) ); + // compute the size of the node + pFpga->pManIvy = p; + pFpga->nLutSize = nLutSize; + pFpga->nCutsMax = nCutsMax; + pFpga->fVerbose = fVerbose; + pFpga->nEntrySize = sizeof(Ivy_FpgaObj_t) + (nCutsMax + 1) * (sizeof(Ivy_FpgaCut_t) + sizeof(int) * nLutSize); + pFpga->nEntryBase = sizeof(Ivy_FpgaObj_t) + (nCutsMax + 1) * (sizeof(Ivy_FpgaCut_t)); + pFpga->pManAttr = Attr_ManStartPtrMem( Ivy_ManObjIdMax(p) + 1, pFpga->nEntrySize ); + if ( fVerbose ) + printf( "Entry size = %d. Total memory = %5.2f Mb.\n", pFpga->nEntrySize, + 1.0 * pFpga->nEntrySize * (Ivy_ManObjIdMax(p) + 1) / (1<<20) ); + // connect memory for cuts + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjFpgaCreate( pFpga, pObj->Id ); + // create temporary cuts + pFpga->pCutStore = (Ivy_FpgaCut_t *)ALLOC( char, pFpga->nEntrySize * (nCutsMax + 1) * (nCutsMax + 1) ); + memset( pFpga->pCutStore, 0, pFpga->nEntrySize * (nCutsMax + 1) * (nCutsMax + 1) ); + { + int i, * pArrays; + pArrays = (int *)((char *)pFpga->pCutStore + sizeof(Ivy_FpgaCut_t) * (nCutsMax + 1) * (nCutsMax + 1)); + for ( i = 0; i < (nCutsMax + 1) * (nCutsMax + 1); i++ ) + pFpga->pCutStore[i].pLeaves = pArrays + i * pFpga->nLutSize; + } + return pFpga; +} + +/**Function************************************************************* + + Synopsis [Quits the manager for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManFpgaUndo( Ivy_FpgaMan_t * pFpga ) +{ + Attr_ManStop( pFpga->pManAttr ); + free( pFpga ); +} + + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjFpgaCreate( Ivy_FpgaMan_t * pFpga, int ObjId ) +{ + Ivy_FpgaObj_t * pObjFpga; + int i, * pArrays; + pObjFpga = Attr_ManReadAttrPtr( pFpga->pManAttr, ObjId ); + pArrays = (int *)((char *)pObjFpga + pFpga->nEntryBase); + for ( i = 0; i <= pFpga->nCutsMax; i++ ) + pObjFpga->Cuts[i].pLeaves = pArrays + i * pFpga->nLutSize; +} + + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjFpgaMerge( Ivy_FpgaCut_t * pC0, Ivy_FpgaCut_t * pC1, Ivy_FpgaCut_t * pC, int nLimit ) +{ + int i, k, c; + assert( pC0->nLeaves >= pC1->nLeaves ); + // the case of the largest cut sizes + if ( pC0->nLeaves == nLimit && pC1->nLeaves == nLimit ) + { + for ( i = 0; i < pC0->nLeaves; i++ ) + if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) + return 0; + for ( i = 0; i < pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + pC->Delay = 1 + IVY_MAX( pC0->Delay, pC1->Delay ); + return 1; + } + // the case when one of the cuts is the largest + if ( pC0->nLeaves == nLimit ) + { + for ( i = 0; i < pC1->nLeaves; i++ ) + { + for ( k = pC0->nLeaves - 1; k >= 0; k-- ) + if ( pC0->pLeaves[k] == pC1->pLeaves[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + pC->Delay = 1 + IVY_MAX( pC0->Delay, pC1->Delay ); + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < nLimit; c++ ) + { + if ( k == pC1->nLeaves ) + { + if ( i == pC0->nLeaves ) + { + pC->nLeaves = c; + pC->Delay = 1 + IVY_MAX( pC0->Delay, pC1->Delay ); + return 1; + } + pC->pLeaves[c] = pC0->pLeaves[i++]; + continue; + } + if ( i == pC0->nLeaves ) + { + if ( k == pC1->nLeaves ) + { + pC->nLeaves = c; + pC->Delay = 1 + IVY_MAX( pC0->Delay, pC1->Delay ); + return 1; + } + pC->pLeaves[c] = pC1->pLeaves[k++]; + continue; + } + if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) + { + pC->pLeaves[c] = pC0->pLeaves[i++]; + continue; + } + if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) + { + pC->pLeaves[c] = pC1->pLeaves[k++]; + continue; + } + pC->pLeaves[c] = pC0->pLeaves[i++]; + k++; + } + if ( i < pC0->nLeaves || k < pC1->nLeaves ) + return 0; + pC->nLeaves = c; + pC->Delay = 1 + IVY_MAX( pC0->Delay, pC1->Delay ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FpgaCutCompare( Ivy_FpgaCut_t * pC0, Ivy_FpgaCut_t * pC1 ) +{ + if ( pC0->Delay < pC1->Delay ) + return -1; + if ( pC0->Delay > pC1->Delay ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjFpgaDelay( Ivy_FpgaMan_t * pFpga, int ObjId, int Fan0Id, int Fan1Id ) +{ + Ivy_FpgaObj_t * pObjFpga, * pObjFpga0, * pObjFpga1; + int nCuts, i, k; + pObjFpga = Attr_ManReadAttrPtr( pFpga->pManAttr, ObjId ); + pObjFpga0 = Attr_ManReadAttrPtr( pFpga->pManAttr, Fan0Id ); + pObjFpga1 = Attr_ManReadAttrPtr( pFpga->pManAttr, Fan1Id ); + // create cross-product of the cuts + nCuts = 0; + for ( i = 0; pObjFpga0->Cuts[i].nLeaves > 0 && i < pFpga->nCutsMax; i++ ) + for ( k = 0; pObjFpga1->Cuts[k].nLeaves > 0 && k < pFpga->nCutsMax; k++ ) + if ( Ivy_ObjFpgaMerge( pObjFpga0->Cuts + i, pObjFpga1->Cuts + k, pFpga->pCutStore + nCuts, pFpga->nLutSize ) ) + nCuts++; + // sort the cuts + qsort( pFpga->pCutStore, nCuts, sizeof(Ivy_FpgaCut_t), (int (*)(const void *, const void *))Ivy_FpgaCutCompare ); + // take the first + pObjFpga->Cuts[0].nLeaves = 1; + pObjFpga->Cuts[0].pLeaves[0] = ObjId; + pObjFpga->Cuts[0].Delay = pFpga->pCutStore[0].Delay; + pObjFpga->Cuts[1] = pFpga->pCutStore[0]; +} + +/**Function************************************************************* + + Synopsis [Maps the nodes for delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManFpgaDelay( Ivy_FpgaMan_t * pFpga ) +{ + Ivy_FpgaObj_t * pObjFpga; + Ivy_Obj_t * pObj; + int i, DelayBest; + int clk = clock(); + // set arrival times and trivial cuts at const 1 and PIs + pObjFpga = Attr_ManReadAttrPtr( pFpga->pManAttr, 0 ); + pObjFpga->Cuts[0].nLeaves = 1; + Ivy_ManForEachPi( pFpga->pManIvy, pObj, i ) + { + pObjFpga = Attr_ManReadAttrPtr( pFpga->pManAttr, pObj->Id ); + pObjFpga->Cuts[0].nLeaves = 1; + pObjFpga->Cuts[0].pLeaves[0] = pObj->Id; + } + // map the internal nodes + Ivy_ManForEachNode( pFpga->pManIvy, pObj, i ) + { + Ivy_ObjFpgaDelay( pFpga, pObj->Id, Ivy_ObjFaninId0(pObj), Ivy_ObjFaninId1(pObj) ); + } + // get the best arrival time of the POs + DelayBest = 0; + Ivy_ManForEachPo( pFpga->pManIvy, pObj, i ) + { + pObjFpga = Attr_ManReadAttrPtr( pFpga->pManAttr, Ivy_ObjFanin0(pObj)->Id ); + if ( DelayBest < (int)pObjFpga->Cuts[1].Delay ) + DelayBest = (int)pObjFpga->Cuts[1].Delay; + } + printf( "Best delay = %d. ", DelayBest ); + PRT( "Time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyFraig.c b/src/aig/ivy/ivyFraig.c new file mode 100644 index 00000000..269ca257 --- /dev/null +++ b/src/aig/ivy/ivyFraig.c @@ -0,0 +1,2704 @@ +/**CFile**************************************************************** + + FileName [ivyFraig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Functional reduction of AIGs] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "satSolver.h" +#include "extra.h" +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_FraigMan_t_ Ivy_FraigMan_t; +typedef struct Ivy_FraigSim_t_ Ivy_FraigSim_t; +typedef struct Ivy_FraigList_t_ Ivy_FraigList_t; + +struct Ivy_FraigList_t_ +{ + Ivy_Obj_t * pHead; + Ivy_Obj_t * pTail; + int nItems; +}; + +struct Ivy_FraigSim_t_ +{ + int Type; + Ivy_FraigSim_t * pNext; + Ivy_FraigSim_t * pFanin0; + Ivy_FraigSim_t * pFanin1; + unsigned pData[0]; +}; + +struct Ivy_FraigMan_t_ +{ + // general info + Ivy_FraigParams_t * pParams; // various parameters + // temporary backtrack limits because "sint64" cannot be defined in Ivy_FraigParams_t ... + sint64 nBTLimitGlobal; // global limit on the number of backtracks + sint64 nInsLimitGlobal;// global limit on the number of clause inspects + // AIG manager + Ivy_Man_t * pManAig; // the starting AIG manager + Ivy_Man_t * pManFraig; // the final AIG manager + // simulation information + int nSimWords; // the number of words + char * pSimWords; // the simulation info + Ivy_FraigSim_t * pSimStart; // the list of simulation info for internal nodes + // counter example storage + int nPatWords; // the number of words in the counter example + unsigned * pPatWords; // the counter example + int * pPatScores; // the scores of each pattern + // equivalence classes + Ivy_FraigList_t lClasses; // equivalence classes + Ivy_FraigList_t lCand; // candidatates + int nPairs; // the number of pairs of nodes + // equivalence checking + sat_solver * pSat; // SAT solver + int nSatVars; // the number of variables currently used + Vec_Ptr_t * vPiVars; // the PIs of the cone used + // other + ProgressBar * pProgress; + // statistics + int nSimRounds; + int nNodesMiter; + int nClassesZero; + int nClassesBeg; + int nClassesEnd; + int nPairsBeg; + int nPairsEnd; + int nSatCalls; + int nSatCallsSat; + int nSatCallsUnsat; + int nSatProof; + int nSatFails; + int nSatFailsReal; + // runtime + int timeSim; + int timeTrav; + int timeSat; + int timeSatUnsat; + int timeSatSat; + int timeSatFail; + int timeRef; + int timeTotal; + int time1; + int time2; +}; + +typedef struct Prove_ParamsStruct_t_ Prove_Params_t; +struct Prove_ParamsStruct_t_ +{ + // general parameters + int fUseFraiging; // enables fraiging + int fUseRewriting; // enables rewriting + int fUseBdds; // enables BDD construction when other methods fail + int fVerbose; // prints verbose stats + // iterations + int nItersMax; // the number of iterations + // mitering + int nMiteringLimitStart; // starting mitering limit + float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // rewriting + int nRewritingLimitStart; // the number of rewriting iterations + float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // fraiging + int nFraigingLimitStart; // starting backtrack(conflict) limit + float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // last-gasp BDD construction + int nBddSizeLimit; // the number of BDD nodes when construction is aborted + int fBddReorder; // enables dynamic BDD variable reordering + // last-gasp mitering + int nMiteringLimitLast; // final mitering limit + // global SAT solver limits + sint64 nTotalBacktrackLimit; // global limit on the number of backtracks + sint64 nTotalInspectLimit; // global limit on the number of clause inspects + // global resources applied + sint64 nTotalBacktracksMade; // the total number of backtracks made + sint64 nTotalInspectsMade; // the total number of inspects made +}; + +static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj ) { return (Ivy_FraigSim_t *)pObj->pFanout; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj ) { return pObj->pNextFan1; } +static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } +static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } +static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj ) { return pObj->pPrevFan1; } +static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj ) { return pObj->pEquiv; } +static inline int Ivy_ObjSatNum( Ivy_Obj_t * pObj ) { return (int)pObj->pNextFan0; } +static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj ) { return (Vec_Ptr_t *)pObj->pNextFan1; } + +static inline void Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim ) { pObj->pFanout = (Ivy_Obj_t *)pSim; } +static inline void Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; } +static inline void Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; } +static inline void Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; } +static inline void Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } +static inline void Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } +static inline void Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; } +static inline void Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode ) { pObj->pEquiv = pNode; } +static inline void Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num ) { pObj->pNextFan0 = (Ivy_Obj_t *)Num; } +static inline void Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins ) { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; } + +static inline unsigned Ivy_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } + +// iterate through equivalence classes +#define Ivy_FraigForEachEquivClass( pList, pEnt ) \ + for ( pEnt = pList; \ + pEnt; \ + pEnt = Ivy_ObjEquivListNext(pEnt) ) +#define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 ) \ + for ( pEnt = pList, \ + pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL ) +// iterate through nodes in one class +#define Ivy_FraigForEachClassNode( pClass, pEnt ) \ + for ( pEnt = pClass; \ + pEnt; \ + pEnt = Ivy_ObjClassNodeNext(pEnt) ) +// iterate through nodes in the hash table +#define Ivy_FraigForEachBinNode( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = Ivy_ObjNodeHashNext(pEnt) ) + +static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +static Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 nBTLimitGlobal, sint64 nInsLimitGlobal, sint64 * pnSatConfs, sint64 * pnSatInspects ); +static void Ivy_FraigPrint( Ivy_FraigMan_t * p ); +static void Ivy_FraigStop( Ivy_FraigMan_t * p ); +static void Ivy_FraigSimulate( Ivy_FraigMan_t * p ); +static void Ivy_FraigSweep( Ivy_FraigMan_t * p ); +static Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ); +static int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); +static int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ); +static void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); +static int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ); +static void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ); +static int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ); +static void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ); +static void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose ); +static int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ); + +static int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ); + +static sint64 s_nBTLimitGlobal = 0; +static sint64 s_nInsLimitGlobal = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets the default solving parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ) +{ + memset( pParams, 0, sizeof(Ivy_FraigParams_t) ); + pParams->nSimWords = 32; // the number of words in the simulation info + pParams->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached + pParams->fPatScores = 0; // enables simulation pattern scoring + pParams->MaxScore = 25; // max score after which resimulation is used + pParams->fDoSparse = 1; // skips sparse functions +// pParams->dActConeRatio = 0.05; // the ratio of cone to be bumped +// pParams->dActConeBumpMax = 5.0; // the largest bump of activity + pParams->dActConeRatio = 0.3; // the ratio of cone to be bumped + pParams->dActConeBumpMax = 10.0; // the largest bump of activity + + pParams->nBTLimitNode = 100; // conflict limit at a node + pParams->nBTLimitMiter = 500000; // conflict limit at an output +// pParams->nBTLimitGlobal = 0; // conflict limit global +// pParams->nInsLimitGlobal = 0; // inspection limit global +} + +/**Function************************************************************* + + Synopsis [Performs combinational equivalence checking for the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ) +{ + Prove_Params_t * pParams = pPars; + Ivy_FraigParams_t Params, * pIvyParams = &Params; + Ivy_Man_t * pManAig, * pManTemp; + int RetValue, nIter, Counter, clk, timeStart = clock(); + sint64 nSatConfs, nSatInspects; + + // start the network and parameters + pManAig = *ppManAig; + Ivy_FraigParamsDefault( pIvyParams ); + pIvyParams->fVerbose = pParams->fVerbose; + pIvyParams->fProve = 1; + + if ( pParams->fVerbose ) + { + printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", + pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); + printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", + pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, + pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, + pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); + printf( "Mitering last = %d.\n", + pParams->nMiteringLimitLast ); + } + + // if SAT only, solve without iteration + if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) + { + clk = clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + *ppManAig = pManAig; + return RetValue; + } + + if ( Ivy_ManNodeNum(pManAig) < 500 ) + { + // run the first mitering + clk = clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + if ( RetValue >= 0 ) + { + *ppManAig = pManAig; + return RetValue; + } + } + + // check the current resource limits + RetValue = -1; + for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) + { + if ( pParams->fVerbose ) + { + printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), + (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); + fflush( stdout ); + } + + // try rewriting + if ( pParams->fUseRewriting ) + { + clk = clock(); + Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); + pManAig = Ivy_ManRwsat( pManAig, 0 ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "Rewriting ", clk, pParams->fVerbose ); + } + if ( RetValue >= 0 ) + break; + + // try fraiging followed by mitering + if ( pParams->fUseFraiging ) + { + clk = clock(); + pIvyParams->nBTLimitNode = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)); + pIvyParams->nBTLimitMiter = (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, pParams->nTotalBacktrackLimit, pParams->nTotalInspectLimit, &nSatConfs, &nSatInspects ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "Fraiging ", clk, pParams->fVerbose ); + } + if ( RetValue >= 0 ) + break; + + // add to the number of backtracks and inspects + pParams->nTotalBacktracksMade += nSatConfs; + pParams->nTotalInspectsMade += nSatInspects; + // check if global resource limit is reached + if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || + (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) + { + printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); + *ppManAig = pManAig; + return -1; + } + } + + if ( RetValue < 0 ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); + fflush( stdout ); + } + clk = clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); + if ( pParams->nTotalBacktrackLimit ) + s_nBTLimitGlobal = pParams->nTotalBacktrackLimit - pParams->nTotalBacktracksMade; + if ( pParams->nTotalInspectLimit ) + s_nInsLimitGlobal = pParams->nTotalInspectLimit - pParams->nTotalInspectsMade; + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + s_nBTLimitGlobal = 0; + s_nInsLimitGlobal = 0; + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + } + + // assign the model if it was proved by rewriting (const 1 miter) + if ( RetValue == 0 && pManAig->pData == NULL ) + { + pManAig->pData = ALLOC( int, Ivy_ManPiNum(pManAig) ); + memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) ); + } + *ppManAig = pManAig; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 nBTLimitGlobal, sint64 nInsLimitGlobal, sint64 * pnSatConfs, sint64 * pnSatInspects ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + int clk; + if ( Ivy_ManNodeNum(pManAig) == 0 ) + return Ivy_ManDup(pManAig); +clk = clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStart( pManAig, pParams ); + // set global limits + p->nBTLimitGlobal = nBTLimitGlobal; + p->nInsLimitGlobal = nInsLimitGlobal; + + Ivy_FraigSimulate( p ); + Ivy_FraigSweep( p ); + pManAigNew = p->pManFraig; +p->timeTotal = clock() - clk; + if ( pnSatConfs ) + *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0; + if ( pnSatInspects ) + *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0; + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + int clk; + if ( Ivy_ManNodeNum(pManAig) == 0 ) + return Ivy_ManDup(pManAig); +clk = clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStart( pManAig, pParams ); + Ivy_FraigSimulate( p ); + Ivy_FraigSweep( p ); + pManAigNew = p->pManFraig; +p->timeTotal = clock() - clk; + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Applies brute-force SAT to the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + Ivy_Obj_t * pObj; + int i, clk; +clk = clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStartSimple( pManAig, pParams ); + // set global limits + p->nBTLimitGlobal = s_nBTLimitGlobal; + p->nInsLimitGlobal = s_nInsLimitGlobal; + // duplicate internal nodes + Ivy_ManForEachNode( p->pManAig, pObj, i ) + pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // try to prove each output of the miter + Ivy_FraigMiterProve( p ); + // add the POs + Ivy_ManForEachPo( p->pManAig, pObj, i ) + Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); + // clean the new manager + Ivy_ManForEachObj( p->pManFraig, pObj, i ) + { + if ( Ivy_ObjFaninVec(pObj) ) + Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); + pObj->pNextFan0 = pObj->pNextFan1 = NULL; + } + // remove dangling nodes + Ivy_ManCleanup( p->pManFraig ); + pManAigNew = p->pManFraig; +p->timeTotal = clock() - clk; + +//printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) ); +//PRT( "Time", p->timeTotal ); + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager without simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + // allocat the fraiging manager + p = ALLOC( Ivy_FraigMan_t, 1 ); + memset( p, 0, sizeof(Ivy_FraigMan_t) ); + p->pParams = pParams; + p->pManAig = pManAig; + p->pManFraig = Ivy_ManStartFrom( pManAig ); + p->vPiVars = Vec_PtrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_FraigSim_t * pSims; + Ivy_Obj_t * pObj; + int i, k, EntrySize; + // clean the fanout representation + Ivy_ManForEachObj( pManAig, pObj, i ) +// pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; + assert( !pObj->pEquiv && !pObj->pFanout ); + // allocat the fraiging manager + p = ALLOC( Ivy_FraigMan_t, 1 ); + memset( p, 0, sizeof(Ivy_FraigMan_t) ); + p->pParams = pParams; + p->pManAig = pManAig; + p->pManFraig = Ivy_ManStartFrom( pManAig ); + // allocate simulation info + p->nSimWords = pParams->nSimWords; +// p->pSimWords = ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords ); + EntrySize = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords; + p->pSimWords = (char *)malloc( Ivy_ManObjNum(pManAig) * EntrySize ); + memset( p->pSimWords, 0, EntrySize ); + k = 0; + Ivy_ManForEachObj( pManAig, pObj, i ) + { + pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++); + pSims->pNext = NULL; + if ( Ivy_ObjIsNode(pObj) ) + { + if ( p->pSimStart == NULL ) + p->pSimStart = pSims; + else + ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims; + pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) ); + pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) ); + pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase; + } + else + { + pSims->pFanin0 = NULL; + pSims->pFanin1 = NULL; + pSims->Type = 0; + } + Ivy_ObjSetSim( pObj, pSims ); + } + assert( k == Ivy_ManObjNum(pManAig) ); + // allocate storage for sim pattern + p->nPatWords = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) ); + p->pPatWords = ALLOC( unsigned, p->nPatWords ); + p->pPatScores = ALLOC( int, 32 * p->nSimWords ); + p->vPiVars = Vec_PtrAlloc( 100 ); + // set random number generator + srand( 0xABCABC ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigStop( Ivy_FraigMan_t * p ) +{ + if ( p->pParams->fVerbose ) + Ivy_FraigPrint( p ); + if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); + if ( p->pSat ) sat_solver_delete( p->pSat ); + FREE( p->pPatScores ); + FREE( p->pPatWords ); + FREE( p->pSimWords ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrint( Ivy_FraigMan_t * p ) +{ + double nMemory; + nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20); + printf( "SimWords = %d. Rounds = %d. Mem = %0.2f Mb. ", p->nSimWords, p->nSimRounds, nMemory ); + printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd ); + printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter ); + printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", + p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero ); + printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n", + Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars ); + if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); + PRT( "AIG simulation ", p->timeSim ); + PRT( "AIG traversal ", p->timeTrav ); + PRT( "SAT solving ", p->timeSat ); + PRT( " Unsat ", p->timeSatUnsat ); + PRT( " Sat ", p->timeSatSat ); + PRT( " Fail ", p->timeSatFail ); + PRT( "Class refining ", p->timeRef ); + PRT( "TOTAL RUNTIME ", p->timeTotal ); + if ( p->time1 ) { PRT( "time1 ", p->time1 ); } +} + + + +/**Function************************************************************* + + Synopsis [Assigns random patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i; + assert( Ivy_ObjIsPi(pObj) ); + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = Ivy_ObjRandomSim(); +} + +/**Function************************************************************* + + Synopsis [Assigns constant patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 ) +{ + Ivy_FraigSim_t * pSims; + int i; + assert( Ivy_ObjIsPi(pObj) ); + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = fConst1? ~(unsigned)0 : 0; +} + +/**Function************************************************************* + + Synopsis [Assings random simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + Ivy_ManForEachPi( p->pManAig, pObj, i ) + Ivy_NodeAssignRandom( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Assings distance-1 simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat ) +{ + Ivy_Obj_t * pObj; + int i, Limit; + Ivy_ManForEachPi( p->pManAig, pObj, i ) + Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) ); + Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i; + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims->pData[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_FraigSim_t * pSims0, * pSims1; + int i; + pSims0 = Ivy_ObjSim(pObj0); + pSims1 = Ivy_ObjSim(pObj1); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims0->pData[i] != pSims1->pData[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims ) +{ + unsigned * pData, * pData0, * pData1; + int i; + pData = pSims->pData; + pData0 = pSims->pFanin0->pData; + pData1 = pSims->pFanin1->pData; + switch( pSims->Type ) + { + case 0: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] & pData1[i]); + break; + case 1: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = ~(pData0[i] & pData1[i]); + break; + case 2: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] & ~pData1[i]); + break; + case 3: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (~pData0[i] | pData1[i]); + break; + case 4: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (~pData0[i] & pData1[i]); + break; + case 5: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] | ~pData1[i]); + break; + case 6: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = ~(pData0[i] | pData1[i]); + break; + case 7: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] | pData1[i]); + break; + } +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims, * pSims0, * pSims1; + int fCompl, fCompl0, fCompl1, i; + assert( !Ivy_IsComplement(pObj) ); + // get hold of the simulation information + pSims = Ivy_ObjSim(pObj); + pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj)); + pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj)); + // get complemented attributes of the children using their random info + fCompl = pObj->fPhase; + fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); + fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); + // simulate + if ( fCompl0 && fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]); + } + else if ( fCompl0 && !fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]); + } + else if ( !fCompl0 && fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]); + } + else // if ( !fCompl0 && !fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]); + } +} + +/**Function************************************************************* + + Synopsis [Computes hash value using simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + Ivy_FraigSim_t * pSims; + unsigned uHash; + int i; + assert( p->nSimWords <= 128 ); + uHash = 0; + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + uHash ^= pSims->pData[i] * s_FPrimes[i]; + return uHash; +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i, clk; +clk = clock(); + Ivy_ManForEachNode( p->pManAig, pObj, i ) + { + Ivy_NodeSimulate( p, pObj ); +/* + if ( Ivy_ObjFraig(pObj) == NULL ) + printf( "%3d --- -- %d : ", pObj->Id, pObj->fPhase ); + else + printf( "%3d %3d %2d %d : ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase ); + Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 ); + printf( "\n" ); +*/ + } +p->timeSim += clock() - clk; +p->nSimRounds++; +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p ) +{ + Ivy_FraigSim_t * pSims; + int clk; +clk = clock(); + for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext ) + Ivy_NodeSimulateSim( p, pSims ); +p->timeSim += clock() - clk; +p->nSimRounds++; +} + +/**Function************************************************************* + + Synopsis [Adds one node to the equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjClassNodeNext(pClass) == NULL ) + Ivy_ObjSetClassNodeNext( pClass, pObj ); + else + Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj ); + Ivy_ObjSetClassNodeLast( pClass, pObj ); + Ivy_ObjSetClassNodeRepr( pObj, pClass ); + Ivy_ObjSetClassNodeNext( pObj, NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds equivalence class to the list of classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) +{ + if ( pList->pHead == NULL ) + { + pList->pHead = pClass; + pList->pTail = pClass; + Ivy_ObjSetEquivListPrev( pClass, NULL ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + } + else + { + Ivy_ObjSetEquivListNext( pList->pTail, pClass ); + Ivy_ObjSetEquivListPrev( pClass, pList->pTail ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + pList->pTail = pClass; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [Updates the list of classes after base class has split.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass ) +{ + Ivy_ObjSetEquivListPrev( pClass, pBase ); + Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) ); + if ( Ivy_ObjEquivListNext(pBase) ) + Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass ); + Ivy_ObjSetEquivListNext( pBase, pClass ); + if ( pList->pTail == pBase ) + pList->pTail = pClass; + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [Removes equivalence class from the list of classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) +{ + if ( pList->pHead == pClass ) + pList->pHead = Ivy_ObjEquivListNext(pClass); + if ( pList->pTail == pClass ) + pList->pTail = Ivy_ObjEquivListPrev(pClass); + if ( Ivy_ObjEquivListPrev(pClass) ) + Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) ); + if ( Ivy_ObjEquivListNext(pClass) ) + Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + Ivy_ObjSetEquivListPrev( pClass, NULL ); + pClass->fMarkA = 0; + pList->nItems--; +} + +/**Function************************************************************* + + Synopsis [Count the number of pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass, * pNode; + int nPairs = 0, nNodes; + return nPairs; + + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) + { + nNodes = 0; + Ivy_FraigForEachClassNode( pClass, pNode ) + nNodes++; + nPairs += nNodes * (nNodes - 1) / 2; + } + return nPairs; +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t ** pTable; + Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry; + int i, nTableSize; + unsigned Hash; + pConst1 = Ivy_ManConst1(p->pManAig); + // allocate the table + nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13; + pTable = ALLOC( Ivy_Obj_t *, nTableSize ); + memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize ); + // collect nodes into the table + Ivy_ManForEachObj( p->pManAig, pObj, i ) + { + if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) + continue; + Hash = Ivy_NodeHash( p, pObj ); + if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) ) + { + Ivy_NodeAddToClass( pConst1, pObj ); + continue; + } + // add the node to the table + pBin = pTable[Hash % nTableSize]; + Ivy_FraigForEachBinNode( pBin, pEntry ) + if ( Ivy_NodeCompareSims( p, pEntry, pObj ) ) + { + Ivy_NodeAddToClass( pEntry, pObj ); + break; + } + // check if the entry was added + if ( pEntry ) + continue; + Ivy_ObjSetNodeHashNext( pObj, pBin ); + pTable[Hash % nTableSize] = pObj; + } + // collect non-trivial classes + assert( p->lClasses.pHead == NULL ); + Ivy_ManForEachObj( p->pManAig, pObj, i ) + { + if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) + continue; + Ivy_ObjSetNodeHashNext( pObj, NULL ); + if ( Ivy_ObjClassNodeRepr(pObj) == NULL ) + { + assert( Ivy_ObjClassNodeNext(pObj) == NULL ); + continue; + } + // recognize the head of the class + if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL ) + continue; + // clean the class representative and add it to the list + Ivy_ObjSetClassNodeRepr( pObj, NULL ); + Ivy_FraigAddClass( &p->lClasses, pObj ); + } + // free the table + free( pTable ); +} + +/**Function************************************************************* + + Synopsis [Recursively refines the class after simulation.] + + Description [Returns 1 if the class has changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode; + int RetValue = 0; + // check if there is refinement + pListOld = pClass; + Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew ) + { + if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) ) + { + if ( p->pParams->fPatScores ) + Ivy_FraigAddToPatScores( p, pClass, pClassNew ); + break; + } + pListOld = pClassNew; + } + if ( pClassNew == NULL ) + return 0; + // set representative of the new class + Ivy_ObjSetClassNodeRepr( pClassNew, NULL ); + // start the new list + pListNew = pClassNew; + // go through the remaining nodes and sort them into two groups: + // (1) matches of the old node; (2) non-matches of the old node + Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode ) + if ( Ivy_NodeCompareSims( p, pClass, pNode ) ) + { + Ivy_ObjSetClassNodeNext( pListOld, pNode ); + pListOld = pNode; + } + else + { + Ivy_ObjSetClassNodeNext( pListNew, pNode ); + Ivy_ObjSetClassNodeRepr( pNode, pClassNew ); + pListNew = pNode; + } + // finish both lists + Ivy_ObjSetClassNodeNext( pListNew, NULL ); + Ivy_ObjSetClassNodeNext( pListOld, NULL ); + // update the list of classes + Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew ); + // if the old class is trivial, remove it + if ( Ivy_ObjClassNodeNext(pClass) == NULL ) + Ivy_FraigRemoveClass( &p->lClasses, pClass ); + // if the new class is trivial, remove it; otherwise, try to refine it + if ( Ivy_ObjClassNodeNext(pClassNew) == NULL ) + Ivy_FraigRemoveClass( &p->lClasses, pClassNew ); + else + RetValue = Ivy_FraigRefineClass_rec( p, pClassNew ); + return RetValue + 1; +} + +/**Function************************************************************* + + Synopsis [Creates the counter-example from the successful pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i, k, BestPat, * pModel; + // find the word of the pattern + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims->pData[i] ) + break; + assert( i < p->nSimWords ); + // find the bit of the pattern + for ( k = 0; k < 32; k++ ) + if ( pSims->pData[i] & (1 << k) ) + break; + assert( k < 32 ); + // determine the best pattern + BestPat = i * 32 + k; + // fill in the counter-example data + pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + Ivy_ManForEachPi( p->pManAig, pObj, i ) + pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat); + // set the model + assert( p->pManFraig->pData == NULL ); + p->pManFraig->pData = pModel; + return; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the one of the output is already non-constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + Ivy_ManForEachPo( p->pManAig, pObj, i ) + if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) ) + { + // create the counter-example from this pattern + Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) ); + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Refines the classes after simulation.] + + Description [Assumes that simulation info is assigned. Returns the + number of classes refined.] + + SideEffects [Large equivalence class of constant 0 may cause problems.] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass, * pClass2; + int clk, RetValue, Counter = 0; + // check if some outputs already became non-constant + // this is a special case when computation can be stopped!!! + if ( p->pParams->fProve ) + Ivy_FraigCheckOutputSims( p ); + if ( p->pManFraig->pData ) + return 0; + // refine the classed +clk = clock(); + Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 ) + { + if ( pClass->fMarkA ) + continue; + RetValue = Ivy_FraigRefineClass_rec( p, pClass ); + Counter += ( RetValue > 0 ); +//if ( Ivy_ObjIsConst1(pClass) ) +//printf( "%d ", RetValue ); +//if ( Ivy_ObjIsConst1(pClass) ) +// p->time1 += clock() - clk; + } +p->timeRef += clock() - clk; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Print the class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintClass( Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pObj; + printf( "Class {" ); + Ivy_FraigForEachClassNode( pClass, pObj ) + printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Count the number of elements in the class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pObj; + int Counter = 0; + Ivy_FraigForEachClassNode( pClass, pObj ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass; + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) + { +// Ivy_FraigPrintClass( pClass ); + printf( "%d ", Ivy_FraigCountClassNodes( pClass ) ); + } +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Generated const 0 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p ) +{ + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); +} + +/**Function************************************************************* + + Synopsis [[Generated const 1 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p ) +{ + memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); +} + +/**Function************************************************************* + + Synopsis [Generates the counter-example satisfying the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ) +{ + int * pModel; + Ivy_Obj_t * pObj; + int i; + pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + Ivy_ManForEachPi( p->pManFraig, pObj, i ) + pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ); + return pModel; +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Ivy_ManForEachPi( p->pManFraig, pObj, i ) +// Vec_PtrForEachEntry( p->vPiVars, pObj, i ) + if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) + Ivy_InfoSetBit( p->pPatWords, i ); +// Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); +// Ivy_ManForEachPi( p->pManFraig, pObj, i ) + Vec_PtrForEachEntry( p->vPiVars, pObj, i ) + if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) +// Ivy_InfoSetBit( p->pPatWords, i ); + Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + for ( i = 0; i < p->nPatWords; i++ ) + p->pPatWords[i] = Ivy_ObjRandomSim(); + Vec_PtrForEachEntry( p->vPiVars, pObj, i ) + if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) ) + Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 ); +} + + +/**Function************************************************************* + + Synopsis [Performs simulation of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulate( Ivy_FraigMan_t * p ) +{ + int nChanges, nClasses; + // start the classes + Ivy_FraigAssignRandom( p ); + Ivy_FraigSimulateOne( p ); + Ivy_FraigCreateClasses( p ); +//printf( "Starting classes = %5d. Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) ); + // refine classes by walking 0/1 patterns + Ivy_FraigSavePattern0( p ); + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + Ivy_FraigSavePattern1( p ); + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + // refine classes by random simulation + do { + Ivy_FraigAssignRandom( p ); + Ivy_FraigSimulateOne( p ); + nClasses = p->lClasses.nItems; + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + } while ( (double)nChanges / nClasses > p->pParams->dSimSatur ); +// Ivy_FraigPrintSimClasses( p ); +} + + + +/**Function************************************************************* + + Synopsis [Cleans pattern scores.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p ) +{ + int i, nLimit = p->nSimWords * 32; + for ( i = 0; i < nLimit; i++ ) + p->pPatScores[i] = 0; +} + +/**Function************************************************************* + + Synopsis [Adds to pattern scores.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ) +{ + Ivy_FraigSim_t * pSims0, * pSims1; + unsigned uDiff; + int i, w; + // get hold of the simulation information + pSims0 = Ivy_ObjSim(pClass); + pSims1 = Ivy_ObjSim(pClassNew); + // iterate through the differences and record the score + for ( w = 0; w < p->nSimWords; w++ ) + { + uDiff = pSims0->pData[w] ^ pSims1->pData[w]; + if ( uDiff == 0 ) + continue; + for ( i = 0; i < 32; i++ ) + if ( uDiff & ( 1 << i ) ) + p->pPatScores[w*32+i]++; + } +} + +/**Function************************************************************* + + Synopsis [Selects the best pattern.] + + Description [Returns 1 if such pattern is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p ) +{ + Ivy_FraigSim_t * pSims; + Ivy_Obj_t * pObj; + int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1; + for ( i = 1; i < nLimit; i++ ) + { + if ( MaxScore < p->pPatScores[i] ) + { + MaxScore = p->pPatScores[i]; + BestPat = i; + } + } + if ( MaxScore == 0 ) + return 0; +// if ( MaxScore > p->pParams->MaxScore ) +// printf( "Max score is %3d. ", MaxScore ); + // copy the best pattern into the selected pattern + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Ivy_ManForEachPi( p->pManAig, pObj, i ) + { + pSims = Ivy_ObjSim(pObj); + if ( Ivy_InfoHasBit(pSims->pData, BestPat) ) + Ivy_InfoSetBit(p->pPatWords, i); + } + return MaxScore; +} + +/**Function************************************************************* + + Synopsis [Resimulates fraiging manager after finding a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigResimulate( Ivy_FraigMan_t * p ) +{ + int nChanges; + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + if ( p->pParams->fPatScores ) + Ivy_FraigCleanPatScores( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; + if ( nChanges < 1 ) + printf( "Error: A counter-example did not refine classes!\n" ); + assert( nChanges >= 1 ); +//printf( "Refined classes! = %5d. Changes = %4d.\n", p->lClasses.nItems, nChanges ); + + if ( !p->pParams->fPatScores ) + return; + + // perform additional simulation using dist1 patterns derived from successful patterns + while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore ) + { + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + Ivy_FraigCleanPatScores( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined class!!! = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + if ( nChanges == 0 ) + break; + } +} + + +/**Function************************************************************* + + Synopsis [Prints the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose ) +{ + if ( !fVerbose ) + return; + printf( "Nodes = %7d. Levels = %4d. ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) ); + PRT( pString, clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Reports the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ) +{ + Ivy_Obj_t * pObj, * pObjNew; + int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; + if ( pMan->pData ) + return 0; + Ivy_ManForEachPo( pMan, pObj, i ) + { + pObjNew = Ivy_ObjChild0(pObj); + // check if the output is constant 1 + if ( pObjNew == pMan->pConst1 ) + { + CountNonConst0++; + continue; + } + // check if the output is constant 0 + if ( pObjNew == Ivy_Not(pMan->pConst1) ) + { + CountConst0++; + continue; + } + // check if the output can be constant 0 + if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) + { + CountNonConst0++; + continue; + } + CountUndecided++; + } +/* + if ( p->pParams->fVerbose ) + { + printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) ); + printf( "Const0 = %d. ", CountConst0 ); + printf( "NonConst0 = %d. ", CountNonConst0 ); + printf( "Undecided = %d. ", CountUndecided ); + printf( "\n" ); + } +*/ + if ( CountNonConst0 ) + return 0; + if ( CountUndecided ) + return -1; + return 1; +} + +/**Function************************************************************* + + Synopsis [Tries to prove each output of the miter until encountering a sat output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj, * pObjNew; + int i, RetValue, clk = clock(); + int fVerbose = 0; + Ivy_ManForEachPo( p->pManAig, pObj, i ) + { + if ( i && fVerbose ) + { + PRT( "Time", clock() -clk ); + } + pObjNew = Ivy_ObjChild0Equiv(pObj); + // check if the output is constant 1 + if ( pObjNew == p->pManFraig->pConst1 ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) is constant 1. ", i, Ivy_ManPoNum(p->pManAig) ); + break; + } + // check if the output is constant 0 + if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) is already constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + continue; + } + // check if the output can be constant 0 + if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) cannot be constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // assing constant 0 model + p->pManFraig->pData = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); + break; + } +/* + // check the representative of this node + pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj)); + if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 ) + printf( "Representative is not constant 1.\n" ); + else + printf( "Representative is constant 1.\n" ); +*/ + // try to prove the output constant 0 + RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) ); + if ( RetValue == 1 ) // proved equivalent + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) was proved constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // set the constant miter + Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) ); + continue; + } + if ( RetValue == -1 ) // failed + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) has timed out at %d backtracks. ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter ); + continue; + } + // proved satisfiable + if ( fVerbose ) + printf( "Output %2d (out of %2d) was proved NOT a constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // create the model + p->pManFraig->pData = Ivy_FraigCreateModel(p); + break; + } + if ( fVerbose ) + { + PRT( "Time", clock() -clk ); + } +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSweep( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj;//, * pTemp; + int i, k = 0; +p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0; +p->nClassesBeg = p->lClasses.nItems; + // duplicate internal nodes + p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) ); + Ivy_ManForEachNode( p->pManAig, pObj, i ) + { + Extra_ProgressBarUpdate( p->pProgress, k++, NULL ); + // default to simple strashing if simulation detected a counter-example for a PO + if ( p->pManFraig->pData ) + pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + else + pObj->pEquiv = Ivy_FraigAnd( p, pObj ); + assert( pObj->pEquiv != NULL ); +// pTemp = Ivy_Regular(pObj->pEquiv); +// assert( Ivy_Regular(pObj->pEquiv)->Type ); + } + Extra_ProgressBarStop( p->pProgress ); +p->nClassesEnd = p->lClasses.nItems; + // try to prove the outputs of the miter + p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig); +// Ivy_FraigMiterStatus( p->pManFraig ); + if ( p->pParams->fProve && p->pManFraig->pData == NULL ) + Ivy_FraigMiterProve( p ); + // add the POs + Ivy_ManForEachPo( p->pManAig, pObj, i ) + Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); + // clean the old manager + Ivy_ManForEachObj( p->pManAig, pObj, i ) + pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; + // clean the new manager + Ivy_ManForEachObj( p->pManFraig, pObj, i ) + { + if ( Ivy_ObjFaninVec(pObj) ) + Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); + pObj->pNextFan0 = pObj->pNextFan1 = NULL; + } + // remove dangling nodes + Ivy_ManCleanup( p->pManFraig ); + // clean up the class marks + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ) +{ + Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew; + int RetValue; + // get the fraiged fanins + pFanin0New = Ivy_ObjChild0Equiv(pObjOld); + pFanin1New = Ivy_ObjChild1Equiv(pObjOld); + // get the candidate fraig node + pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New ); + // get representative of this class + if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node + (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node + { +// if ( Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1 ) +// { +// int x = 0; +// } + assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) ); + assert( pObjNew != Ivy_Regular(pFanin0New) ); + assert( pObjNew != Ivy_Regular(pFanin1New) ); + return pObjNew; + } + // get the fraiged representative + pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld)); + // if the fraiged nodes are the same return + if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) ) + return pObjNew; + assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) ); + // they are different (the counter-example is in p->pPatWords) + RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) ); + if ( RetValue == 1 ) // proved equivalent + { + // mark the class as proved + if ( Ivy_ObjClassNodeNext(pObjOld) == NULL ) + Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1; + return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase ); + } + if ( RetValue == -1 ) // failed + return pObjNew; + // simulate the counter-example and return the new node + Ivy_FraigResimulate( p ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Prints variable activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p ) +{ + int i; + for ( i = 0; i < p->nSatVars; i++ ) + printf( "%d %.3f ", i, p->pSat->activity[i] ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock(); + + // make sure the nodes are not complemented + assert( !Ivy_IsComplement(pNew) ); + assert( !Ivy_IsComplement(pOld) ); + assert( pNew != pOld ); + + // if at least one of the nodes is a failed node, perform adjustments: + // if the backtrack limit is small, simply skip this node + // if the backtrack limit is > 10, take the quare root of the limit + nBTLimit = p->pParams->nBTLimitNode; + if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) + { + p->nSatFails++; + // fail immediately +// return -1; + if ( nBTLimit <= 10 ) + return -1; + nBTLimit = (int)pow(nBTLimit, 0.7); + } + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + p->nSatVars = 1; + sat_solver_setnvars( p->pSat, 1000 ); + } + + // if the nodes do not have SAT variables, allocate them + Ivy_FraigNodeAddToSolver( p, pOld, pNew ); + + // prepare variable activity + Ivy_FraigSetActivityFactors( p, pOld, pNew ); + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 +clk = clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 ); + pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (sint64)nBTLimit, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + if ( pOld != p->pManFraig->pConst1 ) + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } + + // if the old node was constant 0, we already know the answer + if ( pOld == p->pManFraig->pConst1 ) + { + p->nSatProof++; + return 1; + } + + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 +clk = clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 ); + pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (sint64)nBTLimit, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } +/* + // check BDD proof + { + int RetVal; + PRT( "Sat", clock() - clk2 ); + clk2 = clock(); + RetVal = Ivy_FraigNodesAreEquivBdd( pOld, pNew ); +// printf( "%d ", RetVal ); + assert( RetVal ); + PRT( "Bdd", clock() - clk2 ); + printf( "\n" ); + } +*/ + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew ) +{ + int pLits[2], RetValue1, RetValue, clk; + + // make sure the nodes are not complemented + assert( !Ivy_IsComplement(pNew) ); + assert( pNew != p->pManFraig->pConst1 ); + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + p->nSatVars = 1; + sat_solver_setnvars( p->pSat, 1000 ); + } + + // if the nodes do not have SAT variables, allocate them + Ivy_FraigNodeAddToSolver( p, NULL, pNew ); + + // prepare variable activity + Ivy_FraigSetActivityFactors( p, NULL, pNew ); + + // solve under assumptions +clk = clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, + (sint64)p->pParams->nBTLimitMiter, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + if ( p->pPatWords ) + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } + + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Ivy_IsComplement( pNode ) ); + assert( Ivy_ObjIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = Ivy_ObjSatNum(pNode); + VarI = Ivy_ObjSatNum(pNodeI); + VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT)); + VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE)); + // get the complementation flags + fCompT = Ivy_IsComplement(pNodeT); + fCompE = Ivy_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 1^fCompT); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 0^fCompT); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = toLitCond(VarT, 0^fCompT); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarT, 1^fCompT); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper ) +{ + Ivy_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Ivy_IsComplement(pNode) ); + assert( Ivy_ObjIsNode( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin)); + pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( vSuper, pFanin, i ) + pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin)); + pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); + assert( RetValue ); + free( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) || + (fUseMuxes && Ivy_ObjIsMuxType(pObj)) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + // go through the branches + Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes ) +{ + Vec_Ptr_t * vSuper; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_ObjIsPi(pObj) ); + vSuper = Vec_PtrAlloc( 4 ); + Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); + return vSuper; +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + assert( !Ivy_IsComplement(pObj) ); + if ( Ivy_ObjSatNum(pObj) ) + return; + assert( Ivy_ObjSatNum(pObj) == 0 ); + assert( Ivy_ObjFaninVec(pObj) == NULL ); + if ( Ivy_ObjIsConst1(pObj) ) + return; +//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); + Ivy_ObjSetSatNum( pObj, p->nSatVars++ ); + if ( Ivy_ObjIsNode(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + Vec_Ptr_t * vFrontier, * vFanins; + Ivy_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + assert( pOld || pNew ); + // quit if CNF is ready + if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) ) + return; + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier ); + if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( vFrontier, pNode, i ) + { + // create the supergate + assert( Ivy_ObjSatNum(pNode) ); + assert( Ivy_ObjFaninVec(pNode) == NULL ); + if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) ) + { + vFanins = Vec_PtrAlloc( 4 ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); + Ivy_FraigAddClausesMux( p, pNode ); + } + else + { + vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes ); + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); + Ivy_FraigAddClausesSuper( p, pNode, vFanins ); + } + assert( Vec_PtrSize(vFanins) > 1 ); + Ivy_ObjSetFaninVec( pNode, vFanins ); + } + Vec_PtrFree( vFrontier ); +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax ) +{ + Vec_Ptr_t * vFanins; + Ivy_Obj_t * pFanin; + int i, Counter = 0; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjSatNum(pObj) ); + // skip visited variables + if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) ) + return 0; + Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj); + // add the PI to the list + if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) ) + return 0; + // set the factor of this variable + // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump + p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); + veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj)); + // explore the fanins + vFanins = Ivy_ObjFaninVec( pObj ); + Vec_PtrForEachEntry( vFanins, pFanin, i ) + Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + int clk, LevelMin, LevelMax; + assert( pOld || pNew ); +clk = clock(); + // reset the active variables + veci_resize(&p->pSat->act_vars, 0); + // prepare for traversal + Ivy_ManIncrementTravId( p->pManFraig ); + // determine the min and max level to visit + assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 ); + LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); + LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio)); + // traverse + if ( pOld && !Ivy_ObjIsConst1(pOld) ) + Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); + if ( pNew && !Ivy_ObjIsConst1(pNew) ) + Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); +//Ivy_FraigPrintActivity( p ); +p->timeTrav += clock() - clk; + return 1; +} + + + +#include "cuddInt.h" + +/**Function************************************************************* + + Synopsis [Checks equivalence using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Ivy_FraigNodesAreEquivBdd_int( DdManager * dd, DdNode * bFunc, Vec_Ptr_t * vFront, int Level ) +{ + DdNode ** pFuncs; + DdNode * bFuncNew; + Vec_Ptr_t * vTemp; + Ivy_Obj_t * pObj, * pFanin; + int i, NewSize; + // create new frontier + vTemp = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( vFront, pObj, i ) + { + if ( (int)pObj->Level != Level ) + { + pObj->fMarkB = 1; + pObj->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pObj ); + continue; + } + + pFanin = Ivy_ObjFanin0(pObj); + if ( pFanin->fMarkB == 0 ) + { + pFanin->fMarkB = 1; + pFanin->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pFanin ); + } + + pFanin = Ivy_ObjFanin1(pObj); + if ( pFanin->fMarkB == 0 ) + { + pFanin->fMarkB = 1; + pFanin->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pFanin ); + } + } + // collect the permutation + NewSize = IVY_MAX(dd->size, Vec_PtrSize(vTemp)); + pFuncs = ALLOC( DdNode *, NewSize ); + Vec_PtrForEachEntry( vFront, pObj, i ) + { + if ( (int)pObj->Level != Level ) + pFuncs[i] = Cudd_bddIthVar( dd, pObj->TravId ); + else + pFuncs[i] = Cudd_bddAnd( dd, + Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ), + Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ) ); + Cudd_Ref( pFuncs[i] ); + } + // add the remaining vars + assert( NewSize == dd->size ); + for ( i = Vec_PtrSize(vFront); i < dd->size; i++ ) + { + pFuncs[i] = Cudd_bddIthVar( dd, i ); + Cudd_Ref( pFuncs[i] ); + } + + // create new + bFuncNew = Cudd_bddVectorCompose( dd, bFunc, pFuncs ); Cudd_Ref( bFuncNew ); + // clean trav Id + Vec_PtrForEachEntry( vTemp, pObj, i ) + { + pObj->fMarkB = 0; + pObj->TravId = 0; + } + // deref + for ( i = 0; i < dd->size; i++ ) + Cudd_RecursiveDeref( dd, pFuncs[i] ); + free( pFuncs ); + + free( vFront->pArray ); + *vFront = *vTemp; + + vTemp->nCap = vTemp->nSize = 0; + vTemp->pArray = NULL; + Vec_PtrFree( vTemp ); + + Cudd_Deref( bFuncNew ); + return bFuncNew; +} + +/**Function************************************************************* + + Synopsis [Checks equivalence using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ) +{ + static DdManager * dd = NULL; + DdNode * bFunc, * bTemp; + Vec_Ptr_t * vFront; + Ivy_Obj_t * pObj; + int i, RetValue, Iter, Level; + // start the manager + if ( dd == NULL ) + dd = Cudd_Init( 50, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // create front + vFront = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vFront, pObj1 ); + Vec_PtrPush( vFront, pObj2 ); + // get the function + bFunc = Cudd_bddXor( dd, Cudd_bddIthVar(dd,0), Cudd_bddIthVar(dd,1) ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, pObj1->fPhase != pObj2->fPhase ); + // try running BDDs + for ( Iter = 0; ; Iter++ ) + { + // find max level + Level = 0; + Vec_PtrForEachEntry( vFront, pObj, i ) + if ( Level < (int)pObj->Level ) + Level = (int)pObj->Level; + if ( Level == 0 ) + break; + bFunc = Ivy_FraigNodesAreEquivBdd_int( dd, bTemp = bFunc, vFront, Level ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + if ( bFunc == Cudd_ReadLogicZero(dd) ) // proved + {printf( "%d", Iter ); break;} + if ( Cudd_DagSize(bFunc) > 1000 ) + {printf( "b" ); break;} + if ( dd->size > 120 ) + {printf( "s" ); break;} + if ( Iter > 50 ) + {printf( "i" ); break;} + } + if ( bFunc == Cudd_ReadLogicZero(dd) ) // unsat + RetValue = 1; + else if ( Level == 0 ) // sat + RetValue = 0; + else + RetValue = -1; // spaceout/timeout + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFront ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyHaig.c b/src/aig/ivy/ivyHaig.c new file mode 100644 index 00000000..87021600 --- /dev/null +++ b/src/aig/ivy/ivyHaig.c @@ -0,0 +1,530 @@ +/**CFile**************************************************************** + + FileName [ivyHaig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [HAIG management procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + HAIGing rules in working AIG: + - Each node in the working AIG has a pointer to the corresponding node in HAIG + (this node is not necessarily the representative of the equivalence class of HAIG nodes) + - This pointer is complemented if the AIG node and its corresponding HAIG node have different phase + + Choice node rules in HAIG: + - Equivalent nodes are linked into a ring + - Exactly one node in the ring has fanouts (this node is called the representative) + - The pointer going from a node to the next node in the ring is complemented + if the first node is complemented, compared to the representative node of the equivalence class + - (consequence of the above) The representative node always has non-complemented pointer to the next node + - New nodes are inserted into the ring immediately after the representative node +*/ + +// returns the representative node of the given HAIG node +static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + // if the node has no equivalent node or has fanout, it is representative + if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 ) + return pObj; + // the node belongs to a class and is not a representative + // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr + for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + if ( Ivy_ObjRefs(pTemp) > 0 ) + break; + // return the representative node + assert( Ivy_ObjRefs(pTemp) > 0 ); + return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) ); +} + +// counts the number of nodes in the equivalence class +static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pTemp; + int Counter; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjRefs(pObj) > 0 ); + if ( pObj->pEquiv == NULL ) + return 1; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + Counter = 1; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts HAIG for the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ) +{ + Vec_Int_t * vLatches; + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig == NULL ); + p->pHaig = Ivy_ManDup( p ); + + if ( fVerbose ) + { + printf( "Starting : " ); + Ivy_ManPrintStats( p->pHaig ); + } + + // collect latches of design D and set their values to be DC + vLatches = Vec_IntAlloc( 100 ); + Ivy_ManForEachLatch( p->pHaig, pObj, i ) + { + pObj->Init = IVY_INIT_DC; + Vec_IntPush( vLatches, pObj->Id ); + } + p->pHaig->pData = vLatches; +/* + { + int x; + Ivy_ManShow( p, 0, NULL ); + Ivy_ManShow( p->pHaig, 1, NULL ); + x = 0; + } +*/ +} + +/**Function************************************************************* + + Synopsis [Transfers the HAIG to the newly created manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig != NULL ); + Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv; + Ivy_ManForEachPi( pNew, pObj, i ) + pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv; + pNew->pHaig = p->pHaig; +} + +/**Function************************************************************* + + Synopsis [Stops HAIG for the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigStop( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig != NULL ); + Vec_IntFree( p->pHaig->pData ); + Ivy_ManStop( p->pHaig ); + p->pHaig = NULL; + // remove dangling pointers to the HAIG objects + Ivy_ManForEachObj( p, pObj, i ) + pObj->pEquiv = NULL; +} + +/**Function************************************************************* + + Synopsis [Creates a new node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEquiv0, * pEquiv1; + assert( p->pHaig != NULL ); + assert( !Ivy_IsComplement(pObj) ); + if ( Ivy_ObjType(pObj) == IVY_BUF ) + pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); + else if ( Ivy_ObjType(pObj) == IVY_LATCH ) + { +// pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init ); + pEquiv0 = Ivy_ObjChild0Equiv(pObj); + pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); + pObj->pEquiv = Ivy_Latch( p->pHaig, pEquiv0, pObj->Init ); + } + else if ( Ivy_ObjType(pObj) == IVY_AND ) + { +// pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + pEquiv0 = Ivy_ObjChild0Equiv(pObj); + pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); + pEquiv1 = Ivy_ObjChild1Equiv(pObj); + pEquiv1 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv1)), Ivy_IsComplement(pEquiv1) ); + pObj->pEquiv = Ivy_And( p->pHaig, pEquiv0, pEquiv1 ); + } + else assert( 0 ); + // make sure the node points to the representative +// pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) ); +} + +/**Function************************************************************* + + Synopsis [Checks if the old node is in the TFI of the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjIsInTfi_rec( Ivy_Obj_t * pObjNew, Ivy_Obj_t * pObjOld, int Levels ) +{ + if ( pObjNew == pObjOld ) + return 1; + if ( Levels == 0 || Ivy_ObjIsCi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) + return 0; + if ( Ivy_ObjIsInTfi_rec( Ivy_ObjFanin0(pObjNew), pObjOld, Levels - 1 ) ) + return 1; + if ( Ivy_ObjIsNode(pObjNew) && Ivy_ObjIsInTfi_rec( Ivy_ObjFanin1(pObjNew), pObjOld, Levels - 1 ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sets the pair of equivalent nodes in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ) +{ + Ivy_Obj_t * pObjOldHaig, * pObjNewHaig; + Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR; + int fCompl; +//printf( "\nCreating choice for %d and %d in AIG\n", pObjOld->Id, Ivy_Regular(pObjNew)->Id ); + + assert( p->pHaig != NULL ); + assert( !Ivy_IsComplement(pObjOld) ); + // get pointers to the representatives of pObjOld and pObjNew + pObjOldHaig = pObjOld->pEquiv; + pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) ); + // get the classes + pObjOldHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjOldHaig)), Ivy_IsComplement(pObjOldHaig) ); + pObjNewHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjNewHaig)), Ivy_IsComplement(pObjNewHaig) ); + // get regular pointers + pObjOldHaigR = Ivy_Regular(pObjOldHaig); + pObjNewHaigR = Ivy_Regular(pObjNewHaig); + // check if there is phase difference between them + fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig)); + // if the class is the same, nothing to do + if ( pObjOldHaigR == pObjNewHaigR ) + return; + // if the second node belongs to a class, do not merge classes (for the time being) + if ( Ivy_ObjRefs(pObjOldHaigR) == 0 || pObjNewHaigR->pEquiv != NULL || + Ivy_ObjRefs(pObjNewHaigR) > 0 ) //|| Ivy_ObjIsInTfi_rec(pObjNewHaigR, pObjOldHaigR, 10) ) + { +/* + if ( pObjNewHaigR->pEquiv != NULL ) + printf( "c" ); + if ( Ivy_ObjRefs(pObjNewHaigR) > 0 ) + printf( "f" ); + printf( " " ); +*/ + p->pHaig->nClassesSkip++; + return; + } + + // add this node to the class of pObjOldHaig + assert( Ivy_ObjRefs(pObjOldHaigR) > 0 ); + assert( !Ivy_IsComplement(pObjOldHaigR->pEquiv) ); + if ( pObjOldHaigR->pEquiv == NULL ) + pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ); + else + pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl ); + pObjOldHaigR->pEquiv = pObjNewHaigR; +//printf( "Setting choice node %d -> %d.\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); + // update the class of the new node +// Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) ); +//printf( "Creating choice for %d and %d in HAIG\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); + +// if ( pObjOldHaigR->Id == 13 ) +// { +// Ivy_ManShow( p, 0 ); +// Ivy_ManShow( p->pHaig, 1 ); +// } +// if ( !Ivy_ManIsAcyclic( p->pHaig ) ) +// printf( "HAIG contains a cycle\n" ); +} + +/**Function************************************************************* + + Synopsis [Count the number of choices and choice nodes in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices ) +{ + Ivy_Obj_t * pObj; + int nChoices, nChoiceNodes, Counter, i; + assert( p->pHaig != NULL ); + nChoices = nChoiceNodes = 0; + Ivy_ManForEachObj( p->pHaig, pObj, i ) + { + if ( Ivy_ObjIsTerm(pObj) || i == 0 ) + continue; + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + Counter = Ivy_HaigObjCountClass( pObj ); + nChoiceNodes += (int)(Counter > 1); + nChoices += Counter - 1; +// if ( Counter > 1 ) +// printf( "Choice node %d %s\n", pObj->Id, Ivy_ObjIsLatch(pObj)? "(latch)": "" ); + } + *pnChoices = nChoices; + return nChoiceNodes; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ) +{ + int nChoices, nChoiceNodes; + + assert( p->pHaig != NULL ); + + if ( fVerbose ) + { + printf( "Final : " ); + Ivy_ManPrintStats( p ); + printf( "HAIG : " ); + Ivy_ManPrintStats( p->pHaig ); + + // print choice node stats + nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices ); + printf( "Total choice nodes = %d. Total choices = %d. Skipped classes = %d.\n", + nChoiceNodes, nChoices, p->pHaig->nClassesSkip ); + } + + if ( Ivy_ManIsAcyclic( p->pHaig ) ) + { + if ( fVerbose ) + printf( "HAIG is acyclic\n" ); + } + else + printf( "HAIG contains a cycle\n" ); + +// if ( fVerbose ) +// Ivy_ManHaigSimulate( p ); +} + + +/**Function************************************************************* + + Synopsis [Applies the simulation rules.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 ) +{ + assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); + if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 ) + return IVY_INIT_1; + return IVY_INIT_0; +} + +/**Function************************************************************* + + Synopsis [Applies the simulation rules.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Init_t Ivy_ManHaigSimulateChoice( Ivy_Init_t In0, Ivy_Init_t In1 ) +{ + assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); + if ( (In0 == IVY_INIT_0 && In1 == IVY_INIT_1) || (In0 == IVY_INIT_1 && In1 == IVY_INIT_0) ) + { + printf( "Compatibility fails.\n" ); + return IVY_INIT_0; + } + if ( In0 == IVY_INIT_DC && In1 == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( In0 != IVY_INIT_DC ) + return In0; + return In1; +} + +/**Function************************************************************* + + Synopsis [Simulate HAIG using modified 3-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigSimulate( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes, * vLatches, * vLatchesD; + Ivy_Obj_t * pObj, * pTemp; + Ivy_Init_t In0, In1; + int i, k, Counter; + int fVerbose = 0; + + // check choices + Ivy_ManCheckChoices( p ); + + // switch to HAIG + assert( p->pHaig != NULL ); + p = p->pHaig; + +if ( fVerbose ) +Ivy_ManForEachPi( p, pObj, i ) +printf( "Setting PI %d\n", pObj->Id ); + + // collect latches and nodes in the DFS order + vNodes = Ivy_ManDfsSeq( p, &vLatches ); + +if ( fVerbose ) +Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +printf( "Collected node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); + + // set the PI values + Ivy_ManConst1(p)->Init = IVY_INIT_1; + Ivy_ManForEachPi( p, pObj, i ) + pObj->Init = IVY_INIT_0; + + // set the latch values + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Init = IVY_INIT_DC; + // set the latches of D to be determinate + vLatchesD = p->pData; + Ivy_ManForEachNodeVec( p, vLatchesD, pObj, i ) + pObj->Init = IVY_INIT_0; + + // perform several rounds of simulation + for ( k = 0; k < 10; k++ ) + { + // count the number of non-determinate values + Counter = 0; + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + Counter += ( pObj->Init == IVY_INIT_DC ); + printf( "Iter %d : Non-determinate = %d\n", k, Counter ); + + // simulate the internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + { +if ( fVerbose ) +printf( "Processing node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); + In0 = Ivy_InitNotCond( Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) ); + In1 = Ivy_InitNotCond( Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) ); + pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 ); + // simulate the equivalence class if the node is a representative + if ( pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { +if ( fVerbose ) +printf( "Processing choice node %d\n", pObj->Id ); + In0 = pObj->Init; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { +if ( fVerbose ) +printf( "Processing secondary node %d\n", pTemp->Id ); + In1 = Ivy_InitNotCond( pTemp->Init, Ivy_IsComplement(pTemp->pEquiv) ); + In0 = Ivy_ManHaigSimulateChoice( In0, In1 ); + } + pObj->Init = In0; + } + } + + // simulate the latches + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + { + pObj->Level = Ivy_ObjFanin0(pObj)->Init; +if ( fVerbose ) +printf( "Using latch %d with fanin %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id ); + } + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Init = pObj->Level, pObj->Level = 0; + } + // free arrays + Vec_IntFree( vNodes ); + Vec_IntFree( vLatches ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyIsop.c b/src/aig/ivy/ivyIsop.c new file mode 100644 index 00000000..1887eb6a --- /dev/null +++ b/src/aig/ivy/ivyIsop.c @@ -0,0 +1,328 @@ +/**CFile**************************************************************** + + FileName [ivyIsop.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Computing irredundant SOP using truth table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyIsop.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" +#include "mem.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// ISOP computation fails if intermediate memory usage exceed this limit +#define IVY_ISOP_MEM_LIMIT 16*4096 + +// intermediate ISOP representation +typedef struct Ivy_Sop_t_ Ivy_Sop_t; +struct Ivy_Sop_t_ +{ + unsigned * pCubes; + int nCubes; +}; + +// static procedures to compute ISOP +static unsigned * Ivy_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Ivy_Sop_t * pcRes, Vec_Int_t * vStore ); +static unsigned Ivy_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Ivy_Sop_t * pcRes, Vec_Int_t * vStore ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes ISOP from TT.] + + Description [Returns the cover in vCover. Uses the rest of array in vCover + as an intermediate memory storage. Returns the cover with -1 cubes, if the + the computation exceeded the memory limit (IVY_ISOP_MEM_LIMIT words of + intermediate data).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vCover, int fTryBoth ) +{ + Ivy_Sop_t cRes, * pcRes = &cRes; + Ivy_Sop_t cRes2, * pcRes2 = &cRes2; + unsigned * pResult; + int RetValue = 0; + assert( nVars >= 0 && nVars < 16 ); + // if nVars < 5, make sure it does not depend on those vars +// for ( i = nVars; i < 5; i++ ) +// assert( !Extra_TruthVarInSupport(puTruth, 5, i) ); + // prepare memory manager + Vec_IntClear( vCover ); + Vec_IntGrow( vCover, IVY_ISOP_MEM_LIMIT ); + // compute ISOP for the direct polarity + pResult = Ivy_TruthIsop_rec( puTruth, puTruth, nVars, pcRes, vCover ); + if ( pcRes->nCubes == -1 ) + { + vCover->nSize = -1; + return 0; + } + assert( Extra_TruthIsEqual( puTruth, pResult, nVars ) ); + if ( fTryBoth ) + { + // compute ISOP for the complemented polarity + Extra_TruthNot( puTruth, puTruth, nVars ); + pResult = Ivy_TruthIsop_rec( puTruth, puTruth, nVars, pcRes2, vCover ); + if ( pcRes2->nCubes >= 0 ) + { + assert( Extra_TruthIsEqual( puTruth, pResult, nVars ) ); + if ( pcRes->nCubes > pcRes2->nCubes ) + { + RetValue = 1; + pcRes = pcRes2; + } + } + Extra_TruthNot( puTruth, puTruth, nVars ); + } +// printf( "%d ", vCover->nSize ); + // move the cover representation to the beginning of the memory buffer + memmove( vCover->pArray, pcRes->pCubes, pcRes->nCubes * sizeof(unsigned) ); + Vec_IntShrink( vCover, pcRes->nCubes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Computes ISOP 6 variables or more.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Ivy_Sop_t * pcRes, Vec_Int_t * vStore ) +{ + Ivy_Sop_t cRes0, cRes1, cRes2; + Ivy_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; + unsigned * puRes0, * puRes1, * puRes2; + unsigned * puOn0, * puOn1, * puOnDc0, * puOnDc1, * pTemp, * pTemp0, * pTemp1; + int i, k, Var, nWords, nWordsAll; +// assert( Extra_TruthIsImply( puOn, puOnDc, nVars ) ); + // allocate room for the resulting truth table + nWordsAll = Extra_TruthWordNum( nVars ); + pTemp = Vec_IntFetch( vStore, nWordsAll ); + if ( pTemp == NULL ) + { + pcRes->nCubes = -1; + return NULL; + } + // check for constants + if ( Extra_TruthIsConst0( puOn, nVars ) ) + { + pcRes->nCubes = 0; + pcRes->pCubes = NULL; + Extra_TruthClear( pTemp, nVars ); + return pTemp; + } + if ( Extra_TruthIsConst1( puOnDc, nVars ) ) + { + pcRes->nCubes = 1; + pcRes->pCubes = Vec_IntFetch( vStore, 1 ); + if ( pcRes->pCubes == NULL ) + { + pcRes->nCubes = -1; + return NULL; + } + pcRes->pCubes[0] = 0; + Extra_TruthFill( pTemp, nVars ); + return pTemp; + } + assert( nVars > 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Extra_TruthVarInSupport( puOn, nVars, Var ) || + Extra_TruthVarInSupport( puOnDc, nVars, Var ) ) + break; + assert( Var >= 0 ); + // consider a simple case when one-word computation can be used + if ( Var < 5 ) + { + unsigned uRes = Ivy_TruthIsop5_rec( puOn[0], puOnDc[0], Var+1, pcRes, vStore ); + for ( i = 0; i < nWordsAll; i++ ) + pTemp[i] = uRes; + return pTemp; + } + assert( Var >= 5 ); + nWords = Extra_TruthWordNum( Var ); + // cofactor + puOn0 = puOn; puOn1 = puOn + nWords; + puOnDc0 = puOnDc; puOnDc1 = puOnDc + nWords; + pTemp0 = pTemp; pTemp1 = pTemp + nWords; + // solve for cofactors + Extra_TruthSharp( pTemp0, puOn0, puOnDc1, Var ); + puRes0 = Ivy_TruthIsop_rec( pTemp0, puOnDc0, Var, pcRes0, vStore ); + if ( pcRes0->nCubes == -1 ) + { + pcRes->nCubes = -1; + return NULL; + } + Extra_TruthSharp( pTemp1, puOn1, puOnDc0, Var ); + puRes1 = Ivy_TruthIsop_rec( pTemp1, puOnDc1, Var, pcRes1, vStore ); + if ( pcRes1->nCubes == -1 ) + { + pcRes->nCubes = -1; + return NULL; + } + Extra_TruthSharp( pTemp0, puOn0, puRes0, Var ); + Extra_TruthSharp( pTemp1, puOn1, puRes1, Var ); + Extra_TruthOr( pTemp0, pTemp0, pTemp1, Var ); + Extra_TruthAnd( pTemp1, puOnDc0, puOnDc1, Var ); + puRes2 = Ivy_TruthIsop_rec( pTemp0, pTemp1, Var, pcRes2, vStore ); + if ( pcRes2->nCubes == -1 ) + { + pcRes->nCubes = -1; + return NULL; + } + // create the resulting cover + pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; + pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); + if ( pcRes->pCubes == NULL ) + { + pcRes->nCubes = -1; + return NULL; + } + k = 0; + for ( i = 0; i < pcRes0->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+1)); + for ( i = 0; i < pcRes1->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+0)); + for ( i = 0; i < pcRes2->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes2->pCubes[i]; + assert( k == pcRes->nCubes ); + // create the resulting truth table + Extra_TruthOr( pTemp0, puRes0, puRes2, Var ); + Extra_TruthOr( pTemp1, puRes1, puRes2, Var ); + // copy the table if needed + nWords <<= 1; + for ( i = 1; i < nWordsAll/nWords; i++ ) + for ( k = 0; k < nWords; k++ ) + pTemp[i*nWords + k] = pTemp[k]; + // verify in the end +// assert( Extra_TruthIsImply( puOn, pTemp, nVars ) ); +// assert( Extra_TruthIsImply( pTemp, puOnDc, nVars ) ); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [Computes ISOP for 5 variables or less.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Ivy_Sop_t * pcRes, Vec_Int_t * vStore ) +{ + unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + Ivy_Sop_t cRes0, cRes1, cRes2; + Ivy_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; + unsigned uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2; + int i, k, Var; + assert( nVars <= 5 ); + assert( (uOn & ~uOnDc) == 0 ); + if ( uOn == 0 ) + { + pcRes->nCubes = 0; + pcRes->pCubes = NULL; + return 0; + } + if ( uOnDc == 0xFFFFFFFF ) + { + pcRes->nCubes = 1; + pcRes->pCubes = Vec_IntFetch( vStore, 1 ); + if ( pcRes->pCubes == NULL ) + { + pcRes->nCubes = -1; + return 0; + } + pcRes->pCubes[0] = 0; + return 0xFFFFFFFF; + } + assert( nVars > 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Extra_TruthVarInSupport( &uOn, 5, Var ) || + Extra_TruthVarInSupport( &uOnDc, 5, Var ) ) + break; + assert( Var >= 0 ); + // cofactor + uOn0 = uOn1 = uOn; + uOnDc0 = uOnDc1 = uOnDc; + Extra_TruthCofactor0( &uOn0, Var + 1, Var ); + Extra_TruthCofactor1( &uOn1, Var + 1, Var ); + Extra_TruthCofactor0( &uOnDc0, Var + 1, Var ); + Extra_TruthCofactor1( &uOnDc1, Var + 1, Var ); + // solve for cofactors + uRes0 = Ivy_TruthIsop5_rec( uOn0 & ~uOnDc1, uOnDc0, Var, pcRes0, vStore ); + if ( pcRes0->nCubes == -1 ) + { + pcRes->nCubes = -1; + return 0; + } + uRes1 = Ivy_TruthIsop5_rec( uOn1 & ~uOnDc0, uOnDc1, Var, pcRes1, vStore ); + if ( pcRes1->nCubes == -1 ) + { + pcRes->nCubes = -1; + return 0; + } + uRes2 = Ivy_TruthIsop5_rec( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pcRes2, vStore ); + if ( pcRes2->nCubes == -1 ) + { + pcRes->nCubes = -1; + return 0; + } + // create the resulting cover + pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; + pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); + if ( pcRes->pCubes == NULL ) + { + pcRes->nCubes = -1; + return 0; + } + k = 0; + for ( i = 0; i < pcRes0->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+1)); + for ( i = 0; i < pcRes1->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+0)); + for ( i = 0; i < pcRes2->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes2->pCubes[i]; + assert( k == pcRes->nCubes ); + // derive the final truth table + uRes2 |= (uRes0 & ~uMasks[Var]) | (uRes1 & uMasks[Var]); +// assert( (uOn & ~uRes2) == 0 ); +// assert( (uRes2 & ~uOnDc) == 0 ); + return uRes2; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyMan.c b/src/aig/ivy/ivyMan.c new file mode 100644 index 00000000..2d99c4f1 --- /dev/null +++ b/src/aig/ivy/ivyMan.c @@ -0,0 +1,546 @@ +/**CFile**************************************************************** + + FileName [ivyMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManStart() +{ + Ivy_Man_t * p; + // start the manager + p = ALLOC( Ivy_Man_t, 1 ); + memset( p, 0, sizeof(Ivy_Man_t) ); + // perform initializations + p->Ghost.Id = -1; + p->nTravIds = 1; + p->fCatchExor = 1; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + p->vBufs = Vec_PtrAlloc( 100 ); + p->vObjs = Vec_PtrAlloc( 100 ); + // prepare the internal memory manager + Ivy_ManStartMemory( p ); + // create the constant node + p->pConst1 = Ivy_ManFetchMemory( p ); + p->pConst1->fPhase = 1; + Vec_PtrPush( p->vObjs, p->pConst1 ); + p->nCreated = 1; + // start the table + p->nTableSize = 10007; + p->pTable = ALLOC( int, p->nTableSize ); + memset( p->pTable, 0, sizeof(int) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ) +{ + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i; + // create the new manager + pNew = Ivy_ManStart(); + // create the PIs + Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); + Ivy_ManForEachPi( p, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes, * vLatches; + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i; + // collect latches and nodes in the DFS order + vNodes = Ivy_ManDfsSeq( p, &vLatches ); + // create the new manager + pNew = Ivy_ManStart(); + // create the PIs + Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); + Ivy_ManForEachPi( p, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + // create the fake PIs for latches + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + // duplicate internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + if ( Ivy_ObjIsBuf(pObj) ) + pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); + else + pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // add the POs + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) ); + // transform additional PI nodes into latches and connect them + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + { + assert( !Ivy_ObjFaninC0(pObj) ); + pObj->pEquiv->Type = IVY_LATCH; + pObj->pEquiv->Init = pObj->Init; + Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL ); + } + // shrink the arrays + Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) ); + // update the counters of different objects + pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p); + pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p); + // free arrays + Vec_IntFree( vNodes ); + Vec_IntFree( vLatches ); + // make sure structural hashing did not change anything + assert( Ivy_ManNodeNum(p) == Ivy_ManNodeNum(pNew) ); + assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) ); + // check the resulting network + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ) +{ + Vec_Ptr_t * vMapping; + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i, f, nPis, nPos, nIdMax; + assert( Ivy_ManLatchNum(pMan) == 0 ); + assert( nFrames > 0 ); + // prepare the mapping + nPis = Ivy_ManPiNum(pMan) - nLatches; + nPos = Ivy_ManPoNum(pMan) - nLatches; + nIdMax = Ivy_ManObjIdMax(pMan); + // create the new manager + pNew = Ivy_ManStart(); + // set the starting values of latch inputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew); + // add timeframes + vMapping = Vec_PtrStart( nIdMax * nFrames + 1 ); + for ( f = 0; f < nFrames; f++ ) + { + // create PIs + Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew); + for ( i = 0; i < nPis; i++ ) + Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew); + // transfer values to latch outputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv; + // perform strashing + Ivy_ManForEachNode( pMan, pObj, i ) + pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // create POs + for ( i = 0; i < nPos; i++ ) + Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) ); + // set the results of latch inputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i)); + // save the pointers in this frame + Ivy_ManForEachObj( pMan, pObj, i ) + Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv ); + } + // connect latches + if ( !fInit ) + for ( i = 0; i < nLatches; i++ ) + Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv ); + // remove dangling nodes + Ivy_ManCleanup(pNew); + *pvMapping = vMapping; + // check the resulting network + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManFrames(): The check has failed.\n" ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStop( Ivy_Man_t * p ) +{ + if ( p->time1 ) { PRT( "Update lev ", p->time1 ); } + if ( p->time2 ) { PRT( "Update levR ", p->time2 ); } +// Ivy_TableProfile( p ); +// if ( p->vFanouts ) Ivy_ManStopFanout( p ); + if ( p->vChunks ) Ivy_ManStopMemory( p ); + if ( p->vRequired ) Vec_IntFree( p->vRequired ); + if ( p->vPis ) Vec_PtrFree( p->vPis ); + if ( p->vPos ) Vec_PtrFree( p->vPos ); + if ( p->vBufs ) Vec_PtrFree( p->vBufs ); + if ( p->vObjs ) Vec_PtrFree( p->vObjs ); + free( p->pTable ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Removes nodes without fanout.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCleanup( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pNode; + int i, nNodesOld; + nNodesOld = Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pNode, i ) + if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + if ( Ivy_ObjRefs(pNode) == 0 ) + Ivy_ObjDelete_rec( p, pNode, 1 ); +//printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) ); + return nNodesOld - Ivy_ManNodeNum(p); +} + +/**Function************************************************************* + + Synopsis [Marks nodes reachable from the given one.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjIsMarkA(pObj) ) + return; + Ivy_ObjSetMarkA(pObj); + if ( pObj->pFanin0 != NULL ) + Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) ); + if ( pObj->pFanin1 != NULL ) + Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Removes logic that does not feed into POs.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCleanupSeq( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Ivy_Obj_t * pObj; + int i, RetValue; + // mark the constant and PIs + Ivy_ObjSetMarkA( Ivy_ManConst1(p) ); + Ivy_ManForEachPi( p, pObj, i ) + Ivy_ObjSetMarkA( pObj ); + // mark nodes visited from POs + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManCleanupSeq_rec( pObj ); + // collect unmarked nodes + vNodes = Vec_PtrAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( Ivy_ObjIsMarkA(pObj) ) + Ivy_ObjClearMarkA(pObj); + else + Vec_PtrPush( vNodes, pObj ); + } + if ( Vec_PtrSize(vNodes) == 0 ) + { + Vec_PtrFree( vNodes ); +//printf( "Sequential sweep cleaned out %d nodes.\n", 0 ); + return 0; + } + // disconnect the marked objects + Vec_PtrForEachEntry( vNodes, pObj, i ) + Ivy_ObjDisconnect( p, pObj ); + // remove the dangling objects + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) ); + assert( Ivy_ObjRefs(pObj) == 0 ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // delete buffer from the array of buffers + if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) + Vec_PtrRemove( p->vBufs, pObj ); + // free the node + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + } + // return the number of nodes freed + RetValue = Vec_PtrSize(vNodes); + Vec_PtrFree( vNodes ); +//printf( "Sequential sweep cleaned out %d nodes.\n", RetValue ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot ) +{ + if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) ) + return 0; + if ( pLatch == pLatchRoot ) + return 1; + return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch ) +{ + if ( !Ivy_ObjIsLatch(pLatch) ) + return 0; + return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch ); +} + + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ) +{ + Ivy_Obj_t * pNode; + int LimitFactor = 10; + int NodeBeg = Ivy_ManNodeNum(p); + int nSteps; + for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) + { + pNode = Vec_PtrEntryLast(p->vBufs); + while ( Ivy_ObjIsBuf(pNode) ) + pNode = Ivy_ObjReadFirstFanout( p, pNode ); + // check if this buffer should remain + if ( Ivy_ManLatchIsSelfFeed(pNode) ) + { + Vec_PtrPop(p->vBufs); + continue; + } +//printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id ); +//printf( "Latch num %d\n", Ivy_ManLatchNum(p) ); + Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel ); + if ( nSteps > NodeBeg * LimitFactor ) + { + printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor ); + printf( "This circuit cannot be forward-retimed completely. Quitting.\n" ); + break; + } + } +// printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) ); + return nSteps; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManPrintStats( Ivy_Man_t * p ) +{ + printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) ); + printf( "A = %7d. ", Ivy_ManAndNum(p) ); + printf( "L = %5d. ", Ivy_ManLatchNum(p) ); +// printf( "X = %d. ", Ivy_ManExorNum(p) ); +// printf( "B = %3d. ", Ivy_ManBufNum(p) ); + printf( "MaxID = %7d. ", Ivy_ManObjIdMax(p) ); +// printf( "Cre = %d. ", p->nCreated ); +// printf( "Del = %d. ", p->nDeleted ); + printf( "Lev = %3d. ", Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Converts a combinational AIG manager into a sequential one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ) +{ + Ivy_Obj_t * pObj, * pLatch; + Ivy_Init_t Init; + int i; + if ( nLatches == 0 ) + return; + assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) ); + assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) ); + assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) ); + assert( Vec_PtrSize( p->vBufs ) == 0 ); + // create fanouts + if ( p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // collect the POs to be converted into latches + for ( i = 0; i < nLatches; i++ ) + { + // get the latch value + Init = pInits? pInits[i] : IVY_INIT_0; + // create latch + pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i ); + pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init ); + Ivy_ObjDisconnect( p, pObj ); + // recycle the old PO object + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + // convert the corresponding PI to a buffer and connect it to the latch + pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i ); + pObj->Type = IVY_BUF; + Ivy_ObjConnect( p, pObj, pLatch, NULL ); + // save the buffer + Vec_PtrPush( p->vBufs, pObj ); + } + // shrink the arrays + Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches ); + Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches ); + // update the counters of different objects + p->nObjs[IVY_PI] -= nLatches; + p->nObjs[IVY_PO] -= nLatches; + p->nObjs[IVY_BUF] += nLatches; + p->nDeleted -= 2 * nLatches; + // remove dangling nodes + Ivy_ManCleanup(p); + Ivy_ManCleanupSeq(p); +/* + // check for dangling nodes + Ivy_ManForEachObj( p, pObj, i ) + if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) ) + { + assert( Ivy_ObjRefs(pObj) > 0 ); + assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) ); + } +*/ + // perform hashing by propagating the buffers + Ivy_ManPropagateBuffers( p, 0 ); + if ( Ivy_ManBufNum(p) ) + printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) ); + // fix the levels + Ivy_ManResetLevels( p ); + // check the resulting network + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyMem.c b/src/aig/ivy/ivyMem.c new file mode 100644 index 00000000..09c73c49 --- /dev/null +++ b/src/aig/ivy/ivyMem.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [ivyMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Memory management for the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes +#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStartMemory( Ivy_Man_t * p ) +{ + p->vChunks = Vec_PtrAlloc( 128 ); + p->vPages = Vec_PtrAlloc( 128 ); +} + +/**Function************************************************************* + + Synopsis [Stops the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStopMemory( Ivy_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( p->vChunks, pMemory, i ) + free( pMemory ); + Vec_PtrFree( p->vChunks ); + Vec_PtrFree( p->vPages ); + p->pListFree = NULL; +} + +/**Function************************************************************* + + Synopsis [Allocates additional memory for the nodes.] + + Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. + Records the pointer to the AIG manager in the -1 entry.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManAddMemory( Ivy_Man_t * p ) +{ + char * pMemory; + int i, nBytes; + assert( sizeof(Ivy_Obj_t) <= 64 ); + assert( p->pListFree == NULL ); +// assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); + // allocate new memory page + nBytes = sizeof(Ivy_Obj_t) * (1<vChunks, pMemory ); + // align memory at the 32-byte boundary + pMemory = pMemory + 64 - (((int)pMemory) & 63); + // remember the manager in the first entry + Vec_PtrPush( p->vPages, pMemory ); + // break the memory down into nodes + p->pListFree = (Ivy_Obj_t *)pMemory; + for ( i = 1; i <= IVY_PAGE_MASK; i++ ) + { + *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t); + pMemory += sizeof(Ivy_Obj_t); + } + *((char **)pMemory) = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyMulti.c b/src/aig/ivy/ivyMulti.c new file mode 100644 index 00000000..a7970156 --- /dev/null +++ b/src/aig/ivy/ivyMulti.c @@ -0,0 +1,301 @@ +/**CFile**************************************************************** + + FileName [ivyMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Constructing multi-input AND/EXOR gates.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_EVAL_LIMIT 128 + +typedef struct Ivy_Eva_t_ Ivy_Eva_t; +struct Ivy_Eva_t_ +{ + Ivy_Obj_t * pArg; // the argument node + unsigned Mask; // the mask of covered nodes + int Weight; // the number of covered nodes +}; + +static void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ); +static int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs a balanced tree while taking sharing into account.] + + Description [Returns 1 if the implementation exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols ) +{ + static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT]; + Ivy_Eva_t * pEval, * pFan0, * pFan1; + Ivy_Obj_t * pObj, * pTemp; + int nEvals, nEvalsOld, i, k, x, nLeaves; + unsigned uMaskAll; + + // consider special cases + nLeaves = Vec_PtrSize(vLeaves); + assert( nLeaves > 2 ); + if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT ) + return 0; +// if ( nLeaves == 1 ) +// return Vec_PtrEntry( vLeaves, 0 ); +// if ( nLeaves == 2 ) +// return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type ); + + // set the leaf entries + uMaskAll = ((1 << nLeaves) - 1); + nEvals = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + pEval = pEvals + nEvals; + pEval->pArg = pObj; + pEval->Mask = (1 << nEvals); + pEval->Weight = 1; + // mark the leaf + Ivy_Regular(pObj)->TravId = nEvals; + nEvals++; + } + + // propagate masks through the cone + Vec_PtrForEachEntry( vCone, pObj, i ) + { + pObj->TravId = nEvals + i; + if ( Ivy_ObjIsBuf(pObj) ) + pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask; + else + pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask; + } + + // set the internal entries + Vec_PtrForEachEntry( vCone, pObj, i ) + { + if ( i == Vec_PtrSize(vCone) - 1 ) + break; + // skip buffers + if ( Ivy_ObjIsBuf(pObj) ) + continue; + // skip nodes without external fanout + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + assert( !Ivy_IsComplement(pObj) ); + pEval = pEvals + nEvals; + pEval->pArg = pObj; + pEval->Mask = pEvals[pObj->TravId].Mask; + pEval->Weight = Extra_WordCountOnes(pEval->Mask); + // mark the node + pObj->TravId = nEvals; + nEvals++; + } + + // find the available nodes + nEvalsOld = nEvals; + for ( i = 1; i < nEvals; i++ ) + for ( k = 0; k < i; k++ ) + { + pFan0 = pEvals + i; + pFan1 = pEvals + k; + pTemp = Ivy_TableLookup(p, Ivy_ObjCreateGhost(p, pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE)); + // skip nodes in the cone + if ( pTemp == NULL || pTemp->fMarkB ) + continue; + // skip the leaves + for ( x = 0; x < nLeaves; x++ ) + if ( pTemp == Ivy_Regular(vLeaves->pArray[x]) ) + break; + if ( x < nLeaves ) + continue; + pEval = pEvals + nEvals; + pEval->pArg = pTemp; + pEval->Mask = pFan0->Mask | pFan1->Mask; + pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight; + // save the argument + pObj->TravId = nEvals; + nEvals++; + // quit if the number of entries exceeded the limit + if ( nEvals == IVY_EVAL_LIMIT ) + goto Outside; + // quit if we found an acceptable implementation + if ( pEval->Mask == uMaskAll ) + goto Outside; + } +Outside: + +// Ivy_MultiPrint( pEvals, nLeaves, nEvals ); + if ( !Ivy_MultiCover( p, pEvals, nLeaves, nEvals, nLimit, vSols ) ) + return 0; + assert( Vec_PtrSize( vSols ) > 0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes how many uncovered ones this one covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ) +{ + Ivy_Eva_t * pEval; + int i, k; + for ( i = nLeaves; i < nEvals; i++ ) + { + pEval = pEvals + i; + printf( "%2d (id = %5d) : |", i-nLeaves, Ivy_ObjId(pEval->pArg) ); + for ( k = 0; k < nLeaves; k++ ) + { + if ( pEval->Mask & (1 << k) ) + printf( "+" ); + else + printf( " " ); + } + printf( "| Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) ); + } +} + +/**Function************************************************************* + + Synopsis [Computes how many uncovered ones this one covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound ) +{ + assert( uMask & ~uFound ); + if ( (uMask & uFound) == 0 ) + return nMaskOnes; + return Extra_WordCountOnes( uMask & ~uFound ); +} + +/**Function************************************************************* + + Synopsis [Finds the cover.] + + Description [Returns 1 if the cover is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ) +{ + int fVerbose = 0; + Ivy_Eva_t * pEval, * pEvalBest; + unsigned uMaskAll, uFound, uTemp; + int i, k, BestK, WeightBest, WeightCur, LevelBest, LevelCur; + uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1); + uFound = 0; + // solve the covering problem + if ( fVerbose ) + printf( "Solution: " ); + Vec_PtrClear( vSols ); + for ( i = 0; i < nLimit; i++ ) + { + BestK = -1; + for ( k = nEvals - 1; k >= 0; k-- ) + { + pEval = pEvals + k; + if ( (pEval->Mask & ~uFound) == 0 ) + continue; + if ( BestK == -1 ) + { + BestK = k; + pEvalBest = pEval; + WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound ); + LevelBest = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) ); + continue; + } + // compare BestK and the new one (k) + WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound ); + LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) ); + if ( WeightBest < WeightCur || + (WeightBest == WeightCur && LevelBest > LevelCur) ) + { + BestK = k; + pEvalBest = pEval; + WeightBest = WeightCur; + LevelBest = LevelCur; + } + } + assert( BestK != -1 ); + // if the cost is only 1, take the leaf + if ( WeightBest == 1 && BestK >= nLeaves ) + { + uTemp = (pEvalBest->Mask & ~uFound); + for ( k = 0; k < nLeaves; k++ ) + if ( uTemp & (1 << k) ) + break; + assert( k < nLeaves ); + BestK = k; + pEvalBest = pEvals + BestK; + } + if ( fVerbose ) + { + if ( BestK < nLeaves ) + printf( "L(%d) ", BestK ); + else + printf( "%d ", BestK - nLeaves ); + } + // update the found set + Vec_PtrPush( vSols, pEvalBest->pArg ); + uFound |= pEvalBest->Mask; + if ( uFound == uMaskAll ) + break; + } + if ( uFound == uMaskAll ) + { + if ( fVerbose ) + printf( " Found \n\n" ); + return 1; + } + else + { + if ( fVerbose ) + printf( " Not found \n\n" ); + return 0; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyMulti8.c b/src/aig/ivy/ivyMulti8.c new file mode 100644 index 00000000..059d1500 --- /dev/null +++ b/src/aig/ivy/ivyMulti8.c @@ -0,0 +1,427 @@ +/**CFile**************************************************************** + + FileName [ivyMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Constructing multi-input AND/EXOR gates.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_Eval_t_ Ivy_Eval_t; +struct Ivy_Eval_t_ +{ + unsigned Mask : 5; // the mask of covered nodes + unsigned Weight : 3; // the number of covered nodes + unsigned Cost : 4; // the number of overlapping nodes + unsigned Level : 12; // the level of this node + unsigned Fan0 : 4; // the first fanin + unsigned Fan1 : 4; // the second fanin +}; + +static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ); +static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ); +static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type ); + pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Ivy_Oper( pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Constructs a balanced tree while taking sharing into account.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type ) +{ + static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5}; + static Ivy_Eval_t pEvals[15+15*14/2]; + static Ivy_Obj_t * pArgs[16]; + Ivy_Eval_t * pEva, * pEvaBest; + int nArgsNew, nEvals, i, k; + Ivy_Obj_t * pTemp; + + // consider the case of one argument + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgsInit[0]; + // consider the case of two arguments + if ( nArgs == 2 ) + return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type ); + +//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" ); + + // set the initial ones + for ( i = 0; i < nArgs; i++ ) + { + pArgs[i] = pArgsInit[i]; + pEva = pEvals + i; + pEva->Mask = (1 << i); + pEva->Weight = 1; + pEva->Cost = 0; + pEva->Level = Ivy_Regular(pArgs[i])->Level; + pEva->Fan0 = 0; + pEva->Fan1 = 0; + } + + // find the available nodes + pEvaBest = pEvals; + nArgsNew = nArgs; + for ( i = 1; i < nArgsNew; i++ ) + for ( k = 0; k < i; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) ) + { + pEva = pEvals + nArgsNew; + pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; + pEva->Weight = NumBits[pEva->Mask]; + pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; + pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); + pEva->Fan0 = k; + pEva->Fan1 = i; +// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) ); + // compare + if ( pEvaBest->Weight < pEva->Weight || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) + pEvaBest = pEva; + // save the argument + pArgs[nArgsNew++] = pTemp; + if ( nArgsNew == 15 ) + goto Outside; + } +Outside: + +// printf( "Best = %d.\n", pEvaBest - pEvals ); + + // the case of no common nodes + if ( nArgsNew == nArgs ) + { + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); + } + // the case of one common node + if ( nArgsNew == nArgs + 1 ) + { + assert( pEvaBest - pEvals == nArgs ); + k = 0; + for ( i = 0; i < nArgs; i++ ) + if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 ) + pArgs[k++] = pArgs[i]; + pArgs[k++] = pArgs[nArgs]; + assert( k == nArgs - 1 ); + nArgs = k; + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); + } + // the case when there is a node that covers everything + if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) ) + return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); + + // evaluate node pairs + nEvals = nArgsNew; + for ( i = 1; i < nArgsNew; i++ ) + for ( k = 0; k < i; k++ ) + { + pEva = pEvals + nEvals; + pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; + pEva->Weight = NumBits[pEva->Mask]; + pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; + pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); + pEva->Fan0 = k; + pEva->Fan1 = i; + // compare + if ( pEvaBest->Weight < pEva->Weight || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) + pEvaBest = pEva; + // save the argument + nEvals++; + } + assert( pEvaBest - pEvals >= nArgsNew ); + +// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 ); + + // get the best implementation + pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); + + // collect those not covered by EvaBest + k = 0; + for ( i = 0; i < nArgs; i++ ) + if ( (pEvaBest->Mask & (1 << i)) == 0 ) + pArgs[k++] = pArgs[i]; + pArgs[k++] = pTemp; + assert( k == nArgs - (int)pEvaBest->Weight + 1 ); + nArgs = k; + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements multi-input AND/EXOR operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pNode0, * pNode1; + if ( iNum < nArgs ) + return pArgs[iNum]; + pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type ); + pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type ); + return Ivy_Oper( pNode0, pNode1, Type ); +} + +/**Function************************************************************* + + Synopsis [Selection-sorts the nodes in the decreasing over of level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ) +{ + Ivy_Obj_t * pTemp; + int i, j, iBest; + + for ( i = 0; i < nArgs-1; i++ ) + { + iBest = i; + for ( j = i+1; j < nArgs; j++ ) + if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level ) + iBest = j; + pTemp = pArgs[i]; + pArgs[i] = pArgs[iBest]; + pArgs[iBest] = pTemp; + } +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNode1, * pNode2; + int i; + // try to find the node in the array + for ( i = 0; i < nArgs; i++ ) + if ( pArray[i] == pNode ) + return nArgs; + // put the node last + pArray[nArgs++] = pNode; + // find the place to put the new node + for ( i = nArgs-1; i > 0; i-- ) + { + pNode1 = pArray[i ]; + pNode2 = pArray[i-1]; + if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level ) + break; + pArray[i ] = pNode2; + pArray[i-1] = pNode1; + } + return nArgs; +} + +/**Function************************************************************* + + Synopsis [Balances the array recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pNodeNew; + // consider the case of one argument + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgs[0]; + // consider the case of two arguments + if ( nArgs == 2 ) + return Ivy_Oper( pArgs[0], pArgs[1], Type ); + // get the last two nodes + pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type ); + // add the new node + nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements multi-input AND/EXOR operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pTemp; + int i, k; + int nArgsOld = nArgs; + for ( i = 0; i < nArgs; i++ ) + printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level ); + for ( i = 1; i < nArgs; i++ ) + for ( k = 0; k < i; k++ ) + { + pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)); + if ( pTemp != NULL ) + { + printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i ); + pArgs[nArgs++] = pTemp; + } + } + printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld ); + return NULL; +} + + + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pArgsRef[5], * pTemp; + int i, k, m, nArgsNew, Counter = 0; + + +//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" ); + + + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgs[0]; + + // find the nodes with more than one fanout + nArgsNew = 0; + for ( i = 0; i < nArgs; i++ ) + if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 ) + pArgsRef[nArgsNew++] = pArgs[i]; + + // go through pairs + if ( nArgsNew >= 2 ) + for ( i = 0; i < nArgsNew; i++ ) + for ( k = i + 1; k < nArgsNew; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) + Counter++; +// printf( "%d", Counter ); + + // go through pairs + if ( nArgsNew >= 2 ) + for ( i = 0; i < nArgsNew; i++ ) + for ( k = i + 1; k < nArgsNew; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) + { + nArgsNew = 0; + for ( m = 0; m < nArgs; m++ ) + if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] ) + pArgs[nArgsNew++] = pArgs[m]; + pArgs[nArgsNew++] = pTemp; + assert( nArgsNew == nArgs - 1 ); + return Ivy_Multi1( pArgs, nArgsNew, Type ); + } + return Ivy_Multi_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + return Ivy_Multi_rec( pArgs, nArgs, Type ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyObj.c b/src/aig/ivy/ivyObj.c new file mode 100644 index 00000000..59dda19c --- /dev/null +++ b/src/aig/ivy/ivyObj.c @@ -0,0 +1,476 @@ +/**CFile**************************************************************** + + FileName [ivyObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Adding/removing objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ) +{ + return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, NULL, NULL, IVY_PI, IVY_INIT_NONE) ); +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ) +{ + return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pDriver, NULL, IVY_PO, IVY_INIT_NONE) ); +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) +{ + Ivy_Obj_t * pObj; + assert( !Ivy_IsComplement(pGhost) ); + assert( Ivy_ObjIsGhost(pGhost) ); + assert( Ivy_TableLookup(p, pGhost) == NULL ); + // get memory for the new object + pObj = Ivy_ManFetchMemory( p ); + assert( Ivy_ObjIsNone(pObj) ); + pObj->Id = Vec_PtrSize(p->vObjs); + Vec_PtrPush( p->vObjs, pObj ); + // add basic info (fanins, compls, type, init) + pObj->Type = pGhost->Type; + pObj->Init = pGhost->Init; + // add connections + Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); + // compute level + if ( Ivy_ObjIsNode(pObj) ) + pObj->Level = Ivy_ObjLevelNew(pObj); + else if ( Ivy_ObjIsLatch(pObj) ) + pObj->Level = 0; + else if ( Ivy_ObjIsOneFanin(pObj) ) + pObj->Level = Ivy_ObjFanin0(pObj)->Level; + else if ( !Ivy_ObjIsPi(pObj) ) + assert( 0 ); + // create phase + if ( Ivy_ObjIsNode(pObj) ) + pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); + else if ( Ivy_ObjIsOneFanin(pObj) ) + pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); + // set the fail TFO flag + if ( Ivy_ObjIsNode(pObj) ) + pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo; + // mark the fanins in a special way if the node is EXOR + if ( Ivy_ObjIsExor(pObj) ) + { + Ivy_ObjFanin0(pObj)->fExFan = 1; + Ivy_ObjFanin1(pObj)->fExFan = 1; + } + // add PIs/POs to the arrays + if ( Ivy_ObjIsPi(pObj) ) + Vec_PtrPush( p->vPis, pObj ); + else if ( Ivy_ObjIsPo(pObj) ) + Vec_PtrPush( p->vPos, pObj ); +// else if ( Ivy_ObjIsBuf(pObj) ) +// Vec_PtrPush( p->vBufs, pObj ); + if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id ) + Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 ); + // update node counters of the manager + p->nObjs[Ivy_ObjType(pObj)]++; + p->nCreated++; + +// printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " ); +// Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL ); +// printf( "\n" ); + + // if HAIG is defined, create a corresponding node + if ( p->pHaig ) + Ivy_ManHaigCreateObj( p, pObj ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL ); + // add the first fanin + pObj->pFanin0 = pFan0; + pObj->pFanin1 = pFan1; + // increment references of the fanins and add their fanouts + if ( Ivy_ObjFanin0(pObj) != NULL ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); + } + if ( Ivy_ObjFanin1(pObj) != NULL ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } + // add the node to the structural hash table + Ivy_TableInsert( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL ); + // remove connections + if ( pObj->pFanin0 != NULL ) + { + Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj)); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj ); + } + if ( pObj->pFanin1 != NULL ) + { + Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj)); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } + assert( pObj->pNextFan0 == NULL ); + assert( pObj->pNextFan1 == NULL ); + assert( pObj->pPrevFan0 == NULL ); + assert( pObj->pPrevFan1 == NULL ); + // remove the node from the structural hash table + Ivy_TableDelete( p, pObj ); + // add the first fanin + pObj->pFanin0 = NULL; + pObj->pFanin1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Replaces the first fanin of the node by the new fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ) +{ + Ivy_Obj_t * pFaninOld; + assert( !Ivy_IsComplement(pObj) ); + pFaninOld = Ivy_ObjFanin0(pObj); + // decrement ref and remove fanout + Ivy_ObjRefsDec( pFaninOld ); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, pFaninOld, pObj ); + // update the fanin + pObj->pFanin0 = pFaninNew; + // increment ref and add fanout + Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj ); + // get rid of old fanin + if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 ) + Ivy_ObjDelete_rec( p, pFaninOld, 1 ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // remove connections + Ivy_ObjDisconnect( p, pObj ); + // remove PIs/POs from the arrays + if ( Ivy_ObjIsPi(pObj) ) + Vec_PtrRemove( p->vPis, pObj ); + else if ( Ivy_ObjIsPo(pObj) ) + Vec_PtrRemove( p->vPos, pObj ); + else if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) + Vec_PtrRemove( p->vBufs, pObj ); + // clean and recycle the entry + if ( fFreeTop ) + { + // free the node + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + } + else + { + int nRefsOld = pObj->nRefs; + Ivy_Obj_t * pFanout = pObj->pFanout; + Ivy_ObjClean( pObj ); + pObj->pFanout = pFanout; + pObj->nRefs = nRefsOld; + } +} + +/**Function************************************************************* + + Synopsis [Deletes the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) +{ + Ivy_Obj_t * pFanin0, * pFanin1; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_ObjIsNone(pObj) ); + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) ) + return; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + Ivy_ObjDelete( p, pObj, fFreeTop ); + if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 ) + Ivy_ObjDelete_rec( p, pFanin0, 1 ); + if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 ) + Ivy_ObjDelete_rec( p, pFanin1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces one object by another.] + + Description [Both objects are currently in the manager. The new object + (pObjNew) should be used instead of the old object (pObjOld). If the + new object is complemented or used, the buffer is added.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ) +{ + int nRefsOld;//, clk; + // the object to be replaced cannot be complemented + assert( !Ivy_IsComplement(pObjOld) ); + // the object to be replaced cannot be a terminal + assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) ); + // the object to be used cannot be a PO or assert + assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) ); + // the object cannot be the same + assert( pObjOld != Ivy_Regular(pObjNew) ); +//printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id ); + + // if HAIG is defined, create the choice node + if ( p->pHaig ) + { +// if ( pObjOld->Id == 31 ) +// { +// Ivy_ManShow( p, 0 ); +// Ivy_ManShow( p->pHaig, 1 ); +// } + Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew ); + } + // if the new object is complemented or already used, add the buffer + if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) + pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) ); + assert( !Ivy_IsComplement(pObjNew) ); + if ( fUpdateLevel ) + { +//clk = clock(); + // if the new node's arrival time is different, recursively update arrival time of the fanouts + if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level ) + { + assert( Ivy_ObjIsNode(pObjOld) ); + pObjOld->Level = pObjNew->Level; + Ivy_ObjUpdateLevel_rec( p, pObjOld ); + } +//p->time1 += clock() - clk; + // if the new node's required time has changed, recursively update required time of the fanins +//clk = clock(); + if ( p->vRequired ) + { + int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id); + if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) ) + { + Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew ); + Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew ); + } + } +//p->time2 += clock() - clk; + } + // delete the old object + if ( fDeleteOld ) + Ivy_ObjDelete_rec( p, pObjOld, fFreeTop ); + // make sure object is not pointing to itself + assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) ); + assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) ); + // make sure the old node has no fanin fanout pointers + if ( p->fFanout ) + { + assert( pObjOld->pFanout != NULL ); + assert( pObjNew->pFanout == NULL ); + pObjNew->pFanout = pObjOld->pFanout; + } + // transfer the old object + assert( Ivy_ObjRefs(pObjNew) == 0 ); + nRefsOld = pObjOld->nRefs; + Ivy_ObjOverwrite( pObjOld, pObjNew ); + pObjOld->nRefs = nRefsOld; + // patch the fanout of the fanins + if ( p->fFanout ) + { + Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld ); + if ( Ivy_ObjFanin1(pObjOld) ) + Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld ); + } + // update the hash table + Ivy_TableUpdate( p, pObjNew, pObjOld->Id ); + // recycle the object that was taken over by pObjOld + Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL ); + Ivy_ManRecycleMemory( p, pObjNew ); + // if the new node is the buffer propagate it + if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) ) + Vec_PtrPush( p->vBufs, pObjOld ); +// Ivy_ManCheckFanouts( p ); +// printf( "\n" ); +/* + if ( p->pHaig ) + { + int x; + Ivy_ManShow( p, 0, NULL ); + Ivy_ManShow( p->pHaig, 1, NULL ); + x = 0; + } +*/ +// if ( Ivy_ManCheckFanoutNums(p) ) +// { +// int x = 0; +// } +} + +/**Function************************************************************* + + Synopsis [Fixes buffer fanins.] + + Description [This situation happens because NodeReplace is a lazy + procedure, which does not propagate the change to the fanouts but + instead records the change in the form of a buf/inv node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ) +{ + Ivy_Obj_t * pFanReal0, * pFanReal1, * pResult; + if ( Ivy_ObjIsPo(pNode) ) + { + if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ) + return; + pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); + Ivy_ObjPatchFanin0( p, pNode, pFanReal0 ); +// Ivy_ManCheckFanouts( p ); + return; + } + if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) && !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ) + return; + // get the real fanins + pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); + pFanReal1 = Ivy_ObjReal( Ivy_ObjChild1(pNode) ); + // get the new node + if ( Ivy_ObjIsNode(pNode) ) + pResult = Ivy_Oper( p, pFanReal0, pFanReal1, Ivy_ObjType(pNode) ); + else if ( Ivy_ObjIsLatch(pNode) ) + pResult = Ivy_Latch( p, pFanReal0, Ivy_ObjInit(pNode) ); + else + assert( 0 ); + +//printf( "===== Replacing %d by %d.\n", pNode->Id, pResult->Id ); +//Ivy_ObjPrintVerbose( p, pNode, 0 ); printf( "\n" ); +//Ivy_ObjPrintVerbose( p, pResult, 0 ); printf( "\n" ); + + // perform the replacement + Ivy_ObjReplace( p, pNode, pResult, 1, 0, fUpdateLevel ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyOper.c b/src/aig/ivy/ivyOper.c new file mode 100644 index 00000000..8115ce4f --- /dev/null +++ b/src/aig/ivy/ivyOper.c @@ -0,0 +1,293 @@ +/**CFile**************************************************************** + + FileName [ivyOper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedure to detect an EXOR gate +static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 ) +{ + if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) ) + return 0; + p0 = Ivy_Regular(p0); + p1 = Ivy_Regular(p1); + if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) ) + return 0; + if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) ) + return 0; + if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Ivy_ObjChild0(p0); + *ppFan1 = Ivy_ObjChild1(p0); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Perform one operation.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ) +{ + if ( Type == IVY_AND ) + return Ivy_And( p, p0, p1 ); + if ( Type == IVY_EXOR ) + return Ivy_Exor( p, p0, p1 ); + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ +// Ivy_Obj_t * pFan0, * pFan1; + // check trivial cases + if ( p0 == p1 ) + return p0; + if ( p0 == Ivy_Not(p1) ) + return Ivy_Not(p->pConst1); + if ( Ivy_Regular(p0) == p->pConst1 ) + return p0 == p->pConst1 ? p1 : Ivy_Not(p->pConst1); + if ( Ivy_Regular(p1) == p->pConst1 ) + return p1 == p->pConst1 ? p0 : Ivy_Not(p->pConst1); + // check if it can be an EXOR gate +// if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) +// return Ivy_CanonExor( pFan0, pFan1 ); + return Ivy_CanonAnd( p, p0, p1 ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ +/* + // check trivial cases + if ( p0 == p1 ) + return Ivy_Not(p->pConst1); + if ( p0 == Ivy_Not(p1) ) + return p->pConst1; + if ( Ivy_Regular(p0) == p->pConst1 ) + return Ivy_NotCond( p1, p0 == p->pConst1 ); + if ( Ivy_Regular(p1) == p->pConst1 ) + return Ivy_NotCond( p0, p1 == p->pConst1 ); + // check the table + return Ivy_CanonExor( p, p0, p1 ); +*/ + return Ivy_Or( p, Ivy_And(p, p0, Ivy_Not(p1)), Ivy_And(p, Ivy_Not(p0), p1) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ + return Ivy_Not( Ivy_And( p, Ivy_Not(p0), Ivy_Not(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ) +{ + Ivy_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; + int Count0, Count1; + // consider trivial cases + if ( p0 == Ivy_Not(p1) ) + return Ivy_Exor( p, pC, p0 ); + // other cases can be added + // implement the first MUX (F = C * x1 + C' * x0) + pTempA1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, p1, IVY_AND, IVY_INIT_NONE) ); + pTempA2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), p0, IVY_AND, IVY_INIT_NONE) ); + if ( pTempA1 && pTempA2 ) + { + pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempA1), Ivy_Not(pTempA2), IVY_AND, IVY_INIT_NONE) ); + if ( pTemp ) return Ivy_Not(pTemp); + } + Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); + // implement the second MUX (F' = C * x1' + C' * x0') + pTempB1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, Ivy_Not(p1), IVY_AND, IVY_INIT_NONE) ); + pTempB2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), Ivy_Not(p0), IVY_AND, IVY_INIT_NONE) ); + if ( pTempB1 && pTempB2 ) + { + pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempB1), Ivy_Not(pTempB2), IVY_AND, IVY_INIT_NONE) ); + if ( pTemp ) return pTemp; + } + Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); + // compare and decide which one to implement + if ( Count0 >= Count1 ) + { + pTempA1 = pTempA1? pTempA1 : Ivy_And(p, pC, p1); + pTempA2 = pTempA2? pTempA2 : Ivy_And(p, Ivy_Not(pC), p0); + return Ivy_Or( p, pTempA1, pTempA2 ); + } + pTempB1 = pTempB1? pTempB1 : Ivy_And(p, pC, Ivy_Not(p1)); + pTempB2 = pTempB2? pTempB2 : Ivy_And(p, Ivy_Not(pC), Ivy_Not(p0)); + return Ivy_Not( Ivy_Or( p, pTempB1, pTempB2 ) ); + +// return Ivy_Or( Ivy_And(pC, p1), Ivy_And(Ivy_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ) +{ + return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) ); +} + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Ivy_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Ivy_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + return Ivy_Multi_rec( p, pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ) +{ + int i; + assert( vPairs->nSize > 0 ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Ivy_Not( Ivy_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); + vPairs->nSize = vPairs->nSize/2; + return Ivy_Not( Ivy_Multi_rec( p, (Ivy_Obj_t **)vPairs->pArray, vPairs->nSize, IVY_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) +{ + return Ivy_CanonLatch( p, pObj, Init ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyResyn.c b/src/aig/ivy/ivyResyn.c new file mode 100644 index 00000000..f42d7464 --- /dev/null +++ b/src/aig/ivy/ivyResyn.c @@ -0,0 +1,196 @@ +/**CFile**************************************************************** + + FileName [ivyResyn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG rewriting script.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) +{ + int clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pMan, fUpdateLevel ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); +clk = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) +{ + int clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pMan, fUpdateLevel ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); +clk = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); +clk = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); +clk = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ) +{ + int clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + Ivy_ManRewritePre( pMan, 0, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, 0 ); +// pMan = Ivy_ManDup( pTemp = pMan ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +/* +clk = clock(); + Ivy_ManRewritePre( pMan, 0, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, 0 ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); +*/ + return pMan; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyRwr.c b/src/aig/ivy/ivyRwr.c new file mode 100644 index 00000000..3f8720ba --- /dev/null +++ b/src/aig/ivy/ivyRwr.c @@ -0,0 +1,609 @@ +/**CFile**************************************************************** + + FileName [ivyRwt.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Rewriting based on precomputation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyRwt.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" +#include "deco.h" +#include "rwt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ); +static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ); +static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, + Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ); + +static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); +static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ) +{ + Rwt_Man_t * pManRwt; + Ivy_Obj_t * pNode; + int i, nNodes, nGain; + int clk, clkStart = clock(); + // start the rewriting manager + pManRwt = Rwt_ManStart( 0 ); + p->pData = pManRwt; + if ( pManRwt == NULL ) + return 0; + // create fanouts + if ( fUpdateLevel && p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Ivy_ManRequiredLevels( p ); + // set the number of levels +// p->nLevelMax = Ivy_ManLevels( p ); + // resynthesize each node once + nNodes = Ivy_ManObjIdMax(p); + Ivy_ManForEachNode( p, pNode, i ) + { + // fix the fanin buffer problem + Ivy_NodeFixBufferFanins( p, pNode, 1 ); + if ( Ivy_ObjIsBuf(pNode) ) + continue; + // stop if all nodes have been tried once + if ( i > nNodes ) + break; + // for each cut, try to resynthesize it + nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost ); + if ( nGain > 0 || nGain == 0 && fUseZeroCost ) + { + Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt); + int fCompl = Rwt_ManReadCompl(pManRwt); +/* + { + Ivy_Obj_t * pObj; + int i; + printf( "USING: (" ); + Vec_PtrForEachEntry( Rwt_ManReadLeaves(pManRwt), pObj, i ) + printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) ); + printf( ") Gain = %d.\n", nGain ); + } + if ( nGain > 0 ) + { // print stats on the MFFC + extern void Ivy_NodeMffsConeSuppPrint( Ivy_Obj_t * pNode ); + printf( "Node %6d : Gain = %4d ", pNode->Id, nGain ); + Ivy_NodeMffsConeSuppPrint( pNode ); + } +*/ + // complement the FF if needed +clk = clock(); + if ( fCompl ) Dec_GraphComplement( pGraph ); + Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain ); + if ( fCompl ) Dec_GraphComplement( pGraph ); +Rwt_ManAddTimeUpdate( pManRwt, clock() - clk ); + } + } +Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart ); + // print stats + if ( fVerbose ) + Rwt_ManPrintStats( pManRwt ); + // delete the managers + Rwt_ManStop( pManRwt ); + p->pData = NULL; + // fix the levels + if ( fUpdateLevel ) + Vec_IntFree( p->vRequired ), p->vRequired = NULL; + else + Ivy_ManResetLevels( p ); + // check + if ( i = Ivy_ManCleanup(p) ) + printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs rewriting for one node.] + + Description [This procedure considers all the cuts computed for the node + and tries to rewrite each of them using the "forest" of different AIG + structures precomputed and stored in the RWR manager. + Determines the best rewriting and computes the gain in the number of AIG + nodes in the final network. In the end, p->vFanins contains information + about the best cut that can be used for rewriting, while p->pGraph gives + the decomposition dag (represented using decomposition graph data structure). + Returns gain in the number of nodes or -1 if node cannot be rewritten.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ) +{ + int fVeryVerbose = 0; + Dec_Graph_t * pGraph; + Ivy_Store_t * pStore; + Ivy_Cut_t * pCut; + Ivy_Obj_t * pFanin; + unsigned uPhase, uTruthBest, uTruth; + char * pPerm; + int Required, nNodesSaved, nNodesSaveCur; + int i, c, GainCur, GainBest = -1; + int clk, clk2; + + p->nNodesConsidered++; + // get the required times + Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000; + // get the node's cuts +clk = clock(); + pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 ); +p->timeCut += clock() - clk; + + // go through the cuts +clk = clock(); + for ( c = 1; c < pStore->nCuts; c++ ) + { + pCut = pStore->pCuts + c; + // consider only 4-input cuts + if ( pCut->nSize != 4 ) + continue; + // skip the cuts with buffers + for ( i = 0; i < (int)pCut->nSize; i++ ) + if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) ) + break; + if ( i != pCut->nSize ) + { + p->nCutsBad++; + continue; + } + p->nCutsGood++; + // get the fanin permutation +clk2 = clock(); + uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize ); // truth table +p->timeTruth += clock() - clk2; + pPerm = p->pPerms4[ p->pPerms[uTruth] ]; + uPhase = p->pPhases[uTruth]; + // collect fanins with the corresponding permutation/phase + Vec_PtrClear( p->vFaninsCur ); + Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); + for ( i = 0; i < (int)pCut->nSize; i++ ) + { + pFanin = Ivy_ManObj( pMan, pCut->pArray[pPerm[i]] ); + assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) ); + pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); + Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); + } +clk2 = clock(); +/* + printf( "Considering: (" ); + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) ); + printf( ")\n" ); +*/ + // mark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // label MFFC with current ID + Ivy_ManIncrementTravId( pMan ); + nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); + // unmark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +p->timeMffc += clock() - clk2; + + // evaluate the cut +clk2 = clock(); + pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth ); +p->timeEval += clock() - clk2; + + // check if the cut is better than the current best one + if ( pGraph != NULL && GainBest < GainCur ) + { + // save this form + nNodesSaveCur = nNodesSaved; + GainBest = GainCur; + p->pGraph = pGraph; + p->fCompl = ((uPhase & (1<<4)) > 0); + uTruthBest = uTruth; + // collect fanins in the + Vec_PtrClear( p->vFanins ); + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Vec_PtrPush( p->vFanins, pFanin ); + } + } +p->timeRes += clock() - clk; + + if ( GainBest == -1 ) + return -1; + +// printf( "%d", nNodesSaveCur - GainBest ); +/* + if ( GainBest > 0 ) + { + if ( Rwt_CutIsintean( pNode, p->vFanins ) ) + printf( "b" ); + else + { + printf( "Node %d : ", pNode->Id ); + Vec_PtrForEachEntry( p->vFanins, pFanin, i ) + printf( "%d ", Ivy_Regular(pFanin)->Id ); + printf( "a" ); + } + } +*/ +/* + if ( GainBest > 0 ) + if ( p->fCompl ) + printf( "c" ); + else + printf( "." ); +*/ + + // copy the leaves + Vec_PtrForEachEntry( p->vFanins, pFanin, i ) + Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; + + p->nScores[p->pMap[uTruthBest]]++; + p->nNodesGained += GainBest; + if ( fUseZeroCost || GainBest > 0 ) + p->nNodesRewritten++; + + // report the progress + if ( fVeryVerbose && GainBest > 0 ) + { + printf( "Node %6d : ", Ivy_ObjId(pNode) ); + printf( "Fanins = %d. ", p->vFanins->nSize ); + printf( "Save = %d. ", nNodesSaveCur ); + printf( "Add = %d. ", nNodesSaveCur-GainBest ); + printf( "GAIN = %d. ", GainBest ); + printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); + printf( "Class = %d. ", p->pMap[uTruthBest] ); + printf( "\n" ); + } + return GainBest; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth0, uTruth1; + int i; + for ( i = 0; i < nNums; i++ ) + if ( pObj->Id == pNums[i] ) + return uMasks[i]; + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums ); + if ( Ivy_ObjFaninC0(pObj) ) + uTruth0 = ~uTruth0; + if ( Ivy_ObjIsBuf(pObj) ) + return uTruth0; + uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums ); + if ( Ivy_ObjFaninC1(pObj) ) + uTruth1 = ~uTruth1; + return uTruth0 & uTruth1; +} + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + assert( nNums < 6 ); + return Ivy_NodeGetTruth_rec( pObj, pNums, nNums ); +} + +/**Function************************************************************* + + Synopsis [Evaluates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ) +{ + Vec_Ptr_t * vSubgraphs; + Dec_Graph_t * pGraphBest, * pGraphCur; + Rwt_Node_t * pNode, * pFanin; + int nNodesAdded, GainBest, i, k; + // find the matching class of subgraphs + vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); + p->nSubgraphs += vSubgraphs->nSize; + // determine the best subgraph + GainBest = -1; + Vec_PtrForEachEntry( vSubgraphs, pNode, i ) + { + // get the current graph + pGraphCur = (Dec_Graph_t *)pNode->pNext; + // copy the leaves + Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) + Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; + // detect how many unlabeled nodes will be reused + nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax ); + if ( nNodesAdded == -1 ) + continue; + assert( nNodesSaved >= nNodesAdded ); + // count the gain at this node + if ( GainBest < nNodesSaved - nNodesAdded ) + { + GainBest = nNodesSaved - nNodesAdded; + pGraphBest = pGraphCur; + } + } + if ( GainBest == -1 ) + return NULL; + *pGainBest = GainBest; + return pGraphBest; +} + + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, Counter, LevelNew, LevelOld; + // check for constant function or a literal + if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) + return 0; + // set the levels of the leaves + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->Level = Ivy_Regular(pNode->pFunc)->Level; + // compute the AIG size after adding the internal nodes + Counter = 0; + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // get the AIG nodes corresponding to the children + pAnd0 = pNode0->pFunc; + pAnd1 = pNode1->pFunc; + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); + pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); + // return -1 if the node is the same as the original root + if ( Ivy_Regular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + // count the number of new levels + LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level ); + if ( pAnd ) + { + if ( Ivy_Regular(pAnd) == p->pConst1 ) + LevelNew = 0; + else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) ) + LevelNew = (int)Ivy_Regular(pAnd0)->Level; + else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) ) + LevelNew = (int)Ivy_Regular(pAnd1)->Level; + LevelOld = (int)Ivy_Regular(pAnd)->Level; +// assert( LevelNew == LevelOld ); + } + if ( LevelNew > LevelMax ) + return -1; + pNode->pFunc = pAnd; + pNode->Level = LevelNew; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph ) +{ + Ivy_Obj_t * pAnd0, * pAnd1; + Dec_Node_t * pNode; + int i; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) +{ + Ivy_Obj_t * pRootNew; + int nNodesNew, nNodesOld, Required; + Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000; + nNodesOld = Ivy_ManNodeNum(p); + // create the new structure of nodes + pRootNew = Ivy_GraphToNetwork( p, pGraph ); + assert( (int)Ivy_Regular(pRootNew)->Level <= Required ); +// if ( Ivy_Regular(pRootNew)->Level == Required ) +// printf( "Difference %d.\n", Ivy_Regular(pRootNew)->Level - Required ); + // remove the old nodes +// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); +/* + if ( Ivy_IsComplement(pRootNew) ) + printf( "c" ); + else + printf( "d" ); + if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) + printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); + printf( " " ); +*/ + Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 ); + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); + // propagate the buffer + Ivy_ManPropagateBuffers( p, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) +{ + Ivy_Obj_t * pRootNew, * pFanin; + int nNodesNew, nNodesOld, i, nRefsOld; + nNodesOld = Ivy_ManNodeNum(p); + +//printf( "Before = %d. ", Ivy_ManNodeNum(p) ); + // mark the cut + Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // deref the old cone + nRefsOld = pRoot->nRefs; + pRoot->nRefs = 0; + Ivy_ObjDelete_rec( p, pRoot, 0 ); + pRoot->nRefs = nRefsOld; + // unmark the cut + Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); + + // create the new structure of nodes + pRootNew = Ivy_GraphToNetwork( p, pGraph ); +//printf( "Create = %d. ", Ivy_ManNodeNum(p) ); + // remove the old nodes +// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); +/* + if ( Ivy_IsComplement(pRootNew) ) + printf( "c" ); + else + printf( "d" ); + if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) + printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); + printf( " " ); +*/ + Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 ); +//printf( "Replace = %d. ", Ivy_ManNodeNum(p) ); + + // delete remaining dangling nodes + Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + { + pFanin = Ivy_Regular(pFanin); + if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 ) + Ivy_ObjDelete_rec( p, pFanin, 1 ); + } +//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); +//printf( "\n" ); + + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyRwrAlg.c b/src/aig/ivy/ivyRwrAlg.c new file mode 100644 index 00000000..fc48deb0 --- /dev/null +++ b/src/aig/ivy/ivyRwrAlg.c @@ -0,0 +1,408 @@ +/**CFile**************************************************************** + + FileName [ivyRwrAlg.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Algebraic AIG rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); +static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ); +static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Algebraic AIG rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ) +{ + Vec_Int_t * vRequired; + Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol; + Ivy_Obj_t * pObj, * pResult; + int i, RetValue, LevelR, nNodesOld; + int CountUsed, CountUndo; + vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL; + vFront = Vec_PtrAlloc( 100 ); + vLeaves = Vec_PtrAlloc( 100 ); + vCone = Vec_PtrAlloc( 100 ); + vSol = Vec_PtrAlloc( 100 ); + // go through the nodes in the topological order + CountUsed = CountUndo = 0; + nNodesOld = Ivy_ManObjIdNext(p); + Ivy_ManForEachObj( p, pObj, i ) + { + assert( !Ivy_ObjIsBuf(pObj) ); + if ( i >= nNodesOld ) + break; + // skip no-nodes and MUX roots + if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) ) + continue; +// if ( pObj->Id > 297 ) // 296 --- 297 +// break; + if ( pObj->Id == 297 ) + { + int x = 0; + } + // get the largest algebraic cut + RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone ); + // the case of a trivial tree cut + if ( RetValue == 1 ) + continue; + // the case of constant 0 cone + if ( RetValue == -1 ) + { + Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0, 1 ); + continue; + } + assert( Vec_PtrSize(vLeaves) > 2 ); + // get the required level for this node + LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000; + // create a new cone + pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost ); + if ( pResult == NULL || pResult == pObj ) + continue; + assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) ); + if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 ) + Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++; + else + Ivy_ObjReplace( pObj, pResult, 1, 0, 1 ), CountUsed++; + } + printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo ); + Vec_PtrFree( vFront ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSol ); + if ( vRequired ) Vec_IntFree( vRequired ); + if ( i = Ivy_ManCleanup(p) ) + printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewriteAlg(): The check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Analizes one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ) +{ + int fVerbose = 0; + Ivy_Obj_t * pTemp; + int k, Counter, nMffc, RetValue; + + if ( fVerbose ) + { + if ( Ivy_ObjIsExor(pObj) ) + printf( "x " ); + else + printf( " " ); + } + +/* + printf( "%d ", Vec_PtrSize(vFront) ); + printf( "( " ); + Vec_PtrForEachEntry( vFront, pTemp, k ) + printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); + printf( ")\n" ); +*/ + // collect nodes in the cone + if ( Ivy_ObjIsExor(pObj) ) + Ivy_ManCollectCone( pObj, vFront, vCone ); + else + Ivy_ManCollectCone( pObj, vLeaves, vCone ); + + // deref nodes in the cone + Vec_PtrForEachEntry( vCone, pTemp, k ) + { + Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) ); + Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) ); + pTemp->fMarkB = 1; + } + + // count the MFFC size + Vec_PtrForEachEntry( vFront, pTemp, k ) + Ivy_Regular(pTemp)->fMarkA = 1; + nMffc = Ivy_NodeCountMffc( pObj ); + Vec_PtrForEachEntry( vFront, pTemp, k ) + Ivy_Regular(pTemp)->fMarkA = 0; + + if ( fVerbose ) + { + Counter = 0; + Vec_PtrForEachEntry( vCone, pTemp, k ) + Counter += (Ivy_ObjRefs(pTemp) > 0); + printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d. Mffc = %d. Lev = %d. LevR = %d.\n", + pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR ); + } +/* + printf( "Leaves:" ); + Vec_PtrForEachEntry( vLeaves, pTemp, k ) + printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" ); + printf( "\n" ); + printf( "Cone:\n" ); + Vec_PtrForEachEntry( vCone, pTemp, k ) + printf( " %5d = %d%s %d%s\n", pTemp->Id, + Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "", + Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" ); +*/ + + RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols ); + + // ref nodes in the cone + Vec_PtrForEachEntry( vCone, pTemp, k ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) ); + Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) ); + pTemp->fMarkA = 0; + pTemp->fMarkB = 0; + } + + if ( !RetValue ) + return NULL; + + if ( Vec_PtrSize( vSols ) == 1 ) + return Vec_PtrEntry( vSols, 0 ); + return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode ) +{ + if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA ) + return 0; + assert( pNode->fMarkB ); + pNode->fMarkA = 1; +// printf( "%d ", pNode->Id ); + if ( Ivy_ObjIsBuf(pNode) ) + return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ); + return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ) +{ + assert( pNode->fMarkB ); + return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) +{ + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Computing one algebraic cut.] + + Description [Returns 1 if the tree-leaves of this node where traversed + and found to have no external references (and have not been collected). + Returns 0 if the tree-leaves have external references and are collected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) +{ + int RetValue0, RetValue1; + Ivy_Obj_t * pObjR = Ivy_Regular(pObj); + assert( !Ivy_ObjIsBuf(pObjR) ); + assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) ); + + // make sure the node is not visited twice in different polarities + if ( Ivy_IsComplement(pObj) ) + { // if complemented, mark B + if ( pObjR->fMarkA ) + return -1; + pObjR->fMarkB = 1; + } + else + { // if non-complicated, mark A + if ( pObjR->fMarkB ) + return -1; + pObjR->fMarkA = 1; + } + Vec_PtrPush( vCone, pObjR ); + + // if the node is the end of the tree, return + if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type ) + { + if ( Ivy_ObjRefs(pObjR) == 1 ) + return 1; + assert( Ivy_ObjRefs(pObjR) > 1 ); + Vec_PtrPush( vFront, pObj ); + return 0; + } + + // branch on the node + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // what if buffer has more than one fanout??? + RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone ); + RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone ); + if ( RetValue0 == -1 || RetValue1 == -1 ) + return -1; + + // the case when both have no external references + if ( RetValue0 && RetValue1 ) + { + if ( Ivy_ObjRefs(pObj) == 1 ) + return 1; + assert( Ivy_ObjRefs(pObj) > 1 ); + Vec_PtrPush( vFront, pObj ); + return 0; + } + // the case when one of them has external references + if ( RetValue0 ) + Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) ); + if ( RetValue1 ) + Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Computing one algebraic cut.] + + Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge, + (c) boundary of different gates. Returns 1 if this is a pure tree. + Returns -1 if the contant 0 is detected. Return 0 if the array can be used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) +{ + Ivy_Obj_t * pObj, * pPrev; + int RetValue, i; + assert( !Ivy_IsComplement(pRoot) ); + assert( Ivy_ObjIsNode(pRoot) ); + // clear the frontier and collect the nodes + Vec_PtrClear( vCone ); + Vec_PtrClear( vFront ); + Vec_PtrClear( vLeaves ); + RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone ); + // clean the marks + Vec_PtrForEachEntry( vCone, pObj, i ) + pObj->fMarkA = pObj->fMarkB = 0; + // quit if the same node is found in both polarities + if ( RetValue == -1 ) + return -1; + // return if the node is the root of a tree + if ( RetValue == 1 ) + return 1; + // return if the cut is composed of two nodes + if ( Vec_PtrSize(vFront) <= 2 ) + return 1; + // sort the entries in increasing order + Vec_PtrSort( vFront, Ivy_ManFindAlgCutCompare ); + // remove duplicates from vFront and save the nodes in vLeaves + pPrev = Vec_PtrEntry(vFront, 0); + Vec_PtrPush( vLeaves, pPrev ); + Vec_PtrForEachEntryStart( vFront, pObj, i, 1 ) + { + // compare current entry and the previous entry + if ( pObj == pPrev ) + { + if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0 + { + // vLeaves are no longer structural support of pRoot!!! + Vec_PtrPop(vLeaves); + pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves); + } + continue; + } + if ( pObj == Ivy_Not(pPrev) ) + { + assert( Ivy_ObjIsAnd(pRoot) ); + return -1; + } + pPrev = pObj; + Vec_PtrPush( vLeaves, pObj ); + } + if ( Vec_PtrSize(vLeaves) == 0 ) + return -1; + if ( Vec_PtrSize(vLeaves) <= 2 ) + return 1; + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivySeq.c b/src/aig/ivy/ivySeq.c new file mode 100644 index 00000000..263a4398 --- /dev/null +++ b/src/aig/ivy/ivySeq.c @@ -0,0 +1,1130 @@ +/**CFile**************************************************************** + + FileName [ivySeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivySeq.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" +#include "deco.h" +#include "rwt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ); +static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ); +static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ); +static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ); +static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ); +static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ); +static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ); +static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); + +static inline int Ivy_CutHashValue( int NodeId ) { return 1 << (NodeId % 31); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ) +{ + Rwt_Man_t * pManRwt; + Ivy_Obj_t * pNode; + int i, nNodes, nGain; + int clk, clkStart = clock(); + // set the DC latch values + Ivy_ManForEachLatch( p, pNode, i ) + pNode->Init = IVY_INIT_DC; + // start the rewriting manager + pManRwt = Rwt_ManStart( 0 ); + p->pData = pManRwt; + if ( pManRwt == NULL ) + return 0; + // create fanouts + if ( p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // resynthesize each node once + nNodes = Ivy_ManObjIdMax(p); + Ivy_ManForEachNode( p, pNode, i ) + { + assert( !Ivy_ObjIsBuf(pNode) ); + assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ); + assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ); + // fix the fanin buffer problem +// Ivy_NodeFixBufferFanins( p, pNode ); +// if ( Ivy_ObjIsBuf(pNode) ) +// continue; + // stop if all nodes have been tried once + if ( i > nNodes ) + break; + // for each cut, try to resynthesize it + nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost ); + if ( nGain > 0 || nGain == 0 && fUseZeroCost ) + { + Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt); + int fCompl = Rwt_ManReadCompl(pManRwt); + // complement the FF if needed +clk = clock(); + if ( fCompl ) Dec_GraphComplement( pGraph ); + Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain ); + if ( fCompl ) Dec_GraphComplement( pGraph ); +Rwt_ManAddTimeUpdate( pManRwt, clock() - clk ); + } + } +Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart ); + // print stats + if ( fVerbose ) + Rwt_ManPrintStats( pManRwt ); + // delete the managers + Rwt_ManStop( pManRwt ); + p->pData = NULL; + // fix the levels + Ivy_ManResetLevels( p ); +// if ( Ivy_ManCheckFanoutNums(p) ) +// printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + // check + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs rewriting for one node.] + + Description [This procedure considers all the cuts computed for the node + and tries to rewrite each of them using the "forest" of different AIG + structures precomputed and stored in the RWR manager. + Determines the best rewriting and computes the gain in the number of AIG + nodes in the final network. In the end, p->vFanins contains information + about the best cut that can be used for rewriting, while p->pGraph gives + the decomposition dag (represented using decomposition graph data structure). + Returns gain in the number of nodes or -1 if node cannot be rewritten.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ) +{ + int fVeryVerbose = 0; + Dec_Graph_t * pGraph; + Ivy_Store_t * pStore; + Ivy_Cut_t * pCut; + Ivy_Obj_t * pFanin;//, * pFanout; + Vec_Ptr_t * vFanout; + unsigned uPhase, uTruthBest, uTruth; + char * pPerm; + int nNodesSaved, nNodesSaveCur; + int i, c, GainCur, GainBest = -1; + int clk, clk2; + + p->nNodesConsidered++; + // get the node's cuts +clk = clock(); + pStore = Ivy_CutComputeForNode( pMan, pNode, 5 ); +p->timeCut += clock() - clk; + + // go through the cuts +clk = clock(); + vFanout = Vec_PtrAlloc( 100 ); + for ( c = 1; c < pStore->nCuts; c++ ) + { + pCut = pStore->pCuts + c; + // consider only 4-input cuts + if ( pCut->nSize != 4 ) + continue; + // skip the cuts with buffers + for ( i = 0; i < (int)pCut->nSize; i++ ) + if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) ) + break; + if ( i != pCut->nSize ) + { + p->nCutsBad++; + continue; + } + p->nCutsGood++; + // get the fanin permutation +clk2 = clock(); + uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize ); // truth table +p->timeTruth += clock() - clk2; + pPerm = p->pPerms4[ p->pPerms[uTruth] ]; + uPhase = p->pPhases[uTruth]; + // collect fanins with the corresponding permutation/phase + Vec_PtrClear( p->vFaninsCur ); + Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); + for ( i = 0; i < (int)pCut->nSize; i++ ) + { + pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[pPerm[i]] ) ); + assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) ); + pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); + Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); + } +clk2 = clock(); + // mark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // label MFFC with current ID + Ivy_ManIncrementTravId( pMan ); + nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); + // label fanouts with the current ID +// Ivy_ObjForEachFanout( pMan, pNode, vFanout, pFanout, i ) +// Ivy_ObjSetTravIdCurrent( pMan, pFanout ); + // unmark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +p->timeMffc += clock() - clk2; +/* +if ( pNode->Id == 8648 ) +{ + int i; + printf( "Trying cut : {" ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); +// printf( " }\n" ); + printf( " } " ); + Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" ); +} +*/ + + // evaluate the cut +clk2 = clock(); + pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth ); +p->timeEval += clock() - clk2; + + + // check if the cut is better than the current best one + if ( pGraph != NULL && GainBest < GainCur ) + { + // save this form + nNodesSaveCur = nNodesSaved; + GainBest = GainCur; + p->pGraph = pGraph; + p->pCut = pCut; + p->pPerm = pPerm; + p->fCompl = ((uPhase & (1<<4)) > 0); + uTruthBest = uTruth; + // collect fanins in the + Vec_PtrClear( p->vFanins ); + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Vec_PtrPush( p->vFanins, pFanin ); + } + } + Vec_PtrFree( vFanout ); +p->timeRes += clock() - clk; + + if ( GainBest == -1 ) + return -1; +/* + { + Ivy_Cut_t * pCut = p->pCut; + printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + printf( " }\n" ); + } +*/ + + // copy the leaves + Ivy_GraphPrepare( p->pGraph, p->pCut, p->vFanins, p->pPerm ); + + p->nScores[p->pMap[uTruthBest]]++; + p->nNodesGained += GainBest; + if ( fUseZeroCost || GainBest > 0 ) + p->nNodesRewritten++; + +/* + if ( GainBest > 0 ) + { + Ivy_Cut_t * pCut = p->pCut; + printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %5d(%2d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + printf( " }\n" ); + } +*/ + + // report the progress + if ( fVeryVerbose && GainBest > 0 ) + { + printf( "Node %6d : ", Ivy_ObjId(pNode) ); + printf( "Fanins = %d. ", p->vFanins->nSize ); + printf( "Save = %d. ", nNodesSaveCur ); + printf( "Add = %d. ", nNodesSaveCur-GainBest ); + printf( "GAIN = %d. ", GainBest ); + printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); + printf( "Class = %d. ", p->pMap[uTruthBest] ); + printf( "\n" ); + } + return GainBest; +} + + +/**Function************************************************************* + + Synopsis [Evaluates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ) +{ + Vec_Ptr_t * vSubgraphs; + Dec_Graph_t * pGraphBest, * pGraphCur; + Rwt_Node_t * pNode; + int nNodesAdded, GainBest, i; + // find the matching class of subgraphs + vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); + p->nSubgraphs += vSubgraphs->nSize; + // determine the best subgraph + GainBest = -1; + Vec_PtrForEachEntry( vSubgraphs, pNode, i ) + { + // get the current graph + pGraphCur = (Dec_Graph_t *)pNode->pNext; + +// if ( pRoot->Id == 8648 ) +// Dec_GraphPrint( stdout, pGraphCur, NULL, NULL ); + // copy the leaves +// Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) +// Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; + Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm ); + + // detect how many unlabeled nodes will be reused + nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved ); + if ( nNodesAdded == -1 ) + continue; + assert( nNodesSaved >= nNodesAdded ); + // count the gain at this node + if ( GainBest < nNodesSaved - nNodesAdded ) + { + GainBest = nNodesSaved - nNodesAdded; + pGraphBest = pGraphCur; + } + } + if ( GainBest == -1 ) + return NULL; + *pGainBest = GainBest; + return pGraphBest; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + int i; + assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize ); + assert( Vec_PtrSize(vFanins) == pCut->nSize ); + // label the leaves with latch numbers + Dec_GraphForEachLeaf( pGraph, pNode, i ) + { + pNode->pFunc = Vec_PtrEntry( vFanins, i ); + pNode->nLat2 = Ivy_LeafLat( pCut->pArray[pPerm[i]] ); + } + // propagate latches through the nodes + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // distribute the latches + pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 ); + pNode->nLat0 = pNode0->nLat2 - pNode->nLat2; + pNode->nLat1 = pNode1->nLat2 - pNode->nLat2; + } +} + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, k, Counter, fCompl; + // check for constant function or a literal + if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) + return 0; + // compute the AIG size after adding the internal nodes + Counter = 0; + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // get the AIG nodes corresponding to the children + pAnd0 = pNode0->pFunc; + pAnd1 = pNode1->pFunc; + // skip the latches + for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ ) + { + fCompl = Ivy_IsComplement(pAnd0); + pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) ); + if ( pAnd0 ) + pAnd0 = Ivy_NotCond( pAnd0, fCompl ); + } + for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ ) + { + fCompl = Ivy_IsComplement(pAnd1); + pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) ); + if ( pAnd1 ) + pAnd1 = Ivy_NotCond( pAnd1, fCompl ); + } + // get the new node + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); + assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) ); + if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) ) + pAnd = Ivy_And( p, pAnd0, pAnd1 ); + else + pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); + // return -1 if the node is the same as the original root + if ( Ivy_Regular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + pNode->pFunc = pAnd; + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ) +{ + Ivy_Obj_t * pAnd0, * pAnd1; + Dec_Node_t * pNode; + int i, k; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + { + // get the variable node + pNode = Dec_GraphVar(pGraph); + // add the remaining latches + for ( k = 0; k < (int)pNode->nLat2; k++ ) + pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC ); + return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); + } + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + // add the latches + for ( k = 0; k < (int)pNode->nLat0; k++ ) + pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC ); + for ( k = 0; k < (int)pNode->nLat1; k++ ) + pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC ); + // create the node + pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); + } + // add the remaining latches + for ( k = 0; k < (int)pNode->nLat2; k++ ) + pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC ); + // complement the result if necessary + return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ) +{ + Ivy_Obj_t * pRootNew; + int nNodesNew, nNodesOld; + nNodesOld = Ivy_ManNodeNum(p); + // create the new structure of nodes + pRootNew = Ivy_GraphToNetworkSeq( p, pGraph ); + Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 ); + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); + // propagate the buffer + Ivy_ManPropagateBuffers( p, 0 ); +} + + + + + + + + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums ) +{ + static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth0, uTruth1; + Ivy_Obj_t * pObj; + int i; + for ( i = 0; i < nNums; i++ ) + if ( Leaf == pNums[i] ) + return uMasks[i]; + pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); + if ( Ivy_ObjIsLatch(pObj) ) + { + assert( !Ivy_ObjFaninC0(pObj) ); + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 ); + return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + } + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) ); + uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + if ( Ivy_ObjFaninC0(pObj) ) + uTruth0 = ~uTruth0; + if ( Ivy_ObjIsBuf(pObj) ) + return uTruth0; + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) ); + uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + if ( Ivy_ObjFaninC1(pObj) ) + uTruth1 = ~uTruth1; + return uTruth0 & uTruth1; +} + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + assert( Ivy_ObjIsNode(pObj) ); + assert( nNums < 6 ); + return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums ); +} + + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) +{ + int i; + if ( pCut->nSize < pCut->nSizeMax ) + return 1; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 >= 0 ) + { + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + IdNew0 = -1; + } + } + if ( IdNew1 >= 0 ) + { + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + IdNew1 = -1; + } + } + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_CutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 >= 0 ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + if ( IdNew1 >= 0 ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); + for ( i = 1; i < pCutNew->nSize; i++ ) + assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_CutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + if ( IdNew1 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); +// for ( i = 1; i < pCutNew->nSize; i++ ) +// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Find the hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) +{ + int i; + pCut->uHash = 0; + for ( i = 0; i < pCut->nSize; i++ ) + pCut->uHash |= (1 << (pCut->pArray[i] % 31)); + return pCut->uHash; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + pCutNew->pArray[ k++ ] = IdNew0; + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + pCutNew->pArray[ k++ ] = IdNew1; + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + } + if ( IdNew0 < 0x7FFFFFFF ) + pCutNew->pArray[ k++ ] = IdNew0; + if ( IdNew1 < 0x7FFFFFFF ) + pCutNew->pArray[ k++ ] = IdNew1; + pCutNew->nSize = k; + assert( pCutNew->nSize <= pCut->nSizeMax ); + Ivy_NodeCutHash( pCutNew ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < pDom->nSize; i++ ) + { + assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] ); + for ( k = 0; k < pCut->nSize; k++ ) + if ( pDom->pArray[i] == pCut->pArray[k] ) + break; + if ( k == pCut->nSize ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize == pCutNew->nSize ) + { + if ( pCut->uHash == pCutNew->uHash ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + continue; + } + if ( pCut->nSize < pCutNew->nSize ) + { + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) + return 1; + continue; + } + // check potential containment of other cut + + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) + { + // remove the current cut + pCut->nSize = 0; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compresses the cut representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutCompactAll( Ivy_Store_t * pCutStore ) +{ + Ivy_Cut_t * pCut; + int i, k; + pCutStore->nCutsM = 0; + for ( i = k = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize < pCut->nSizeMax ) + pCutStore->nCutsM++; + pCutStore->pCuts[k++] = *pCut; + } + pCutStore->nCuts = k; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutPrintForNode( Ivy_Cut_t * pCut ) +{ + int i; + assert( pCut->nSize > 0 ); + printf( "%d : {", pCut->nSize ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d", pCut->pArray[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore ) +{ + int i; + printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); + for ( i = 0; i < pCutStore->nCuts; i++ ) + Ivy_CutPrintForNode( pCutStore->pCuts + i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin ) +{ + int nLats, iLeaf; + assert( !Ivy_IsComplement(pFanin) ); + if ( !Ivy_ObjIsLatch(pFanin) ) + return Ivy_LeafCreate( pFanin->Id, 0 ); + iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin)); + nLats = Ivy_LeafLat(iLeaf); + assert( nLats < IVY_LEAF_MASK ); + return 1 + iLeaf; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; + Ivy_Man_t * pMan = p; + Ivy_Obj_t * pLeaf; + int i, k, Temp, nLats, iLeaf0, iLeaf1; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // start the trivial cut + pCutNew->uHash = 0; + pCutNew->nSize = 1; + pCutNew->nSizeMax = nLeaves; + pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 ); + pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] ); + // add the trivial cut + pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew; + assert( pCutStore->nCuts == 1 ); + + // explore the cuts + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + // expand this cut + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + for ( k = 0; k < pCut->nSize; k++ ) + { + pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) ); + if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) ) + continue; + assert( Ivy_ObjIsNode(pLeaf) ); + nLats = Ivy_LeafLat(pCut->pArray[k]); + + // get the fanins fanins + iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) ); + iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) ); + assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK ); + iLeaf0 = nLats + iLeaf0; + iLeaf1 = nLats + iLeaf1; + if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) ) + continue; + // the given cut exist + if ( iLeaf0 > iLeaf1 ) + Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp; + // create the new cut + if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) ) + continue; + // add the cut + Ivy_CutFindOrAddFilter( pCutStore, pCutNew ); + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + pCutStore->fSatur = 1; + else + pCutStore->fSatur = 0; +// printf( "%d ", pCutStore->nCuts ); + Ivy_CutCompactAll( pCutStore ); +// printf( "%d \n", pCutStore->nCuts ); +// Ivy_CutPrintForNodes( pCutStore ); + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ) +{ + Ivy_Store_t * pStore; + Ivy_Obj_t * pObj; + int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver; + int clk = clock(); + if ( nInputs > IVY_CUT_INPUT ) + { + printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT ); + return; + } + nNodeTotal = nNodeOver = 0; + nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pStore = Ivy_CutComputeForNode( p, pObj, nInputs ); + nCutsTotal += pStore->nCuts; + nCutsTotalM += pStore->nCutsM; + nNodeOver += pStore->fSatur; + nNodeTotal++; + } + printf( "All = %6d. Minus = %6d. Triv = %6d. Node = %6d. Satur = %6d. ", + nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + PRT( "Time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyShow.c b/src/aig/ivy/ivyShow.c new file mode 100644 index 00000000..cd726e43 --- /dev/null +++ b/src/aig/ivy/ivyShow.c @@ -0,0 +1,338 @@ +/**CFile**************************************************************** + + FileName [ivyShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Visualization of HAIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) +{ + extern void Abc_ShowFile( char * FileNameDot ); + static Counter = 0; + char FileNameDot[200]; + FILE * pFile; + // create the file name +// Ivy_ShowGetFileName( pMan->pName, FileNameDot ); + sprintf( FileNameDot, "temp%02d.dot", Counter++ ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + // generate the file + Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); + // visualize the file + Abc_ShowFile( FileNameDot ); +} + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) +{ + FILE * pFile; + Ivy_Obj_t * pNode, * pTemp, * pPrev; + int LevelMax, Level, i; + + if ( Ivy_ManNodeNum(pMan) > 200 ) + { + fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); + return; + } + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // mark the nodes + if ( vBold ) + Vec_PtrForEachEntry( vBold, pNode, i ) + pNode->fMarkB = 1; + + // compute levels + LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig ); + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != 0 ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the COs + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the CO nodes + Ivy_ManForEachCo( pMan, pNode, i ) + { + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate nodes of each rank + for ( Level = LevelMax - 1; Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Ivy_ManForEachObj( pMan, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + else + fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = ellipse" ); + if ( vBold && pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the CI nodes + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", 0 ); + // generate constant node + if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 ) + { + pNode = Ivy_ManConst1(pMan); + // check if the costant node is present + fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + // generate the CI nodes + Ivy_ManForEachCi( pMan, pNode, i ) + { + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Ivy_ManForEachCo( pMan, pNode, i ) + fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + + // generate edges + Ivy_ManForEachObj( pMan, pNode, i ) + { + if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d%s", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" ); +// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + if ( !Ivy_ObjIsNode(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" ); +// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + // generate the edges between the equivalent nodes + if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) + { + pPrev = pNode; + for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pTemp->Id ); + fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + pPrev = pTemp; + } + // connect the last node with the first + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark nodes + if ( vBold ) + Vec_PtrForEachEntry( vBold, pNode, i ) + pNode->fMarkB = 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyTable.c b/src/aig/ivy/ivyTable.c new file mode 100644 index 00000000..2ac0ae49 --- /dev/null +++ b/src/aig/ivy/ivyTable.c @@ -0,0 +1,301 @@ +/**CFile**************************************************************** + + FileName [ivyTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Structural hashing table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006. ] + + Revision [$Id: ivyTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing the node +static unsigned Ivy_Hash( Ivy_Obj_t * pObj, int TableSize ) +{ + unsigned Key = Ivy_ObjIsExor(pObj) * 1699; + Key ^= Ivy_ObjFaninId0(pObj) * 7937; + Key ^= Ivy_ObjFaninId1(pObj) * 2971; + Key ^= Ivy_ObjFaninC0(pObj) * 911; + Key ^= Ivy_ObjFaninC1(pObj) * 353; + Key ^= Ivy_ObjInit(pObj) * 911; + return Key % TableSize; +} + +// returns the place where this node is stored (or should be stored) +static int * Ivy_TableFind( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + int i; + assert( Ivy_ObjIsHash(pObj) ); + for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) + if ( p->pTable[i] == pObj->Id ) + break; + return p->pTable + i; +} + +static void Ivy_TableResize( Ivy_Man_t * p ); +static unsigned int Cudd_PrimeAig( unsigned int p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEntry; + int i; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return NULL; + assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 ); + assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) ); + if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) ) + return NULL; + for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) + { + pEntry = Ivy_ManObj( p, p->pTable[i] ); + if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) && + Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) && + Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) && + Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) ) + return pEntry; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds the node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + int * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + if ( (pObj->Id & 63) == 0 ) + { + if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) ) + Ivy_TableResize( p ); + } + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == 0 ); + *pPlace = pObj->Id; +} + +/**Function************************************************************* + + Synopsis [Deletes the node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEntry; + int i, * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == pObj->Id ); // node should be in the table + *pPlace = 0; + // rehash the adjacent entries + i = pPlace - p->pTable; + for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) + { + pEntry = Ivy_ManObj( p, p->pTable[i] ); + p->pTable[i] = 0; + Ivy_TableInsert( p, pEntry ); + } +} + +/**Function************************************************************* + + Synopsis [Updates the table to point to the new node.] + + Description [If the old node (pObj) is in the table, updates the table + to point to an object with different ID (ObjIdNew). The table should + not contain an object with ObjIdNew (this is currently not checked).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ) +{ + int * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == pObj->Id ); // node should be in the table + *pPlace = ObjIdNew; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TableCountEntries( Ivy_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + Counter += (p->pTable[i] != 0); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [Typically this procedure should not be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableResize( Ivy_Man_t * p ) +{ + int * pTableOld, * pPlace; + int nTableSizeOld, Counter, nEntries, e, clk; +clk = clock(); + // save the old table + pTableOld = p->pTable; + nTableSizeOld = p->nTableSize; + // get the new table + p->nTableSize = Cudd_PrimeAig( 5 * Ivy_ManHashObjNum(p) ); + p->pTable = ALLOC( int, p->nTableSize ); + memset( p->pTable, 0, sizeof(int) * p->nTableSize ); + // rehash the entries from the old table + Counter = 0; + for ( e = 0; e < nTableSizeOld; e++ ) + { + if ( pTableOld[e] == 0 ) + continue; + Counter++; + // get the place where this entry goes in the table table + pPlace = Ivy_TableFind( p, Ivy_ManObj(p, pTableOld[e]) ); + assert( *pPlace == 0 ); // should not be in the table + *pPlace = pTableOld[e]; + } + nEntries = Ivy_ManHashObjNum(p); +// assert( Counter == nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( pTableOld ); +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Ivy_TableProfile( Ivy_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + { + if ( p->pTable[i] ) + Counter++; + else if ( Counter ) + { + printf( "%d ", Counter ); + Counter = 0; + } + } +} + +/**Function******************************************************************** + + Synopsis [Returns the next prime >= p.] + + Description [Copied from CUDD, for stand-aloneness.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +unsigned int Cudd_PrimeAig( unsigned int p) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivyUtil.c b/src/aig/ivy/ivyUtil.c new file mode 100644 index 00000000..0e44c216 --- /dev/null +++ b/src/aig/ivy/ivyUtil.c @@ -0,0 +1,738 @@ +/**CFile**************************************************************** + + FileName [ivyUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Various procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManIncrementTravId( Ivy_Man_t * p ) +{ + if ( p->nTravIds >= (1<<30)-1 - 1000 ) + Ivy_ManCleanTravId( p ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Sets the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCleanTravId( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + p->nTravIds = 1; + Ivy_ManForEachObj( p, pObj, i ) + pObj->TravId = 0; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes ) +{ + if ( pNode->fMarkA ) + return; + pNode->fMarkA = 1; + assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) ); + Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes ); + Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes ); + Vec_IntPush( vNodes, pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [Does not modify the array of leaves. Uses array vTruth to store + temporary truth tables. The returned pointer should be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) +{ + int i, Leaf; + // collect and mark the leaves + Vec_IntClear( vNodes ); + Vec_IntForEachEntry( vLeaves, Leaf, i ) + { + Vec_IntPush( vNodes, Leaf ); + Ivy_ManObj(p, Leaf)->fMarkA = 1; + } + // collect and mark the nodes + Ivy_ManCollectCut_rec( p, pRoot, vNodes ); + // clean the nodes + Vec_IntForEachEntry( vNodes, Leaf, i ) + Ivy_ManObj(p, Leaf)->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth ) +{ + return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int i; + pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth ); + pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth ); + pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth ); + if ( Ivy_ObjIsExor(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [Does not modify the array of leaves. Uses array vTruth to store + temporary truth tables. The returned pointer should be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ) +{ + static unsigned uTruths[8][8] = { // elementary truth tables + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + int i, Leaf; + // collect the cut + Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes ); + // set the node numbers + Vec_IntForEachEntry( vNodes, Leaf, i ) + Ivy_ManObj(p, Leaf)->TravId = i; + // alloc enough memory + Vec_IntClear( vTruth ); + Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) ); + // set the elementary truth tables + Vec_IntForEachEntry( vLeaves, Leaf, i ) + memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) ); + // compute truths for other nodes + Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) ) + Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 ); + return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth ); +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ) +{ + Vec_Int_t * vLatches; + Ivy_Obj_t * pObj; + int i; + vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); + Ivy_ManForEachLatch( p, pObj, i ) + Vec_IntPush( vLatches, pObj->Id ); + return vLatches; +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, LevelMax = 0; + Ivy_ManForEachPo( p, pObj, i ) + LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj ) +{ + if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) + return pObj->Level; + if ( Ivy_ObjIsBuf(pObj) ) + return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); + Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) ); + return pObj->Level = Ivy_ObjLevelNew( pObj ); +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManResetLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + Ivy_ManForEachObj( p, pObj, i ) + pObj->Level = 0; + Ivy_ManForEachCo( p, pObj, i ) + Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel ) +{ + Ivy_Obj_t * pNode0, * pNode1; + int Counter; + // label visited nodes + if ( fLabel ) + Ivy_ObjSetTravIdCurrent( p, pNode ); + // skip the CI + if ( Ivy_ObjIsPi(pNode) ) + return 0; + assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) ); + // process the internal node + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + Counter = Ivy_ObjIsNode(pNode); + if ( fReference ) + { + if ( pNode0->nRefs++ == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); + if ( pNode1 && pNode1->nRefs++ == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); + } + else + { + assert( pNode0->nRefs > 0 ); + assert( pNode1 == NULL || pNode1->nRefs > 0 ); + if ( --pNode0->nRefs == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); + if ( pNode1 && --pNode1->nRefs == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Labels MFFC with the current label.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( !Ivy_IsComplement( pNode ) ); + assert( Ivy_ObjIsNode( pNode ) ); + nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference + nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Recursively updates fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + Vec_Ptr_t * vFanouts; + int i, LevelNew; + assert( p->fFanout ); + assert( Ivy_ObjIsNode(pObj) ); + vFanouts = Vec_PtrAlloc( 10 ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + if ( Ivy_ObjIsCo(pFanout) ) + { +// assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax ); + continue; + } + LevelNew = Ivy_ObjLevelNew( pFanout ); + if ( (int)pFanout->Level == LevelNew ) + continue; + pFanout->Level = LevelNew; + Ivy_ObjUpdateLevel_rec( p, pFanout ); + } + Vec_PtrFree( vFanouts ); +} + +/**Function************************************************************* + + Synopsis [Compute the new required level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + Vec_Ptr_t * vFanouts; + int i, Required, LevelNew = 1000000; + assert( p->fFanout && p->vRequired ); + vFanouts = Vec_PtrAlloc( 10 ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + Required = Vec_IntEntry(p->vRequired, pFanout->Id); + LevelNew = IVY_MIN( LevelNew, Required ); + } + Vec_PtrFree( vFanouts ); + return LevelNew - 1; +} + +/**Function************************************************************* + + Synopsis [Recursively updates fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ) +{ + Ivy_Obj_t * pFanin; + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + return; + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + // process the first fanin + pFanin = Ivy_ObjFanin0(pObj); + if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) + { + Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); + Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); + } + if ( Ivy_ObjIsBuf(pObj) ) + return; + // process the second fanin + pFanin = Ivy_ObjFanin1(pObj); + if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) + { + Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); + Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Ivy_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Ivy_ObjIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || + (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) || + (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || + (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1))); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE ) +{ + Ivy_Obj_t * pNode0, * pNode1; + assert( !Ivy_IsComplement(pNode) ); + assert( Ivy_ObjIsMuxType(pNode) ); + // get children + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + // find the control variable +// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) + if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Ivy_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + return Ivy_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + return Ivy_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) + else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Ivy_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + return Ivy_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + return Ivy_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) + else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Ivy_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + return Ivy_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + return Ivy_ObjChild1(pNode0);//pNode1->p2; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) + else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Ivy_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + return Ivy_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + return Ivy_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the real fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanin; + if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) ) + return pObj; + pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) ); + return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ) +{ + Ivy_Obj_t * pTemp; + int fShowFanouts = 0; + assert( !Ivy_IsComplement(pObj) ); + printf( "Node %5d : ", Ivy_ObjId(pObj) ); + if ( Ivy_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Ivy_ObjIsPi(pObj) ) + printf( "PI" ); + else if ( Ivy_ObjIsPo(pObj) ) + printf( "PO" ); + else if ( Ivy_ObjIsLatch(pObj) ) + printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + else if ( Ivy_ObjIsBuf(pObj) ) + printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + else + printf( "AND( %5d%s, %5d%s )", + Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "), + Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Ivy_ObjRefs(pObj) ); + if ( fShowFanouts ) + { + Vec_Ptr_t * vFanouts; + Ivy_Obj_t * pFanout; + int i; + vFanouts = Vec_PtrAlloc( 10 ); + printf( "\nFanouts:\n" ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + printf( " " ); + printf( "Node %5d : ", Ivy_ObjId(pFanout) ); + if ( Ivy_ObjIsPo(pFanout) ) + printf( "PO" ); + else if ( Ivy_ObjIsLatch(pFanout) ) + printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); + else if ( Ivy_ObjIsBuf(pFanout) ) + printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); + else + printf( "AND( %5d%s, %5d%s )", + Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "), + Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") ); + printf( "\n" ); + } + Vec_PtrFree( vFanouts ); + return; + } + if ( !fHaig ) + { + if ( pObj->pEquiv == NULL ) + printf( " HAIG node not given" ); + else + printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") ); + return; + } + if ( pObj->pEquiv == NULL ) + return; + // there are choices + if ( Ivy_ObjRefs(pObj) > 0 ) + { + // print equivalence class + printf( " { %5d ", pObj->Id ); + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") ); + printf( " }" ); + return; + } + // this is a secondary node + for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) ); + assert( Ivy_ObjRefs(pTemp) > 0 ); + printf( " class of %d", pTemp->Id ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ) +{ + Vec_Int_t * vNodes; + Ivy_Obj_t * pObj; + int i; + printf( "PIs: " ); + Ivy_ManForEachPi( p, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + printf( "POs: " ); + Ivy_ManForEachPo( p, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + printf( "Latches: " ); + Ivy_ManForEachLatch( p, pObj, i ) + printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + printf( "\n" ); + vNodes = Ivy_ManDfsSeq( p, NULL ); + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" ); + printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/ivy_.c b/src/aig/ivy/ivy_.c new file mode 100644 index 00000000..65689689 --- /dev/null +++ b/src/aig/ivy/ivy_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [ivy_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ivy/module.make b/src/aig/ivy/module.make new file mode 100644 index 00000000..c1f7d1b8 --- /dev/null +++ b/src/aig/ivy/module.make @@ -0,0 +1,23 @@ +SRC += src/aig/ivy/ivyBalance.c \ + src/aig/ivy/ivyCanon.c \ + src/aig/ivy/ivyCheck.c \ + src/aig/ivy/ivyCut.c \ + src/aig/ivy/ivyCutTrav.c \ + src/aig/ivy/ivyDfs.c \ + src/aig/ivy/ivyDsd.c \ + src/aig/ivy/ivyFanout.c \ + src/aig/ivy/ivyFastMap.c \ + src/aig/ivy/ivyFraig.c \ + src/aig/ivy/ivyHaig.c \ + src/aig/ivy/ivyIsop.c \ + src/aig/ivy/ivyMan.c \ + src/aig/ivy/ivyMem.c \ + src/aig/ivy/ivyMulti.c \ + src/aig/ivy/ivyObj.c \ + src/aig/ivy/ivyOper.c \ + src/aig/ivy/ivyResyn.c \ + src/aig/ivy/ivyRwr.c \ + src/aig/ivy/ivySeq.c \ + src/aig/ivy/ivyShow.c \ + src/aig/ivy/ivyTable.c \ + src/aig/ivy/ivyUtil.c diff --git a/src/aig/mem/mem.c b/src/aig/mem/mem.c new file mode 100644 index 00000000..15199755 --- /dev/null +++ b/src/aig/mem/mem.c @@ -0,0 +1,588 @@ +/**CFile**************************************************************** + + FileName [esopMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cover manipulation package.] + + Synopsis [Memory managers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: esopMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include "mem.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Mem_Fixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Mem_Flex_t_ +{ + // information about individual entries + int nEntriesUsed; // the number of entries allocated + char * pCurrent; // the current pointer to free memory + char * pEnd; // the first entry outside the free memory + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Mem_Step_t_ +{ + int nMems; // the number of fixed memory managers employed + Mem_Fixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Mem_Fixed_t ** pMap; // maps the number of bytes into its memory manager +}; + +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates memory pieces of fixed size.] + + Description [The size of the chunk is computed as the minimum of + 1024 entries and 64K. Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mem_Fixed_t * Mem_FixedStart( int nEntrySize ) +{ + Mem_Fixed_t * p; + + p = ALLOC( Mem_Fixed_t, 1 ); + memset( p, 0, sizeof(Mem_Fixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + if ( nEntrySize * (1 << 10) < (1<<16) ) + p->nChunkSize = (1 << 10); + else + p->nChunkSize = (1<<16) / nEntrySize; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mem_FixedEntryFetch( Mem_Fixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FixedRestart( Mem_Fixed_t * p ) +{ + int i; + char * pTemp; + + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mem_FixedReadMemUsage( Mem_Fixed_t * p ) +{ + return p->nMemoryAlloc; +} + + + +/**Function************************************************************* + + Synopsis [Allocates entries of flexible size.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mem_Flex_t * Mem_FlexStart() +{ + Mem_Flex_t * p; + + p = ALLOC( Mem_Flex_t, 1 ); + memset( p, 0, sizeof(Mem_Flex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 14); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", + p->nChunkSize, p->nChunks ); + printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", + p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ) +{ + char * pTemp; + // check if there are still free entries + if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) + { // need to allocate more entries + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + if ( nBytes > p->nChunkSize ) + { + // resize the chunk size if more memory is requested than it can give + // (ideally, this should never happen) + p->nChunkSize = 2 * nBytes; + } + p->pCurrent = ALLOC( char, p->nChunkSize ); + p->pEnd = p->pCurrent + p->nChunkSize; + p->nMemoryAlloc += p->nChunkSize; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pCurrent; + } + assert( p->pCurrent + nBytes <= p->pEnd ); + // increment the counter of used entries + p->nEntriesUsed++; + // keep track of the memory used + p->nMemoryUsed += nBytes; + // return the next entry + pTemp = p->pCurrent; + p->pCurrent += nBytes; + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FlexRestart( Mem_Flex_t * p ) +{ + int i; + if ( p->nChunks == 0 ) + return; + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + p->nMemoryAlloc = p->nChunkSize; + // transform these entries into a linked list + p->pCurrent = p->pChunks[0]; + p->pEnd = p->pCurrent + p->nChunkSize; + p->nEntriesUsed = 0; + p->nMemoryUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mem_FlexReadMemUsage( Mem_Flex_t * p ) +{ + return p->nMemoryUsed; +} + + + + + +/**Function************************************************************* + + Synopsis [Starts the hierarchical memory manager.] + + Description [This manager can allocate entries of any size. + Iternally they are mapped into the entries with the number of bytes + equal to the power of 2. The smallest entry size is 8 bytes. The + next one is 16 bytes etc. So, if the user requests 6 bytes, he gets + 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. + The input parameters "nSteps" says how many fixed memory managers + are employed internally. Calling this procedure with nSteps equal + to 10 results in 10 hierarchically arranged internal memory managers, + which can allocate up to 4096 (1Kb) entries. Requests for larger + entries are handed over to malloc() and then free()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mem_Step_t * Mem_StepStart( int nSteps ) +{ + Mem_Step_t * p; + int i, k; + p = ALLOC( Mem_Step_t, 1 ); + memset( p, 0, sizeof(Mem_Step_t) ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ALLOC( Mem_Fixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Mem_FixedStart( (8<nMapSize = (4<nMems); + p->pMap = ALLOC( Mem_Fixed_t *, p->nMapSize+1 ); + p->pMap[0] = NULL; + for ( k = 1; k <= 4; k++ ) + p->pMap[k] = p->pMems[0]; + for ( i = 0; i < p->nMems; i++ ) + for ( k = (4<pMap[k] = p->pMems[i]; +//for ( i = 1; i < 100; i ++ ) +//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_StepStop( Mem_Step_t * p, int fVerbose ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Mem_FixedStop( p->pMems[i], fVerbose ); +// if ( p->pLargeChunks ) +// { +// for ( i = 0; i < p->nLargeChunks; i++ ) +// free( p->pLargeChunks[i] ); +// free( p->pLargeChunks ); +// } + free( p->pMems ); + free( p->pMap ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; + if ( nBytes > p->nMapSize ) + { +// printf( "Allocating %d bytes.\n", nBytes ); +/* + if ( p->nLargeChunks == p->nLargeChunksAlloc ) + { + if ( p->nLargeChunksAlloc == 0 ) + p->nLargeChunksAlloc = 5; + p->nLargeChunksAlloc *= 2; + p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); + } + p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes ); + return p->pLargeChunks[ p->nLargeChunks - 1 ]; +*/ + return ALLOC( char, nBytes ); + } + return Mem_FixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; + if ( nBytes > p->nMapSize ) + { + free( pEntry ); + return; + } + Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mem_StepReadMemUsage( Mem_Step_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/aig/mem/mem.h b/src/aig/mem/mem.h new file mode 100644 index 00000000..611c968d --- /dev/null +++ b/src/aig/mem/mem.h @@ -0,0 +1,71 @@ +/**CFile**************************************************************** + + FileName [mem.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Memory management.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MEM_H__ +#define __MEM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Mem_Fixed_t_ Mem_Fixed_t; +typedef struct Mem_Flex_t_ Mem_Flex_t; +typedef struct Mem_Step_t_ Mem_Step_t; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mem.c ===========================================================*/ +// fixed-size-block memory manager +extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize ); +extern void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ); +extern char * Mem_FixedEntryFetch( Mem_Fixed_t * p ); +extern void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ); +extern void Mem_FixedRestart( Mem_Fixed_t * p ); +extern int Mem_FixedReadMemUsage( Mem_Fixed_t * p ); +// flexible-size-block memory manager +extern Mem_Flex_t * Mem_FlexStart(); +extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ); +extern char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ); +extern void Mem_FlexRestart( Mem_Flex_t * p ); +extern int Mem_FlexReadMemUsage( Mem_Flex_t * p ); +// hierarchical memory manager +extern Mem_Step_t * Mem_StepStart( int nSteps ); +extern void Mem_StepStop( Mem_Step_t * p, int fVerbose ); +extern char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ); +extern void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ); +extern int Mem_StepReadMemUsage( Mem_Step_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/mem/module.make b/src/aig/mem/module.make new file mode 100644 index 00000000..ae6fcbe4 --- /dev/null +++ b/src/aig/mem/module.make @@ -0,0 +1 @@ +SRC += src/aig/mem/mem.c diff --git a/src/aig/rwt/module.make b/src/aig/rwt/module.make new file mode 100644 index 00000000..2852f2ba --- /dev/null +++ b/src/aig/rwt/module.make @@ -0,0 +1,3 @@ +SRC += src/hop/rwt/rwtDec.c \ + src/hop/rwt/rwtMan.c \ + src/hop/rwt/rwtUtil.c diff --git a/src/aig/rwt/rwt.h b/src/aig/rwt/rwt.h new file mode 100644 index 00000000..42a57ad6 --- /dev/null +++ b/src/aig/rwt/rwt.h @@ -0,0 +1,155 @@ +/**CFile**************************************************************** + + FileName [rwt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __RWT_H__ +#define __RWT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "mem.h" +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +#define RWT_LIMIT 1048576/4 // ((1 << 20) +#define RWT_MIN(a,b) (((a) < (b))? (a) : (b)) +#define RWT_MAX(a,b) (((a) > (b))? (a) : (b)) + +typedef struct Rwt_Man_t_ Rwt_Man_t; +typedef struct Rwt_Node_t_ Rwt_Node_t; + +struct Rwt_Man_t_ +{ + // internal lookups + int nFuncs; // number of four var functions + unsigned short * puCanons; // canonical forms + char * pPhases; // canonical phases + char * pPerms; // canonical permutations + unsigned char * pMap; // mapping of functions into class numbers + unsigned short * pMapInv; // mapping of classes into functions + char * pPractical; // practical NPN classes + char ** pPerms4; // four-var permutations + // node space + Vec_Ptr_t * vForest; // all the nodes + Rwt_Node_t ** pTable; // the hash table of nodes by their canonical form + Vec_Vec_t * vClasses; // the nodes of the equivalence classes + Mem_Fixed_t * pMmNode; // memory for nodes and cuts + // statistical variables + int nTravIds; // the counter of traversal IDs + int nConsidered; // the number of nodes considered + int nAdded; // the number of nodes added to lists + int nClasses; // the number of NN classes + // the result of resynthesis + int fCompl; // indicates if the output of FF should be complemented + void * pCut; // the decomposition tree (temporary) + void * pGraph; // the decomposition tree (temporary) + char * pPerm; // permutation used for the best cut + Vec_Ptr_t * vFanins; // the fanins array (temporary) + Vec_Ptr_t * vFaninsCur; // the fanins array (temporary) + Vec_Int_t * vLevNums; // the array of levels (temporary) + Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary) + // node statistics + int nNodesConsidered; + int nNodesRewritten; + int nNodesGained; + int nScores[222]; + int nCutsGood; + int nCutsBad; + int nSubgraphs; + // runtime statistics + int timeStart; + int timeTruth; + int timeCut; + int timeRes; + int timeEval; + int timeMffc; + int timeUpdate; + int timeTotal; +}; + +struct Rwt_Node_t_ // 24 bytes +{ + int Id; // ID + int TravId; // traversal ID + unsigned uTruth : 16; // truth table + unsigned Volume : 8; // volume + unsigned Level : 6; // level + unsigned fUsed : 1; // mark + unsigned fExor : 1; // mark + Rwt_Node_t * p0; // first child + Rwt_Node_t * p1; // second child + Rwt_Node_t * pNext; // next in the table +}; + +// manipulation of complemented attributes +static inline int Rwt_IsComplement( Rwt_Node_t * p ) { return (int)(((unsigned long)p) & 01); } +static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) & ~01); } +static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) ^ 01); } +static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((unsigned long)(p) ^ (c)); } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== rwrDec.c ========================================================*/ +extern void Rwt_ManPreprocess( Rwt_Man_t * p ); +/*=== rwrMan.c ========================================================*/ +extern Rwt_Man_t * Rwt_ManStart( int fPrecompute ); +extern void Rwt_ManStop( Rwt_Man_t * p ); +extern void Rwt_ManPrintStats( Rwt_Man_t * p ); +extern void Rwt_ManPrintStatsFile( Rwt_Man_t * p ); +extern void * Rwt_ManReadDecs( Rwt_Man_t * p ); +extern Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ); +extern int Rwt_ManReadCompl( Rwt_Man_t * p ); +extern void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time ); +extern void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time ); +extern void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time ); +/*=== rwrUtil.c ========================================================*/ +extern void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ); +extern char * Rwt_ManGetPractical( Rwt_Man_t * p ); +extern Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ); +extern void Rwt_ManIncTravId( Rwt_Man_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/rwt/rwtDec.c b/src/aig/rwt/rwtDec.c new file mode 100644 index 00000000..98019629 --- /dev/null +++ b/src/aig/rwt/rwtDec.c @@ -0,0 +1,150 @@ +/**CFile**************************************************************** + + FileName [rwtDec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Evaluation and decomposition procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwtDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwt.h" +#include "deco.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ); +static Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Preprocesses computed library of subgraphs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManPreprocess( Rwt_Man_t * p ) +{ + Dec_Graph_t * pGraph; + Rwt_Node_t * pNode; + int i, k; + // put the nodes into the structure + p->pMapInv = ALLOC( unsigned short, 222 ); + memset( p->pMapInv, 0, sizeof(unsigned short) * 222 ); + p->vClasses = Vec_VecStart( 222 ); + for ( i = 0; i < p->nFuncs; i++ ) + { + if ( p->pTable[i] == NULL ) + continue; + // consider all implementations of this function + for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) + { + assert( pNode->uTruth == p->pTable[i]->uTruth ); + assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 ); + Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode ); + p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth]; + } + } + // compute decomposition forms for each node and verify them + Vec_VecForEachEntry( p->vClasses, pNode, i, k ) + { + pGraph = Rwt_NodePreprocess( p, pNode ); + pNode->pNext = (Rwt_Node_t *)pGraph; +// assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) ); + } +} + +/**Function************************************************************* + + Synopsis [Preprocesses subgraphs rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot; + assert( !Rwt_IsComplement(pNode) ); + // consider constant + if ( pNode->uTruth == 0 ) + return Dec_GraphCreateConst0(); + // consider the case of elementary var + if ( pNode->uTruth == 0x00FF ) + return Dec_GraphCreateLeaf( 3, 4, 1 ); + // start the subgraphs + pGraph = Dec_GraphCreate( 4 ); + // collect the nodes + Rwt_ManIncTravId( p ); + eRoot = Rwt_TravCollect_rec( p, pNode, pGraph ); + Dec_GraphSetRoot( pGraph, eRoot ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + // elementary variable + if ( pNode->fUsed ) + return Dec_EdgeCreate( pNode->Id - 1, 0 ); + // previously visited node + if ( pNode->TravId == p->nTravIds ) + return Dec_IntToEdge( pNode->Volume ); + pNode->TravId = p->nTravIds; + // solve for children + eNode0 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p0), pGraph ); + if ( Rwt_IsComplement(pNode->p0) ) + eNode0.fCompl = !eNode0.fCompl; + eNode1 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p1), pGraph ); + if ( Rwt_IsComplement(pNode->p1) ) + eNode1.fCompl = !eNode1.fCompl; + // create the decomposition node(s) + if ( pNode->fExor ) + eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); + else + eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + // save the result + pNode->Volume = Dec_EdgeToInt( eNode ); + return eNode; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/rwt/rwtMan.c b/src/aig/rwt/rwtMan.c new file mode 100644 index 00000000..869043a4 --- /dev/null +++ b/src/aig/rwt/rwtMan.c @@ -0,0 +1,358 @@ +/**CFile**************************************************************** + + FileName [rwtMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Rewriting manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwt.h" +#include "deco.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned short * s_puCanons = NULL; +static char * s_pPhases = NULL; +static char * s_pPerms = NULL; +static unsigned char * s_pMap = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts residual rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManGlobalStart() +{ + if ( s_puCanons == NULL ) + Extra_Truth4VarNPN( &s_puCanons, &s_pPhases, &s_pPerms, &s_pMap ); +} + +/**Function************************************************************* + + Synopsis [Starts residual rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManGlobalStop() +{ + FREE( s_puCanons ); + FREE( s_pPhases ); + FREE( s_pPerms ); + FREE( s_pMap ); +} + +/**Function************************************************************* + + Synopsis [Starts rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwt_Man_t * Rwt_ManStart( int fPrecompute ) +{ + Rwt_Man_t * p; + int clk = clock(); +clk = clock(); + p = ALLOC( Rwt_Man_t, 1 ); + memset( p, 0, sizeof(Rwt_Man_t) ); + p->nFuncs = (1<<16); + // copy the global tables + Rwt_ManGlobalStart(); + p->puCanons = s_puCanons; + p->pPhases = s_pPhases; + p->pPerms = s_pPerms; + p->pMap = s_pMap; + // initialize practical NPN classes + p->pPractical = Rwt_ManGetPractical( p ); + // create the table + p->pTable = ALLOC( Rwt_Node_t *, p->nFuncs ); + memset( p->pTable, 0, sizeof(Rwt_Node_t *) * p->nFuncs ); + // create the elementary nodes + p->pMmNode = Mem_FixedStart( sizeof(Rwt_Node_t) ); + p->vForest = Vec_PtrAlloc( 100 ); + Rwt_ManAddVar( p, 0x0000, fPrecompute ); // constant 0 + Rwt_ManAddVar( p, 0xAAAA, fPrecompute ); // var A + Rwt_ManAddVar( p, 0xCCCC, fPrecompute ); // var B + Rwt_ManAddVar( p, 0xF0F0, fPrecompute ); // var C + Rwt_ManAddVar( p, 0xFF00, fPrecompute ); // var D + p->nClasses = 5; + // other stuff + p->nTravIds = 1; + p->pPerms4 = Extra_Permutations( 4 ); + p->vLevNums = Vec_IntAlloc( 50 ); + p->vFanins = Vec_PtrAlloc( 50 ); + p->vFaninsCur = Vec_PtrAlloc( 50 ); + p->vNodesTemp = Vec_PtrAlloc( 50 ); + if ( fPrecompute ) + { // precompute subgraphs +// Rwt_ManPrecompute( p ); +// Rwt_ManPrint( p ); +// Rwt_ManWriteToArray( p ); + } + else + { // load saved subgraphs + Rwt_ManLoadFromArray( p, 0 ); +// Rwt_ManPrint( p ); + Rwt_ManPreprocess( p ); + } +p->timeStart = clock() - clk; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManStop( Rwt_Man_t * p ) +{ + if ( p->vClasses ) + { + Rwt_Node_t * pNode; + int i, k; + Vec_VecForEachEntry( p->vClasses, pNode, i, k ) + Dec_GraphFree( (Dec_Graph_t *)pNode->pNext ); + } + if ( p->vClasses ) Vec_VecFree( p->vClasses ); + Vec_PtrFree( p->vNodesTemp ); + Vec_PtrFree( p->vForest ); + Vec_IntFree( p->vLevNums ); + Vec_PtrFree( p->vFanins ); + Vec_PtrFree( p->vFaninsCur ); + Mem_FixedStop( p->pMmNode, 0 ); + FREE( p->pMapInv ); + free( p->pTable ); + free( p->pPractical ); + free( p->pPerms4 ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManPrintStats( Rwt_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < 222; i++ ) + Counter += (p->nScores[i] > 0); + + printf( "Rewriting statistics:\n" ); + printf( "Total cuts tries = %8d.\n", p->nCutsGood ); + printf( "Bad cuts found = %8d.\n", p->nCutsBad ); + printf( "Total subgraphs = %8d.\n", p->nSubgraphs ); + printf( "Used NPN classes = %8d.\n", Counter ); + printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); + printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten ); + printf( "Calculated gain = %8d.\n", p->nNodesGained ); + PRT( "Start ", p->timeStart ); + PRT( "Cuts ", p->timeCut ); + PRT( "Truth ", p->timeTruth ); + PRT( "Resynthesis ", p->timeRes ); + PRT( " Mffc ", p->timeMffc ); + PRT( " Eval ", p->timeEval ); + PRT( "Update ", p->timeUpdate ); + PRT( "TOTAL ", p->timeTotal ); + +/* + printf( "The scores are:\n" ); + for ( i = 0; i < 222; i++ ) + if ( p->nScores[i] > 0 ) + { + extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); + printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] ); + Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) ); + } + printf( "\n" ); +*/ +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManPrintStatsFile( Rwt_Man_t * p ) +{ + FILE * pTable; + pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%d ", p->nCutsGood ); + fprintf( pTable, "%d ", p->nSubgraphs ); + fprintf( pTable, "%d ", p->nNodesRewritten ); + fprintf( pTable, "%d", p->nNodesGained ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Rwt_ManReadDecs( Rwt_Man_t * p ) +{ + return p->pGraph; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ) +{ + return p->vFanins; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwt_ManReadCompl( Rwt_Man_t * p ) +{ + return p->fCompl; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time ) +{ + p->timeCut += Time; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time ) +{ + p->timeUpdate += Time; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time ) +{ + p->timeTotal += Time; +} + + +/**Function************************************************************* + + Synopsis [Precomputes AIG subgraphs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Precompute() +{ + Rwt_Man_t * p; + p = Rwt_ManStart( 1 ); + Rwt_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/rwt/rwtUtil.c b/src/aig/rwt/rwtUtil.c new file mode 100644 index 00000000..af3e1893 --- /dev/null +++ b/src/aig/rwt/rwtUtil.c @@ -0,0 +1,665 @@ +/**CFile**************************************************************** + + FileName [rwtUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwtUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// precomputed data +#ifdef _WIN32 +unsigned short s_RwtPracticalClasses[]; +unsigned short s_RwtAigSubgraphs[]; +#else +static unsigned short s_RwtPracticalClasses[]; +static unsigned short s_RwtAigSubgraphs[]; +#endif + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds the node to the end of the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ListAddToTail( Rwt_Node_t ** ppList, Rwt_Node_t * pNode ) +{ + Rwt_Node_t * pTemp; + // find the last one + for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext ) + ppList = &pTemp->pNext; + // attach at the end + *ppList = pNode; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ) +{ + Rwt_Node_t * pNew; + pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); + pNew->Id = p->vForest->nSize; + pNew->TravId = 0; + pNew->uTruth = uTruth; + pNew->Level = 0; + pNew->Volume = 0; + pNew->fUsed = 1; + pNew->fExor = 0; + pNew->p0 = NULL; + pNew->p1 = NULL; + pNew->pNext = NULL; + Vec_PtrPush( p->vForest, pNew ); + if ( fPrecompute ) + Rwt_ListAddToTail( p->pTable + uTruth, pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwt_Node_t * Rwt_ManAddNode( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1, int fExor, int Level, int Volume ) +{ + Rwt_Node_t * pNew; + unsigned uTruth; + // compute truth table, leve, volume + p->nConsidered++; + if ( fExor ) + uTruth = (p0->uTruth ^ p1->uTruth); + else + uTruth = (Rwt_IsComplement(p0)? ~Rwt_Regular(p0)->uTruth : Rwt_Regular(p0)->uTruth) & + (Rwt_IsComplement(p1)? ~Rwt_Regular(p1)->uTruth : Rwt_Regular(p1)->uTruth) & 0xFFFF; + // create the new node + pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); + pNew->Id = p->vForest->nSize; + pNew->TravId = 0; + pNew->uTruth = uTruth; + pNew->Level = Level; + pNew->Volume = Volume; + pNew->fUsed = 0; + pNew->fExor = fExor; + pNew->p0 = p0; + pNew->p1 = p1; + pNew->pNext = NULL; + Vec_PtrPush( p->vForest, pNew ); + // do not add if the node is not essential + if ( uTruth != p->puCanons[uTruth] ) + return pNew; + + // add to the list + p->nAdded++; + if ( p->pTable[uTruth] == NULL ) + p->nClasses++; + Rwt_ListAddToTail( p->pTable + uTruth, pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Trav_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, int * pVolume ) +{ + if ( pNode->fUsed || pNode->TravId == p->nTravIds ) + return; + pNode->TravId = p->nTravIds; + (*pVolume)++; + if ( pNode->fExor ) + (*pVolume)++; + Rwt_Trav_rec( p, Rwt_Regular(pNode->p0), pVolume ); + Rwt_Trav_rec( p, Rwt_Regular(pNode->p1), pVolume ); +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManIncTravId( Rwt_Man_t * p ) +{ + Rwt_Node_t * pNode; + int i; + if ( p->nTravIds++ < 0x8FFFFFFF ) + return; + Vec_PtrForEachEntry( p->vForest, pNode, i ) + pNode->TravId = 0; + p->nTravIds = 1; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwt_ManNodeVolume( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1 ) +{ + int Volume = 0; + Rwt_ManIncTravId( p ); + Rwt_Trav_rec( p, p0, &Volume ); + Rwt_Trav_rec( p, p1, &Volume ); + return Volume; +} + +/**Function************************************************************* + + Synopsis [Loads data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ) +{ + unsigned short * pArray = s_RwtAigSubgraphs; + Rwt_Node_t * p0, * p1; + unsigned Entry0, Entry1; + int Level, Volume, nEntries, fExor; + int i, clk = clock(); + + // reconstruct the forest + for ( i = 0; ; i++ ) + { + Entry0 = pArray[2*i + 0]; + Entry1 = pArray[2*i + 1]; + if ( Entry0 == 0 && Entry1 == 0 ) + break; + // get EXOR flag + fExor = (Entry0 & 1); + Entry0 >>= 1; + // get the nodes + p0 = p->vForest->pArray[Entry0 >> 1]; + p1 = p->vForest->pArray[Entry1 >> 1]; + // compute the level and volume of the new nodes + Level = 1 + RWT_MAX( p0->Level, p1->Level ); + Volume = 1 + Rwt_ManNodeVolume( p, p0, p1 ); + // set the complemented attributes + p0 = Rwt_NotCond( p0, (Entry0 & 1) ); + p1 = Rwt_NotCond( p1, (Entry1 & 1) ); + // add the node +// Rwt_ManTryNode( p, p0, p1, Level, Volume ); + Rwt_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); + } + nEntries = i - 1; + if ( fVerbose ) + { + printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); + printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk ); + } +} + +/**Function************************************************************* + + Synopsis [Create practical classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Rwt_ManGetPractical( Rwt_Man_t * p ) +{ + char * pPractical; + int i; + pPractical = ALLOC( char, p->nFuncs ); + memset( pPractical, 0, sizeof(char) * p->nFuncs ); + pPractical[0] = 1; + for ( i = 1; ; i++ ) + { + if ( s_RwtPracticalClasses[i] == 0 ) + break; + pPractical[ s_RwtPracticalClasses[i] ] = 1; + } + return pPractical; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +// the following 135 practical NPN classes of 4-variable functions were computed +// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks +static unsigned short s_RwtPracticalClasses[] = +{ + 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, + 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, + 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, + 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, + 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab, + 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, + 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368, + 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5, + 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669, + 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2, + 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8, + 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4, + 0x1ee1, 0x3cc3, 0x6996, 0x0000 +}; + +static unsigned short s_RwtAigSubgraphs[] = +{ + 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, + 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, + 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, + 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, + 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, + 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, + 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, + 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, + 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, + 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, + 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, + 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, + 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, + 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, + 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, + 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, + 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, + 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, + 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, + 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, + 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, + 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, + 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, + 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, + 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, + 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, + 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, + 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, + 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, + 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, + 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, + 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, + 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, + 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, + 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, + 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, + 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, + 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, + 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, + 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, + 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, + 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, + 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, + 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, + 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, + 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, + 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, + 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, + 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, + 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, + 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, + 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, + 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, + 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, + 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, + 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, + 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, + 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, + 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, + 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, + 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, + 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, + 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, + 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, + 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, + 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, + 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, + 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, + 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, + 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, + 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, + 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, + 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, + 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, + 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, + 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, + 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, + 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, + 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, + 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, + 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, + 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, + 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, + 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, + 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, + 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, + 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, + 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, + 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, + 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, + 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, + 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, + 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, + 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, + 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, + 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, + 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, + 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, + 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, + 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, + 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, + 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, + 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, + 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, + 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, + 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, + 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, + 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, + 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, + 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, + 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, + 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, + 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, + 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, + 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, + 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, + 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, + 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, + 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, + 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, + 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, + 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, + 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, + 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, + 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, + 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, + 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, + 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, + 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, + 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, + 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, + 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, + 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, + 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, + 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, + 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, + 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, + 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, + 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, + 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, + 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, + 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, + 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, + 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, + 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, + 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, + 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, + 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, + 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, + 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, + 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, + 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, + 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, + 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, + 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, + 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, + 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, + 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, + 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, + 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, + 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, + 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, + 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, + 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, + 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, + 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, + 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, + 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, + 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, + 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, + 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, + 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, + 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, + 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, + 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, + 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, + 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, + 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, + 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, + 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, + 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, + 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, + 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, + 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, + 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, + 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, + 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, + 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, + 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, + 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, + 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, + 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, + 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, + 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, + 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, + 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, + 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, + 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, + 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, + 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, + 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, + 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, + 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, + 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, + 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, + 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, + 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, + 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, + 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, + 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, + 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, + 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, + 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, + 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, + 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, + 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, + 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, + 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, + 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, + 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, + 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, + 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, + 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, + 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, + 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, + 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, + 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, + 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, + 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, + 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, + 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, + 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, + 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, + 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, + 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, + 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, + 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, + 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, + 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, + 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, + 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, + 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, + 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, + 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, + 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, + 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, + 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, + 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, + 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, + 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, + 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, + 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, + 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, + 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, + 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, + 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, + 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, + 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, + 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, + 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, + 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, + 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, + 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, + 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, + 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, + 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, + 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, + 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, + 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, + 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, + 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, + 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, + 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, + 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, + 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, + 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, + 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, + 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, + 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, + 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, + 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, + 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, + 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, + 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, + 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, + 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, + 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, + 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, + 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, + 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, + 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, + 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, + 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, + 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, + 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, + 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, + 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, + 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, + 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, + 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, + 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, + 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, + 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, + 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, + 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, + 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, + 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, + 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, + 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, + 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, + 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, + 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, + 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, + 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, + 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, + 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, + 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, + 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, + 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, + 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, + 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, + 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, + 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, + 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, + 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, + 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, + 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, + 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, + 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, + 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, + 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, + 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, + 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, + 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, + 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, + 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, + 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, + 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, + 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, + 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, + 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, + 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, + 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, + 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, + 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, + 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, + 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, + 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, + 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, + 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, + 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, + 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, + 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, + 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, + 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, + 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, + 0x0000,0x0000 +}; + + diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index f44a8022..c4c42f99 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -36,7 +36,7 @@ extern "C" { #include #include "cuddInt.h" -#include "aig.h" +#include "hop.h" #include "extra.h" #include "solver.h" #include "vec.h" @@ -178,7 +178,6 @@ struct Abc_Ntk_t_ Vec_Ptr_t * vPios; // the array of PIOs Vec_Ptr_t * vAsserts; // the array of assertions Vec_Ptr_t * vBoxes; // the array of boxes - Vec_Ptr_t * vCutSet; // the array of cutset nodes (used in the sequential AIG) // the number of living objects int nObjs; // the number of live objs int nObjCounts[ABC_OBJ_NUMBER]; // the number of objects by type @@ -196,8 +195,6 @@ struct Abc_Ntk_t_ Extra_MmStep_t * pMmStep; // memory manager for arrays void * pManFunc; // functionality manager (AIG manager, BDD manager, or memory manager for SOPs) // Abc_Lib_t * pVerLib; // for structural verilog designs - void * pManGlob; // the global BDD manager - Vec_Ptr_t * vFuncsGlob; // the global BDDs of CO functions Abc_ManTime_t * pManTime; // the timing manager (for mapped networks) stores arrival/required times for all nodes void * pManCut; // the cut manager (for AIGs) stores information about the cuts computed for the nodes int LevelMax; // maximum number of levels @@ -206,10 +203,8 @@ struct Abc_Ntk_t_ int * pModel; // counter-example (for miters) Abc_Ntk_t * pExdc; // the EXDC network (if given) void * pData; // misc - // skew values (for latches) - float maxMeanCycle; // maximum mean cycle time - float globalSkew; // global skewing - Vec_Flt_t * vSkews; // endpoint skewing + // node attributes + Vec_Ptr_t * vAttrs; // managers of various node attributes (node functionality, global BDDs, etc) }; struct Abc_Lib_t_ @@ -282,7 +277,6 @@ static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return Ve static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCos); } static inline int Abc_NtkAssertNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vAsserts); } static inline int Abc_NtkBoxNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vBoxes); } -static inline int Abc_NtkCutSetNodeNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCutSet); } static inline int Abc_NtkBiNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BI]; } static inline int Abc_NtkBoNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BO]; } static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NET]; } @@ -315,7 +309,6 @@ static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { return (A static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); } static inline Abc_Obj_t * Abc_NtkAssert( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vAsserts, i );} static inline Abc_Obj_t * Abc_NtkBox( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); } -static inline Abc_Obj_t * Abc_NtkCutSetNode( Abc_Ntk_t * pNtk, int i){ return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCutSet, i ); } // reading data members of the object static inline unsigned Abc_ObjType( Abc_Obj_t * pObj ) { return pObj->Type; } @@ -409,9 +402,12 @@ static inline bool Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Ab static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_DC; } static inline int Abc_LatchInit( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return (int)pLatch->pData; } -// skewing latches -static inline void Abc_NtkSetLatSkew ( Abc_Ntk_t * pNtk, int lat, float skew ) { Vec_FltWriteEntry( pNtk->vSkews, lat, skew ); } -static inline float Abc_NtkGetLatSkew ( Abc_Ntk_t * pNtk, int lat ) { if (lat >= Vec_FltSize( pNtk->vSkews )) return 0; else return Vec_FltEntry( pNtk->vSkews, lat ); } +// global BDDs of the nodes +static inline void * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk ) { return (void *)Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD); } +static inline DdManager * Abc_NtkGlobalBddMan( Abc_Ntk_t * pNtk ) { return (DdManager *)Vec_AttMan( Abc_NtkGlobalBdds(pNtk) ); } +static inline DdNode ** Abc_NtkGlobalBddArray( Abc_Ntk_t * pNtk ) { return (DdNode **)Vec_AttArray( Abc_NtkGlobalBdds(pNtk) ); } +static inline DdNode * Abc_ObjGlobalBdd( Abc_Obj_t * pObj ) { return (DdNode *)Vec_AttEntry( Abc_NtkGlobalBdds(pObj->pNtk), pObj->Id ); } +static inline void Abc_ObjSetGlobalBdd( Abc_Obj_t * pObj, DdNode * bF ) { Vec_AttWriteEntry( Abc_NtkGlobalBdds(pObj->pNtk), pObj->Id, bF ); } // outputs the runtime in seconds #define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) @@ -436,9 +432,6 @@ static inline float Abc_NtkGetLatSkew ( Abc_Ntk_t * pNtk, int lat ) #define Abc_AigForEachAnd( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_AigNodeIsAnd(pNode) ) {} else -#define Abc_SeqForEachCutsetNode( pNtk, pNode, i ) \ - for ( i = 0; (i < Abc_NtkCutSetNodeNum(pNtk)) && (((pNode) = Abc_NtkCutSetNode(pNtk, i)), 1); i++ )\ - if ( (pNode) == NULL ) {} else // various boxes #define Abc_NtkForEachBox( pNtk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) @@ -489,7 +482,7 @@ extern Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk ); extern void Abc_AigFree( Abc_Aig_t * pMan ); extern int Abc_AigCleanup( Abc_Aig_t * pMan ); extern bool Abc_AigCheck( Abc_Aig_t * pMan ); -extern int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk ); +extern int Abc_AigLevel( Abc_Ntk_t * pNtk ); extern Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ); extern Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); extern Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); @@ -536,7 +529,8 @@ extern Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ); extern Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); extern Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ); extern Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi ); -extern int Abc_NtkGetLevelNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkLevel( Abc_Ntk_t * pNtk ); +extern int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ); extern bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ); extern Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ); /*=== abcFanio.c ==========================================================*/ @@ -652,8 +646,8 @@ extern Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ); /*=== abcNtbdd.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); extern Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ); -extern DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fLatchOnly, int fReorder, int fVerbose ); -extern void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk ); +extern DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); +extern DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ); /*=== abcNtk.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ); extern Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); @@ -759,7 +753,7 @@ extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); /*=== abcSweep.c ==========================================================*/ extern int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); extern int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); -extern int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fVerbose ); +extern int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ); /*=== abcTiming.c ==========================================================*/ extern Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ); extern Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ); @@ -782,6 +776,7 @@ extern void Abc_NodeSetReverseLevel( Abc_Obj_t * pObj, int LevelR extern int Abc_NodeReadReverseLevel( Abc_Obj_t * pObj ); extern int Abc_NodeReadRequiredLevel( Abc_Obj_t * pObj ); /*=== abcUtil.c ==========================================================*/ +extern void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ); extern void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ); extern void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ); extern int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c index ce430cf4..46070a11 100644 --- a/src/base/abc/abcAig.c +++ b/src/base/abc/abcAig.c @@ -269,7 +269,7 @@ bool Abc_AigCheck( Abc_Aig_t * pMan ) SeeAlso [] ***********************************************************************/ -int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk ) +int Abc_AigLevel( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, LevelsMax; diff --git a/src/base/abc/abcCheck.c b/src/base/abc/abcCheck.c index eb5a8400..087d5150 100644 --- a/src/base/abc/abcCheck.c +++ b/src/base/abc/abcCheck.c @@ -580,12 +580,33 @@ bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ) fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) ); Value = 0; } - // make sure the latch has only one fanin + // make sure the latch has only one fanout if ( Abc_ObjFanoutNum(pLatch) != 1 ) { fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) ); Value = 0; } + // make sure the latch input has only one fanin + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n", + Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) ); + Value = 0; + } + // make sure the latch input has only one fanout + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n", + Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) ); + Value = 0; + } + // make sure the latch output has only one fanin + if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n", + Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) ); + Value = 0; + } return Value; } diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c index a8edfbeb..5a0bf252 100644 --- a/src/base/abc/abcDfs.c +++ b/src/base/abc/abcDfs.c @@ -24,12 +24,12 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +static void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes ); static void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); static void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); static void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); static void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); static void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ); -static int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode ); static bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// @@ -137,6 +137,101 @@ void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) Vec_PtrPush( vNodes, pNode ); } +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes, * vStack; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 1000 ); + vStack = Vec_PtrAlloc( 1000 ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_iter( vStack, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_iter( vStack, pObj, vNodes ); + } + Vec_PtrFree( vStack ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Iterative version of the DFS procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pNode, * pFanin; + int iFanin; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pRoot ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pRoot ); + // skip the CI + if ( Abc_ObjIsCi(pRoot) || (Abc_NtkIsStrash(pRoot->pNtk) && Abc_AigNodeIsConst(pRoot)) ) + return; + // add the CI + Vec_PtrClear( vStack ); + Vec_PtrPush( vStack, pRoot ); + Vec_PtrPush( vStack, (void *)0 ); + while ( Vec_PtrSize(vStack) > 0 ) + { + // get the node and its fanin + iFanin = (int)Vec_PtrPop(vStack); + pNode = Vec_PtrPop(vStack); + assert( !Abc_ObjIsNet(pNode) ); + // add it to the array of nodes if we finished + if ( iFanin == Abc_ObjFaninNum(pNode) ) + { + Vec_PtrPush( vNodes, pNode ); + continue; + } + // explore the next fanin + Vec_PtrPush( vStack, pNode ); + Vec_PtrPush( vStack, (void *)(iFanin+1) ); + // get the fanin + pFanin = Abc_ObjFanin0Ntk( Abc_ObjFanin(pNode,iFanin) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pFanin ) ) + continue; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pFanin ); + // skip the CI + if ( Abc_ObjIsCi(pFanin) || (Abc_NtkIsStrash(pFanin->pNtk) && Abc_AigNodeIsConst(pFanin)) ) + continue; + Vec_PtrPush( vStack, pFanin ); + Vec_PtrPush( vStack, (void *)0 ); + } +} + /**Function************************************************************* @@ -593,7 +688,7 @@ void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ) /**Function************************************************************* - Synopsis [Computes the number of logic levels not counting PIs/POs.] + Synopsis [Recursively counts the number of logic levels of one node.] Description [] @@ -602,24 +697,31 @@ void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ) SeeAlso [] ***********************************************************************/ -int Abc_NtkGetLevelNum( Abc_Ntk_t * pNtk ) +int Abc_NtkLevel_rec( Abc_Obj_t * pNode ) { - Abc_Obj_t * pNode; - int i, LevelsMax; - // set the traversal ID for this traversal - Abc_NtkIncrementTravId( pNtk ); - // set the CI levels to zero - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->Level = 0; - // perform the traversal - LevelsMax = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) + Abc_Obj_t * pNext; + int i, Level; + assert( !Abc_ObjIsNet(pNode) ); + // skip the PI + if ( Abc_ObjIsCi(pNode) ) + return pNode->Level; + assert( Abc_ObjIsNode( pNode ) ); + // if this node is already visited, return + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return pNode->Level; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + pNode->Level = 0; + Abc_ObjForEachFanin( pNode, pNext, i ) { - Abc_NtkGetLevelNum_rec( pNode ); - if ( LevelsMax < (int)pNode->Level ) - LevelsMax = (int)pNode->Level; + Level = Abc_NtkLevel_rec( Abc_ObjFanin0Ntk(pNext) ); + if ( pNode->Level < (unsigned)Level ) + pNode->Level = Level; } - return LevelsMax; + if ( Abc_ObjFaninNum(pNode) > 0 ) + pNode->Level++; + return pNode->Level; } /**Function************************************************************* @@ -633,18 +735,14 @@ int Abc_NtkGetLevelNum( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode ) +int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode ) { - Abc_Obj_t * pFanin; + Abc_Obj_t * pNext; int i, Level; assert( !Abc_ObjIsNet(pNode) ); - if ( pNode->Id == 27278 ) - { - int x = 0; - } // skip the PI - if ( Abc_ObjIsCi(pNode) ) - return 0; + if ( Abc_ObjIsCo(pNode) ) + return pNode->Level; assert( Abc_ObjIsNode( pNode ) ); // if this node is already visited, return if ( Abc_NodeIsTravIdCurrent( pNode ) ) @@ -653,17 +751,76 @@ int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode ) Abc_NodeSetTravIdCurrent( pNode ); // visit the transitive fanin pNode->Level = 0; - Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_ObjForEachFanout( pNode, pNext, i ) { - Level = Abc_NtkGetLevelNum_rec( Abc_ObjFanin0Ntk(pFanin) ); + Level = Abc_NtkLevelReverse_rec( Abc_ObjFanout0Ntk(pNext) ); if ( pNode->Level < (unsigned)Level ) pNode->Level = Level; } - if ( Abc_ObjFaninNum(pNode) > 0 ) - pNode->Level++; + pNode->Level++; return pNode->Level; } +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the CI levels to zero + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->Level = 0; + // perform the traversal + LevelsMax = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkLevel_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the CO levels to zero + Abc_NtkForEachCo( pNtk, pNode, i ) + pNode->Level = 0; + // perform the traversal + LevelsMax = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkLevelReverse_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + return LevelsMax; +} + /**Function************************************************************* diff --git a/src/base/abc/abcFanio.c b/src/base/abc/abcFanio.c index a988062f..e7ee3405 100644 --- a/src/base/abc/abcFanio.c +++ b/src/base/abc/abcFanio.c @@ -50,6 +50,10 @@ void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id ); if ( Abc_ObjIsComplement(pFanin) ) Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 ); + if ( Abc_ObjIsNet(pObj) && Abc_ObjFaninNum(pObj) > 1 ) + { + int x = 0; + } } diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index 23afcd25..e2389fc6 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -29,8 +29,8 @@ #define ABC_MUX_CUBES 100000 static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); -static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Aig_Obj_t * pRoot); -static Aig_Obj_t * Abc_ConvertSopToAig( Aig_Man_t * pMan, char * pSop ); +static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot); +static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -533,13 +533,13 @@ int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ) int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; - Aig_Man_t * pMan; + Hop_Man_t * pMan; int i; assert( Abc_NtkIsSopLogic(pNtk) || Abc_NtkIsSopNetlist(pNtk) ); // start the functionality manager - pMan = Aig_ManStart(); + pMan = Hop_ManStart(); // convert each node from SOP to BDD Abc_NtkForEachNode( pNtk, pNode, i ) @@ -572,32 +572,32 @@ int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Aig_Obj_t * Abc_ConvertSopToAigInternal( Aig_Man_t * pMan, char * pSop ) +Hop_Obj_t * Abc_ConvertSopToAigInternal( Hop_Man_t * pMan, char * pSop ) { - Aig_Obj_t * pAnd, * pSum; + Hop_Obj_t * pAnd, * pSum; int i, Value, nFanins; char * pCube; // get the number of variables nFanins = Abc_SopGetVarNum(pSop); // go through the cubes of the node's SOP - pSum = Aig_ManConst0(pMan); + pSum = Hop_ManConst0(pMan); Abc_SopForEachCube( pSop, nFanins, pCube ) { // create the AND of literals - pAnd = Aig_ManConst1(pMan); + pAnd = Hop_ManConst1(pMan); Abc_CubeForEachVar( pCube, Value, i ) { if ( Value == '1' ) - pAnd = Aig_And( pMan, pAnd, Aig_IthVar(pMan,i) ); + pAnd = Hop_And( pMan, pAnd, Hop_IthVar(pMan,i) ); else if ( Value == '0' ) - pAnd = Aig_And( pMan, pAnd, Aig_Not(Aig_IthVar(pMan,i)) ); + pAnd = Hop_And( pMan, pAnd, Hop_Not(Hop_IthVar(pMan,i)) ); } // add to the sum of cubes - pSum = Aig_Or( pMan, pSum, pAnd ); + pSum = Hop_Or( pMan, pSum, pAnd ); } // decide whether to complement the result if ( Abc_SopIsComplement(pSop) ) - pSum = Aig_Not(pSum); + pSum = Hop_Not(pSum); return pSum; } @@ -612,16 +612,16 @@ Aig_Obj_t * Abc_ConvertSopToAigInternal( Aig_Man_t * pMan, char * pSop ) SeeAlso [] ***********************************************************************/ -Aig_Obj_t * Abc_ConvertSopToAig( Aig_Man_t * pMan, char * pSop ) +Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ) { - extern Aig_Obj_t * Dec_GraphFactorSop( Aig_Man_t * pMan, char * pSop ); + extern Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ); int fUseFactor = 1; // consider the constant node if ( Abc_SopGetVarNum(pSop) == 0 ) - return Aig_NotCond( Aig_ManConst1(pMan), Abc_SopIsConst0(pSop) ); + return Hop_NotCond( Hop_ManConst1(pMan), Abc_SopIsConst0(pSop) ); // consider the special case of EXOR function if ( Abc_SopIsExorType(pSop) ) - return Aig_NotCond( Aig_CreateExor(pMan, Abc_SopGetVarNum(pSop)), Abc_SopIsComplement(pSop) ); + return Hop_NotCond( Hop_CreateExor(pMan, Abc_SopGetVarNum(pSop)), Abc_SopIsComplement(pSop) ); // decide when to use factoring if ( fUseFactor && Abc_SopGetVarNum(pSop) > 2 && Abc_SopGetCubeNum(pSop) > 1 ) return Dec_GraphFactorSop( pMan, pSop ); @@ -642,7 +642,7 @@ Aig_Obj_t * Abc_ConvertSopToAig( Aig_Man_t * pMan, char * pSop ) int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; - Aig_Man_t * pMan; + Hop_Man_t * pMan; DdManager * dd; int nFaninsMax, i; @@ -657,9 +657,9 @@ int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) // set the mapping of AIG nodes into the BDD nodes pMan = pNtk->pManFunc; - assert( Aig_ManPiNum(pMan) >= nFaninsMax ); + assert( Hop_ManPiNum(pMan) >= nFaninsMax ); for ( i = 0; i < nFaninsMax; i++ ) - Aig_ManPi(pMan, i)->pData = Cudd_bddIthVar(dd, i); + Hop_ManPi(pMan, i)->pData = Cudd_bddIthVar(dd, i); // convert each node from SOP to BDD Abc_NtkForEachNode( pNtk, pNode, i ) @@ -674,7 +674,7 @@ int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) Cudd_Ref( pNode->pData ); } - Aig_ManStop( pNtk->pManFunc ); + Hop_ManStop( pNtk->pManFunc ); pNtk->pManFunc = dd; // update the network type @@ -693,17 +693,17 @@ int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_ConvertAigToBdd_rec1( DdManager * dd, Aig_Obj_t * pObj ) +void Abc_ConvertAigToBdd_rec1( DdManager * dd, Hop_Obj_t * pObj ) { - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; - Abc_ConvertAigToBdd_rec1( dd, Aig_ObjFanin0(pObj) ); - Abc_ConvertAigToBdd_rec1( dd, Aig_ObjFanin1(pObj) ); - pObj->pData = Cudd_bddAnd( dd, (DdNode *)Aig_ObjChild0Copy(pObj), (DdNode *)Aig_ObjChild1Copy(pObj) ); + Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, (DdNode *)Hop_ObjChild0Copy(pObj), (DdNode *)Hop_ObjChild1Copy(pObj) ); Cudd_Ref( pObj->pData ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* @@ -717,17 +717,17 @@ void Abc_ConvertAigToBdd_rec1( DdManager * dd, Aig_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -void Abc_ConvertAigToBdd_rec2( DdManager * dd, Aig_Obj_t * pObj ) +void Abc_ConvertAigToBdd_rec2( DdManager * dd, Hop_Obj_t * pObj ) { - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) ) + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) return; - Abc_ConvertAigToBdd_rec2( dd, Aig_ObjFanin0(pObj) ); - Abc_ConvertAigToBdd_rec2( dd, Aig_ObjFanin1(pObj) ); + Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin1(pObj) ); Cudd_RecursiveDeref( dd, pObj->pData ); pObj->pData = NULL; - assert( Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjClearMarkA( pObj ); + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); } /**Function************************************************************* @@ -741,18 +741,18 @@ void Abc_ConvertAigToBdd_rec2( DdManager * dd, Aig_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -DdNode * Abc_ConvertAigToBdd( DdManager * dd, Aig_Obj_t * pRoot ) +DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot ) { DdNode * bFunc; // check the case of a constant - if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) ) - return Cudd_NotCond( Cudd_ReadOne(dd), Aig_IsComplement(pRoot) ); + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Cudd_NotCond( Cudd_ReadOne(dd), Hop_IsComplement(pRoot) ); // construct BDD - Abc_ConvertAigToBdd_rec1( dd, Aig_Regular(pRoot) ); + Abc_ConvertAigToBdd_rec1( dd, Hop_Regular(pRoot) ); // hold on to the result - bFunc = Cudd_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Cudd_Ref( bFunc ); // dereference BDD - Abc_ConvertAigToBdd_rec2( dd, Aig_Regular(pRoot) ); + Abc_ConvertAigToBdd_rec2( dd, Hop_Regular(pRoot) ); // return the result Cudd_Deref( bFunc ); return bFunc; diff --git a/src/base/abc/abcLatch.c b/src/base/abc/abcLatch.c index e475fd2a..cf3ddaba 100644 --- a/src/base/abc/abcLatch.c +++ b/src/base/abc/abcLatch.c @@ -117,11 +117,11 @@ int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ) { if ( Abc_NtkLatchIsSelfFeed( pLatch ) ) { - if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsSeq(pNtk) ) + if ( Abc_NtkIsStrash(pNtk) ) pConst1 = Abc_AigConst1(pNtk); else pConst1 = Abc_NtkCreateNodeConst1(pNtk); - Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 ); + Abc_ObjPatchFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 ); Counter++; } } diff --git a/src/base/abc/abcLib.c b/src/base/abc/abcLib.c index 218df6ef..0036e687 100644 --- a/src/base/abc/abcLib.c +++ b/src/base/abc/abcLib.c @@ -47,7 +47,7 @@ Abc_Lib_t * Abc_LibCreate( char * pName ) p->pName = Extra_UtilStrsav( pName ); p->tModules = st_init_table( strcmp, st_strhash ); p->vModules = Vec_PtrAlloc( 100 ); - p->pManFunc = Aig_ManStart(); + p->pManFunc = Hop_ManStart(); p->pLibrary = NULL; return p; } @@ -70,7 +70,7 @@ void Abc_LibFree( Abc_Lib_t * pLib ) if ( pLib->pName ) free( pLib->pName ); if ( pLib->pManFunc ) - Aig_ManStop( pLib->pManFunc ); + Hop_ManStop( pLib->pManFunc ); if ( pLib->tModules ) st_free_table( pLib->tModules ); if ( pLib->vModules ) diff --git a/src/base/abc/abcNetlist.c b/src/base/abc/abcNetlist.c index 5ea9b369..1ce10209 100644 --- a/src/base/abc/abcNetlist.c +++ b/src/base/abc/abcNetlist.c @@ -251,15 +251,6 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk, int fDirect ) pNtkNew = Abc_NtkLogicSopToNetlist( pNtkTemp ); Abc_NtkDelete( pNtkTemp ); } - else if ( Abc_NtkIsSeq(pNtk) ) - { - assert( 0 ); -/* - pNtkTemp = Abc_NtkSeqToLogicSop(pNtk); - pNtkNew = Abc_NtkLogicSopToNetlist( pNtkTemp ); - Abc_NtkDelete( pNtkTemp ); -*/ - } else if ( Abc_NtkIsBddLogic(pNtk) ) { if ( !Abc_NtkBddToSop(pNtk, fDirect) ) @@ -328,13 +319,22 @@ Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk ) Abc_NtkCleanup( pNtk, 0 ); assert( Abc_NtkIsLogic(pNtk) ); - assert( Abc_NtkLogicHasSimpleCos(pNtk) ); +// assert( Abc_NtkLogicHasSimpleCos(pNtk) ); + if ( !Abc_NtkLogicHasSimpleCos(pNtk) ) + { + printf( "Abc_NtkLogicSopToNetlist() warning: The network is converted to have simple COs.\n" ); + Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + } + if ( Abc_NtkIsBddLogic(pNtk) ) { if ( !Abc_NtkBddToSop(pNtk,0) ) return NULL; } +// Abc_NtkForEachCo(pNtk, pObj, i) +// Abc_ObjPrint( stdout, Abc_ObjFanin0(pObj) ); + // start the netlist by creating PI/PO/Latch objects pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); // create the CI nets and remember them in the new CI nodes @@ -358,7 +358,7 @@ Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk ) continue; } assert( Abc_ObjIsNode(pDriver) ); - // if the CO drive has no net, create it + // if the CO driver has no net, create it if ( pDriver->pCopy->pCopy == NULL ) { // create the CO net and connect it to CO diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index a3ce5145..f0642ffa 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -58,9 +58,7 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan pNtk->vPos = Vec_PtrAlloc( 100 ); pNtk->vCis = Vec_PtrAlloc( 100 ); pNtk->vCos = Vec_PtrAlloc( 100 ); - pNtk->vCutSet = Vec_PtrAlloc( 100 ); pNtk->vBoxes = Vec_PtrAlloc( 100 ); - pNtk->vSkews = Vec_FltAlloc( 100 ); // start the memory managers pNtk->pMmObj = fUseMemMan? Extra_MmFixedStart( sizeof(Abc_Obj_t) ) : NULL; pNtk->pMmStep = fUseMemMan? Extra_MmStepStart( ABC_NUM_STEPS ) : NULL; @@ -76,13 +74,15 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan else if ( Abc_NtkHasBdd(pNtk) ) pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); else if ( Abc_NtkHasAig(pNtk) ) - pNtk->pManFunc = Aig_ManStart(); + pNtk->pManFunc = Hop_ManStart(); else if ( Abc_NtkHasMapping(pNtk) ) pNtk->pManFunc = Abc_FrameReadLibGen(); else if ( !Abc_NtkHasBlackbox(pNtk) ) assert( 0 ); // name manager pNtk->pManName = Nm_ManCreate( 200 ); + // attribute manager + pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); return pNtk; } @@ -301,40 +301,6 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n", Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) ); } -/* - else if ( Abc_NtkIsSeq(pNtk) ) - { - // start the storage for initial states - Seq_Resize( pNtkNew->pManFunc, Abc_NtkObjNumMax(pNtk) ); - // copy the nodes - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( pObj->pCopy == NULL ) - { - Abc_NtkDupObj(pNtkNew, pObj, 0); - pObj->pCopy->Level = pObj->Level; - pObj->pCopy->fPhase = pObj->fPhase; - } - // connect the nodes - Abc_NtkForEachObj( pNtk, pObj, i ) - { - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - if ( Abc_ObjFaninC(pObj, k) ) - Abc_ObjSetFaninC( pObj->pCopy, k ); - if ( Seq_ObjFaninL(pObj, k) ) - Seq_NodeDupLats( pObj->pCopy, pObj, k ); - } - } - // relink the choice nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - if ( pObj->pData ) - pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; - // copy the cutset - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - Vec_PtrPush( pNtkNew->vCutSet, pObj->pCopy ); - } -*/ else { // duplicate the nets and nodes (CIs/COs/latches already dupped) @@ -795,6 +761,7 @@ Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) void Abc_NtkDelete( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; + void * pAttrMan; int TotalMemory, i; int LargePiece = (4 << ABC_NUM_STEPS); if ( pNtk == NULL ) @@ -845,9 +812,7 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) Vec_PtrFree( pNtk->vCos ); Vec_PtrFree( pNtk->vAsserts ); Vec_PtrFree( pNtk->vObjs ); - Vec_PtrFree( pNtk->vCutSet ); Vec_PtrFree( pNtk->vBoxes ); - Vec_FltFree( pNtk->vSkews ); if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR ); if ( pNtk->pModel ) free( pNtk->pModel ); TotalMemory = 0; @@ -874,7 +839,7 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) else if ( Abc_NtkHasBdd(pNtk) ) Extra_StopManager( pNtk->pManFunc ); else if ( Abc_NtkHasAig(pNtk) ) - { if ( pNtk->pManFunc ) Aig_ManStop( pNtk->pManFunc ); } + { if ( pNtk->pManFunc ) Hop_ManStop( pNtk->pManFunc ); } else if ( Abc_NtkHasMapping(pNtk) ) pNtk->pManFunc = NULL; else if ( !Abc_NtkHasBlackbox(pNtk) ) @@ -891,6 +856,11 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) } if ( pNtk->pBlackBoxes ) Vec_IntFree( pNtk->pBlackBoxes ); + // free node attributes + Vec_PtrForEachEntry( pNtk->vAttrs, pAttrMan, i ) + if ( pAttrMan ) + Vec_AttFree( pAttrMan, 1 ); + Vec_PtrFree( pNtk->vAttrs ); free( pNtk ); } diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c index dc3ff73c..d0e1dc37 100644 --- a/src/base/abc/abcObj.c +++ b/src/base/abc/abcObj.c @@ -299,7 +299,7 @@ void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ) Abc_NodeCollectFanins( pObj, vNodes ); Abc_NtkDeleteObj( pObj ); Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) == 0 ) + if ( !Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) Abc_NtkDeleteAll_rec( pObj ); Vec_PtrFree( vNodes ); } @@ -342,7 +342,7 @@ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName else if ( Abc_NtkHasBdd(pNtkNew) ) pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData); else if ( Abc_NtkHasAig(pNtkNew) ) - pObjNew->pData = Aig_Transfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj)); + pObjNew->pData = Hop_Transfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj)); else if ( Abc_NtkHasMapping(pNtkNew) ) pObjNew->pData = pObj->pData; else assert( 0 ); @@ -576,7 +576,7 @@ Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ) else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData ); else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Aig_ManConst0(pNtk->pManFunc); + pNode->pData = Hop_ManConst0(pNtk->pManFunc); else if ( Abc_NtkHasMapping(pNtk) ) pNode->pData = Mio_LibraryReadConst0(Abc_FrameReadLibGen()); else if ( !Abc_NtkHasBlackbox(pNtk) ) @@ -605,7 +605,7 @@ Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ) else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData ); else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Aig_ManConst1(pNtk->pManFunc); + pNode->pData = Hop_ManConst1(pNtk->pManFunc); else if ( Abc_NtkHasMapping(pNtk) ) pNode->pData = Mio_LibraryReadConst1(Abc_FrameReadLibGen()); else if ( !Abc_NtkHasBlackbox(pNtk) ) @@ -635,7 +635,7 @@ Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_Not(Cudd_bddIthVar(pNtk->pManFunc,0)), Cudd_Ref( pNode->pData ); else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Aig_Not(Aig_IthVar(pNtk->pManFunc,0)); + pNode->pData = Hop_Not(Hop_IthVar(pNtk->pManFunc,0)); else if ( Abc_NtkHasMapping(pNtk) ) pNode->pData = Mio_LibraryReadInv(Abc_FrameReadLibGen()); else @@ -665,7 +665,7 @@ Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_bddIthVar(pNtk->pManFunc,0), Cudd_Ref( pNode->pData ); else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Aig_IthVar(pNtk->pManFunc,0); + pNode->pData = Hop_IthVar(pNtk->pManFunc,0); else if ( Abc_NtkHasMapping(pNtk) ) pNode->pData = Mio_LibraryReadBuf(Abc_FrameReadLibGen()); else @@ -697,7 +697,7 @@ Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Extra_bddCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Aig_CreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ); else assert( 0 ); return pNode; @@ -727,7 +727,7 @@ Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Extra_bddCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Aig_CreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + pNode->pData = Hop_CreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ); else assert( 0 ); return pNode; @@ -757,7 +757,7 @@ Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Extra_bddCreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Aig_CreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + pNode->pData = Hop_CreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ); else assert( 0 ); return pNode; @@ -787,7 +787,7 @@ Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_ else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pNode->pData ); else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Aig_Mux(pNtk->pManFunc,Aig_IthVar(pNtk->pManFunc,0),Aig_IthVar(pNtk->pManFunc,1),Aig_IthVar(pNtk->pManFunc,2)); + pNode->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2)); else assert( 0 ); return pNode; @@ -834,7 +834,7 @@ bool Abc_NodeIsConst0( Abc_Obj_t * pNode ) if ( Abc_NtkHasBdd(pNtk) ) return Cudd_IsComplement(pNode->pData); if ( Abc_NtkHasAig(pNtk) ) - return Aig_IsComplement(pNode->pData); + return Hop_IsComplement(pNode->pData); if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == Mio_LibraryReadConst0(Abc_FrameReadLibGen()); assert( 0 ); @@ -864,7 +864,7 @@ bool Abc_NodeIsConst1( Abc_Obj_t * pNode ) if ( Abc_NtkHasBdd(pNtk) ) return !Cudd_IsComplement(pNode->pData); if ( Abc_NtkHasAig(pNtk) ) - return !Aig_IsComplement(pNode->pData); + return !Hop_IsComplement(pNode->pData); if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == Mio_LibraryReadConst1(Abc_FrameReadLibGen()); assert( 0 ); @@ -894,7 +894,7 @@ bool Abc_NodeIsBuf( Abc_Obj_t * pNode ) if ( Abc_NtkHasBdd(pNtk) ) return !Cudd_IsComplement(pNode->pData); if ( Abc_NtkHasAig(pNtk) ) - return !Aig_IsComplement(pNode->pData); + return !Hop_IsComplement(pNode->pData); if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == Mio_LibraryReadBuf(Abc_FrameReadLibGen()); assert( 0 ); @@ -924,7 +924,7 @@ bool Abc_NodeIsInv( Abc_Obj_t * pNode ) if ( Abc_NtkHasBdd(pNtk) ) return Cudd_IsComplement(pNode->pData); if ( Abc_NtkHasAig(pNtk) ) - return Aig_IsComplement(pNode->pData); + return Hop_IsComplement(pNode->pData); if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == Mio_LibraryReadInv(Abc_FrameReadLibGen()); assert( 0 ); @@ -951,7 +951,7 @@ void Abc_NodeComplement( Abc_Obj_t * pNode ) else if ( Abc_NtkHasBdd(pNode->pNtk) ) pNode->pData = Cudd_Not( pNode->pData ); else if ( Abc_NtkHasAig(pNode->pNtk) ) - pNode->pData = Aig_Not( pNode->pData ); + pNode->pData = Hop_Not( pNode->pData ); else assert( 0 ); } diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c index fa921391..ee86e8aa 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -77,109 +77,6 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) Abc_ShowFile( FileNameDot ); } -/**Function************************************************************* - - Synopsis [Visualizes AIG with choices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkShowAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesShow ) -{ - FILE * pFile; - Abc_Obj_t * pNode; - Vec_Ptr_t * vNodes; - char FileNameDot[200]; - int i; - - assert( Abc_NtkIsStrash(pNtk) ); - // create the file name - Abc_ShowGetFileName( pNtk->pName, FileNameDot ); - // check that the file can be opened - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - fclose( pFile ); - - // collect all nodes in the network - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachObj( pNtk, pNode, i ) - Vec_PtrPush( vNodes, pNode ); - // write the DOT file - Io_WriteDotAig( pNtk, vNodes, vNodesShow, FileNameDot, 0 ); - Vec_PtrFree( vNodes ); - - // visualize the file - Abc_ShowFile( FileNameDot ); -} - -/**Function************************************************************* - - Synopsis [Visualizes AIG with choices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkShowMulti( Abc_Ntk_t * pNtk ) -{ - FILE * pFile; - Abc_Obj_t * pNode; - Vec_Ptr_t * vNodes; - char FileNameDot[200]; - int i; - extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); - extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); - extern void Abc_NtkBalanceLevel( Abc_Ntk_t * pNtk ); - - assert( Abc_NtkIsStrash(pNtk) ); - // create the file name - Abc_ShowGetFileName( pNtk->pName, FileNameDot ); - // check that the file can be opened - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - fclose( pFile ); - - // get the implication supergates - Abc_NtkBalanceAttach( pNtk ); - // set the levels based on the implication supergates - Abc_NtkBalanceLevel( pNtk ); - - // collect all nodes that are roots - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachCi( pNtk, pNode, i ) - Vec_PtrPush( vNodes, pNode ); - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( pNode->pCopy || Abc_ObjFaninNum(pNode) == 0 ) - Vec_PtrPush( vNodes, pNode ); - Abc_NtkForEachPo( pNtk, pNode, i ) - Vec_PtrPush( vNodes, pNode ); - - // write the DOT file - Io_WriteDotAig( pNtk, vNodes, NULL, FileNameDot, 1 ); - Vec_PtrFree( vNodes ); - - // undo the supergates - Abc_NtkBalanceDetach( pNtk ); - // set the normal levels - Abc_NtkGetLevelNum( pNtk ); - - // visualize the file - Abc_ShowFile( FileNameDot ); -} - /**Function************************************************************* Synopsis [Visualizes a reconvergence driven cut at the node.] @@ -232,7 +129,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) // add the root node to the cone (for visualization) Vec_PtrPush( vCutSmall, pNode ); // write the DOT file - Io_WriteDotAig( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0 ); + Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0 ); // stop the cut computation manager Abc_NtkManCutStop( p ); @@ -251,7 +148,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) SeeAlso [] ***********************************************************************/ -void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames ) +void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ) { FILE * pFile; Abc_Obj_t * pNode; @@ -259,8 +156,15 @@ void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames ) char FileNameDot[200]; int i; - assert( !Abc_NtkIsStrash(pNtk) ); - Abc_NtkLogicToSop( pNtk, 0 ); + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkGetChoiceNum(pNtk) ) + { + printf( "Temporarily visualization of AIGs with choice nodes is disabled.\n" ); + return; + } + // convert to logic SOP + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkLogicToSop( pNtk, 0 ); // create the file name Abc_ShowGetFileName( pNtk->pName, FileNameDot ); // check that the file can be opened @@ -274,10 +178,12 @@ void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames ) // collect all nodes in the network vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachObj( pNtk, pNode, i ) -// if ( !Abc_ObjIsBi(pNode) && !Abc_ObjIsBo(pNode) ) - Vec_PtrPush( vNodes, pNode ); + Vec_PtrPush( vNodes, pNode ); // write the DOT file - Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames ); + if ( fSeq ) + Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); + else + Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); Vec_PtrFree( vNodes ); // visualize the file diff --git a/src/base/abc/abcSop.c b/src/base/abc/abcSop.c index db0803c1..81d91499 100644 --- a/src/base/abc/abcSop.c +++ b/src/base/abc/abcSop.c @@ -768,7 +768,8 @@ bool Abc_SopCheck( char * pSop, int nFanins ) // compare the distance if ( pCubes - pCubesOld != nFanins ) { - fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover and its fanins.\n" ); + fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover size (%d) and its fanin number (%d).\n", + pCubes - pCubesOld, nFanins ); return 0; } // check the output values for this cube @@ -779,7 +780,7 @@ bool Abc_SopCheck( char * pSop, int nFanins ) fFound1 = 1; else if ( *pCubes != 'x' && *pCubes != 'n' ) { - fprintf( stdout, "Abc_SopCheck: SOP has a strange character in the output part of its cube.\n" ); + fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes ); return 0; } // check the last symbol (new line) diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index fa1cd69a..12bb8341 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -32,6 +32,27 @@ /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [Frees one attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ) +{ + void * pUserMan; + Vec_Att_t * pAttrMan; + pAttrMan = Vec_PtrEntry( pNtk->vAttrs, Attr ); + Vec_PtrWriteEntry( pNtk->vAttrs, Attr, NULL ); + pUserMan = Vec_AttFree( pAttrMan, fFreeMan ); + return pUserMan; +} + /**Function************************************************************* Synopsis [Increments the current traversal ID of the network.] @@ -225,7 +246,7 @@ int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ) assert( pNode->pData ); if ( Abc_NodeIsConst(pNode) ) continue; - nNodes += pNode->pData? Aig_DagSize( pNode->pData ) : 0; + nNodes += pNode->pData? Hop_DagSize( pNode->pData ) : 0; } return nNodes; } @@ -356,7 +377,7 @@ int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter; - if ( !Abc_NtkHasAig(pNtk) ) + if ( !Abc_NtkIsStrash(pNtk) ) return 0; Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) @@ -578,7 +599,7 @@ void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fD Description [The COs of a logic network are simple under three conditions: (1) The edge from CO to its driver is not complemented. (2) If CI is a driver of a CO, they have the same name.] - (2) If two COs share the same driver, they have the same name.] + (3) If two COs share the same driver, they have the same name.] SideEffects [] @@ -621,7 +642,7 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ) Description [The COs of a logic network are simple under three conditions: (1) The edge from CO to its driver is not complemented. (2) If CI is a driver of a CO, they have the same name.] - (2) If two COs share the same driver, they have the same name. + (3) If two COs share the same driver, they have the same name. In some cases, such as FPGA mapping, we prevent the increase in delay by duplicating the driver nodes, rather than adding invs/bufs.] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index dffe4b99..9613ab40 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -22,10 +22,9 @@ #include "mainInt.h" #include "fraig.h" #include "fxu.h" -#include "fpga.h" -#include "pga.h" #include "cut.h" -//#include "seq.h" +#include "fpga.h" +#include "if.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -46,12 +45,10 @@ static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintSkews ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandShowAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandShowNtk ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -123,7 +120,7 @@ static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPga ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandScut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandInit ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -145,9 +142,6 @@ static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandHoward ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSkewForward ( Abc_Frame_t * pAbc, int argc, char ** argv ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -182,12 +176,10 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_skews", Abc_CommandPrintSkews, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 ); Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "show_aig", Abc_CommandShowAig, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "show_ntk", Abc_CommandShowNtk, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); @@ -259,7 +251,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 ); Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 ); - Cmd_CommandAdd( pAbc, "FPGA mapping", "pga", Abc_CommandPga, 1 ); + Cmd_CommandAdd( pAbc, "FPGA mapping", "if", Abc_CommandIf, 1 ); // Cmd_CommandAdd( pAbc, "Sequential", "scut", Abc_CommandScut, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "init", Abc_CommandInit, 1 ); @@ -281,9 +273,6 @@ void Abc_Init( Abc_Frame_t * pAbc ) // Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 ); // Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 ); -// Cmd_CommandAdd( pAbc, "Sequential", "howard", Abc_CommandHoward, 0 ); -// Cmd_CommandAdd( pAbc, "Sequential", "skew_fwd", Abc_CommandSkewForward, 0 ); - // Rwt_Man4ExploreStart(); // Map_Var3Print(); // Map_Var4Test(); @@ -1383,29 +1372,38 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPrintSkews( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk; int c; - int fPrintAll; + int fSeq; + int fGateNames; + int fUseReverse; + extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fPrintAll = 0; + fSeq = 0; + fGateNames = 0; + fUseReverse = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "rsgh" ) ) != EOF ) { switch ( c ) { - case 'a': - fPrintAll = 1; + case 'r': + fUseReverse ^= 1; + break; + case 's': + fSeq ^= 1; + break; + case 'g': + fGateNames ^= 1; break; - case 'h': - goto usage; default: goto usage; } @@ -1417,25 +1415,19 @@ int Abc_CommandPrintSkews( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( !Abc_NtkIsSeq(pNtk) && Abc_NtkLatchNum(pNtk) == 0 ) - { - fprintf( pErr, "The network has no latches.\n" ); - return 0; - } - - if ( pNtk->vSkews == NULL || pNtk->vSkews->nSize == 0 ) - { - fprintf( pErr, "The network has no clock skew schedule.\n" ); - return 0; - } - - Abc_NtkPrintSkews( pOut, pNtk, fPrintAll ); + Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse ); return 0; usage: - fprintf( pErr, "usage: print_skews [-h] [-a]\n" ); - fprintf( pErr, "\t prints information about a clock skew schedule\n" ); - fprintf( pErr, "\t-a : dumps the skew of every latch [default = no]\n"); + fprintf( pErr, "usage: show [-srgh]\n" ); + fprintf( pErr, " visualizes the network structure using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\t-s : toggles visualization of sequential networks [default = %s].\n", fSeq? "yes": "no" ); + fprintf( pErr, "\t-r : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" ); + fprintf( pErr, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -1628,145 +1620,6 @@ usage: return 1; } -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandShowAig( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fMulti; - extern void Abc_NtkShowAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesShow ); - extern void Abc_NtkShowMulti( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fMulti = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) - { - switch ( c ) - { - case 'm': - fMulti ^= 1; - break; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Visualizing networks other than AIGs can be done using command \"show_ntk\".\n" ); - return 1; - } - - if ( fMulti && !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Visualizing multi-input ANDs cannot be done for sequential network (run \"unseq\").\n" ); - return 1; - } - - if ( !fMulti ) - Abc_NtkShowAig( pNtk, NULL ); - else - Abc_NtkShowMulti( pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: show_aig [-h]\n" ); - fprintf( pErr, " visualizes the AIG with choices using DOT and GSVIEW\n" ); -#ifdef WIN32 - fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); - fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); -#endif - fprintf( pErr, "\t-m : toggles visualization of multi-input ANDs [default = %s].\n", fMulti? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandShowNtk( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fGateNames; - extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fGateNames = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) - { - switch ( c ) - { - case 'g': - fGateNames ^= 1; - break; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Visualizing AIG can only be done using command \"show_aig\".\n" ); - return 1; - } - Abc_NtkShow( pNtk, fGateNames ); - return 0; - -usage: - fprintf( pErr, "usage: show_ntk [-gh]\n" ); - fprintf( pErr, " visualizes the network structure using DOT and GSVIEW\n" ); -#ifdef WIN32 - fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); - fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); -#endif - fprintf( pErr, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - /**Function************************************************************* @@ -5136,8 +4989,8 @@ int Abc_CommandCycle( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - nFrames = 50; - fVerbose = 0; + nFrames = 100; + fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF ) { @@ -5633,7 +5486,7 @@ int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - fUpdateLevel = 1; + fUpdateLevel = 0; fUseZeroCost = 0; fVerbose = 0; Extra_UtilGetoptReset(); @@ -7343,7 +7196,7 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: if ( DelayTarget == -1 ) - sprintf( Buffer, "not used" ); + sprintf( Buffer, "best possible" ); else sprintf( Buffer, "%.2f", DelayTarget ); if ( nLutSize == -1 ) @@ -7394,7 +7247,7 @@ int Abc_CommandFpgaFast( Abc_Frame_t * pAbc, int argc, char ** argv ) fRecovery = 1; fVerbose = 0; DelayTarget =-1; - nLutSize = 8; + nLutSize = 5; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "avhDK" ) ) != EOF ) { @@ -7514,46 +7367,90 @@ usage: SeeAlso [] ***********************************************************************/ -int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) { + char Buffer[100]; + char LutSize[100]; FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkRes; - Pga_Params_t Params, * pParams = &Params; + If_Par_t Pars, * pPars = &Pars; int c; - extern Abc_Ntk_t * Abc_NtkPga( Pga_Params_t * pParams ); + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - memset( pParams, 0, sizeof(Pga_Params_t) ); - pParams->pNtk = pNtk; - pParams->pLutLib = Abc_FrameReadLibLut(); - pParams->fAreaFlow = 1; - pParams->fArea = 1; - pParams->fSwitching = 0; - pParams->fDropCuts = 0; - pParams->fVerbose = 0; + memset( pPars, 0, sizeof(If_Par_t) ); + pPars->Mode = 1; + pPars->nLutSize = 4; +// pPars->pLutLib = Abc_FrameReadLibLut(); + pPars->nCutsMax = 2; + pPars->fSeq = 0; + pPars->fLatchPaths = 0; + pPars->nLatches = 0; + pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); + pPars->pTimesReq = NULL; + pPars->DelayTarget = -1; + pPars->fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "fapdvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "MKCDlsvh" ) ) != EOF ) { switch ( c ) { - case 'f': - pParams->fAreaFlow ^= 1; + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->Mode = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->Mode < 0 ) + goto usage; break; - case 'a': - pParams->fArea ^= 1; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutSize < 0 ) + goto usage; break; - case 'p': - pParams->fSwitching ^= 1; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; break; - case 'd': - pParams->fDropCuts ^= 1; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->DelayTarget <= 0.0 ) + goto usage; + break; + case 'l': + pPars->fLatchPaths ^= 1; + break; + case 's': + pPars->fSeq ^= 1; break; case 'v': - pParams->fVerbose ^= 1; + pPars->fVerbose ^= 1; break; case 'h': default: @@ -7567,8 +7464,18 @@ int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - printf( "This command is not yet implemented.\n" ); - return 0; + if ( pPars->Mode < 0 || pPars->Mode > 4 ) + { + fprintf( pErr, "Incorrect mapping mode.\n" ); + return 1; + } + + // set the latch paths + if ( pPars->fLatchPaths ) + { + for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ ) + pPars->pTimesArr[c] = -ABC_INFINITY; + } if ( !Abc_NtkIsStrash(pNtk) ) { @@ -7588,7 +7495,7 @@ int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv ) } fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); // get the new network - pNtkRes = Abc_NtkPga( pParams ); + pNtkRes = Abc_NtkIf( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); @@ -7600,7 +7507,7 @@ int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv ) else { // get the new network - pNtkRes = Abc_NtkPga( pParams ); + pNtkRes = Abc_NtkIf( pNtk, pPars ); if ( pNtkRes == NULL ) { fprintf( pErr, "FPGA mapping has failed.\n" ); @@ -7612,14 +7519,28 @@ int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: pga [-fapdvh]\n" ); - fprintf( pErr, "\t performs FPGA mapping of the current network\n" ); - fprintf( pErr, "\t-f : toggles area flow recovery [default = %s]\n", pParams->fAreaFlow? "yes": "no" ); - fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", pParams->fArea? "yes": "no" ); - fprintf( pErr, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", pParams->fSwitching? "yes": "no" ); - fprintf( pErr, "\t-d : toggles dropping cuts to save memory [default = %s]\n", pParams->fDropCuts? "yes": "no" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : prints the command usage\n"); + if ( pPars->DelayTarget == -1 ) + sprintf( Buffer, "best possible" ); + else + sprintf( Buffer, "%.2f", pPars->DelayTarget ); + if ( pPars->nLutSize == -1 ) + sprintf( LutSize, "library" ); + else + sprintf( LutSize, "%d", pPars->nLutSize ); + fprintf( pErr, "usage: if [-M num] [-K num] [-C num] [-D float] [-lsvh]\n" ); + fprintf( pErr, "\t performs FPGA mapping of the network as follows:\n" ); + fprintf( pErr, "\t 1 - delay only\n" ); + fprintf( pErr, "\t 2 - area only\n" ); + fprintf( pErr, "\t 3 - area under delay constraints\n" ); + fprintf( pErr, "\t 4 - area under delay constraints with area recovery\n" ); + fprintf( pErr, "\t-M num : the mapping mode [default = %d]\n", pPars->Mode ); + fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 32) [default = %s]\n", LutSize ); + fprintf( pErr, "\t-C num : the max number of cuts to use (1 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); + fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); + fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); + fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeq? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : prints the command usage\n"); return 1; } @@ -7996,7 +7917,7 @@ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) Mode = 5; fForward = 0; fBackward = 0; - fVerbose = 1; + fVerbose = 0; nMaxIters = 15; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Mfbvh" ) ) != EOF ) @@ -8048,6 +7969,12 @@ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } + if ( Mode < 0 || Mode > 6 ) + { + fprintf( pErr, "The mode (%d) is incorrect. Retiming is not performed.\n", Mode ); + return 0; + } + if ( Abc_NtkIsStrash(pNtk) ) { if ( Abc_NtkGetChoiceNum(pNtk) ) @@ -8089,6 +8016,7 @@ usage: fprintf( pErr, "\t 3: forward and backward min-area retiming\n" ); fprintf( pErr, "\t 4: forward and backward min-delay retiming\n" ); fprintf( pErr, "\t 5: mode 3 followed by mode 4\n" ); + fprintf( pErr, "\t 6: Pan's optimum-delay retiming using binary search\n" ); fprintf( pErr, "\t-M num : the retiming algorithm to use [default = %d]\n", Mode ); fprintf( pErr, "\t-f : enables forward-only retiming in modes 3,4,5 [default = %s]\n", fForward? "yes": "no" ); fprintf( pErr, "\t-b : enables backward-only retiming in modes 3,4,5 [default = %s]\n", fBackward? "yes": "no" ); @@ -8488,6 +8416,8 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) FILE * pOut, * pErr; Abc_Ntk_t * pNtk; int c; + int fLatchSweep; + int fAutoSweep; int fVerbose; pNtk = Abc_FrameReadNtk(pAbc); @@ -8495,12 +8425,20 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults - fVerbose = 1; + fLatchSweep = 0; + fAutoSweep = 0; + fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "lavh" ) ) != EOF ) { switch ( c ) { + case 'l': + fLatchSweep ^= 1; + break; + case 'a': + fAutoSweep ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -8521,16 +8459,18 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } // modify the current network - Abc_NtkCleanupSeq( pNtk, fVerbose ); + Abc_NtkCleanupSeq( pNtk, fLatchSweep, fAutoSweep, fVerbose ); return 0; usage: - fprintf( pErr, "usage: scleanup [-vh]\n" ); + fprintf( pErr, "usage: scleanup [-lavh]\n" ); fprintf( pErr, "\t performs sequential cleanup\n" ); fprintf( pErr, "\t - removes nodes/latches that do not feed into POs\n" ); fprintf( pErr, "\t - removes and shared latches driven by constants\n" ); fprintf( pErr, "\t - replaces autonomous logic by free PI variables\n" ); fprintf( pErr, "\t (the latter may change sequential behaviour)\n" ); + fprintf( pErr, "\t-l : toggle sweeping latches [default = %s]\n", fLatchSweep? "yes": "no" ); + fprintf( pErr, "\t-a : toggle removing autonomous logic [default = %s]\n", fAutoSweep? "yes": "no" ); fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -8694,7 +8634,7 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults fSat = 0; fVerbose = 0; - nFrames = 3; + nFrames = 5; nSeconds = 20; nConfLimit = 10000; nInsLimit = 0; @@ -8758,6 +8698,12 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) } } + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) @@ -9290,168 +9236,6 @@ usage: return 1; } -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandHoward( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fVerbose; - double result; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsSeq(pNtk) && Abc_NtkLatchNum(pNtk) == 0 ) - { - fprintf( pErr, "The network has no latches. Analysis is not performed.\n" ); - return 0; - } - - if ( Abc_NtkHasAig(pNtk) ) - { - // quit if there are choice nodes - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "Currently cannot analyze networks with choice nodes.\n" ); - return 0; - } - - /* - if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkAigToSeq(pNtk); - else - pNtkRes = Abc_NtkDup(pNtk); - - */ - - fprintf( pErr, "Currently cannot analyze unmapped networks.\n" ); - return 0; - } - -// result = Seq_NtkHoward( pNtk, fVerbose ); - result = 0; - - if (result < 0) { - fprintf( pErr, "Analysis failed.\n" ); - return 0; - } - - printf("Maximum mean cycle time = %.2f\n", result); - - return 1; - -usage: - fprintf( pErr, "usage: howard [-h]\n" ); - fprintf( pErr, "\t computes the maximum mean cycle time using Howard's algorithm\n" ); - fprintf( pErr, "\t-v : toggles 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_CommandSkewForward( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fMinimize; - float target; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - target = pNtk->maxMeanCycle; - fMinimize = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) - { - switch ( c ) - { - case 'm': - fMinimize ^= 1; - break; - default: - goto usage; - } - } - - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsSeq(pNtk) && Abc_NtkLatchNum(pNtk) == 0 ) - { - fprintf( pErr, "The network has no latches.\n" ); - return 0; - } - - if ( pNtk->vSkews == NULL || pNtk->vSkews->nSize == 0 ) - { - fprintf( pErr, "The network has no clock skew schedule.\n" ); - return 0; - } - -// Seq_NtkSkewForward( pNtk, target, fMinimize ); - - return 1; - -usage: - fprintf( pErr, "usage: skew_fwd [-h] [-m] [-t float]\n" ); - fprintf( pErr, "\t converts a skew schedule into a set of forward skews 0pManGlob; - pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob ); +// dd = pNtk->pManGlob; + dd = Abc_NtkGlobalBddMan( pNtk ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + pbGlobal = (DdNode **)Vec_PtrArray( vFuncsGlob ); // get the network names pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); @@ -83,12 +91,14 @@ void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ) Abc_NtkAutoPrintOne( dd, nInputs, pbGlobal, Output, pInputNames, pOutputNames, fNaive ); // deref the PO functions - Abc_NtkFreeGlobalBdds( pNtk ); +// Abc_NtkFreeGlobalBdds( pNtk ); // stop the global BDD manager - Extra_StopManager( pNtk->pManGlob ); - pNtk->pManGlob = NULL; +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + Abc_NtkFreeGlobalBdds( pNtk, 1 ); free( pInputNames ); free( pOutputNames ); + Vec_PtrFree( vFuncsGlob ); } /**Function************************************************************* diff --git a/src/base/abci/abcClpBdd.c b/src/base/abci/abcClpBdd.c index 650f379f..ce67aff7 100644 --- a/src/base/abci/abcClpBdd.c +++ b/src/base/abci/abcClpBdd.c @@ -49,25 +49,27 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, i assert( Abc_NtkIsStrash(pNtk) ); // compute the global BDDs - if ( Abc_NtkGlobalBdds(pNtk, fBddSizeMax, 0, fReorder, fVerbose) == NULL ) + if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) return NULL; if ( fVerbose ) { - printf( "The shared BDD size is %d nodes. ", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) ); + DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); + printf( "The shared BDD size is %d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); PRT( "BDD construction time", clock() - clk ); } // create the new network pNtkNew = Abc_NtkFromGlobalBdds( pNtk ); - Abc_NtkFreeGlobalBdds( pNtk ); +// Abc_NtkFreeGlobalBdds( pNtk ); + Abc_NtkFreeGlobalBdds( pNtk, 1 ); if ( pNtkNew == NULL ) { - Cudd_Quit( pNtk->pManGlob ); - pNtk->pManGlob = NULL; +// Cudd_Quit( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; return NULL; } - Extra_StopManager( pNtk->pManGlob ); - pNtk->pManGlob = NULL; +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; // make the network minimum base Abc_NtkMinimumBase( pNtkNew ); @@ -100,8 +102,9 @@ Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode, * pNodeNew; - DdManager * dd = pNtk->pManGlob; + Abc_Obj_t * pNode, * pDriver, * pNodeNew; +// DdManager * dd = pNtk->pManGlob; + DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); int i; // start the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); @@ -112,7 +115,14 @@ Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) ); + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) ) + { + Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy ); + continue; + } +// pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) ); + pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Abc_ObjGlobalBdd(pNode) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Extra_ProgressBarStop( pProgress ); diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c index c021728a..f1dd4ab5 100644 --- a/src/base/abci/abcCut.c +++ b/src/base/abci/abcCut.c @@ -202,6 +202,7 @@ void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) ***********************************************************************/ Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) { +/* Cut_Man_t * p; Abc_Obj_t * pObj, * pNode; int i, nIters, fStatus; @@ -288,6 +289,8 @@ printf( "Converged after %d iterations.\n", nIters ); } //Abc_NtkPrintCuts( p, pNtk, 1 ); return p; +*/ + return NULL; } /**Function************************************************************* diff --git a/src/base/abci/abcDebug.c b/src/base/abci/abcDebug.c index 4d37c496..7771148e 100644 --- a/src/base/abci/abcDebug.c +++ b/src/base/abci/abcDebug.c @@ -86,7 +86,8 @@ void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ) else // no bug Abc_NtkDelete( pNtkMod ); } - printf( "Iteration %6d : Nodes = %6d. Steps = %6d. Error step = %3d. ", nIter, Abc_NtkObjNum(pNtk), nSteps, i ); + printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d. ", + nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i ); PRT( "Time", clock() - clk ); if ( i == nSteps ) // could not modify it while preserving the bug break; @@ -116,7 +117,11 @@ int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ) Abc_NtkForEachObj( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) { - if ( Abc_NodeIsConst(pFanin) ) + if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) + continue; + if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) + continue; + if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) continue; Counter++; } @@ -141,7 +146,11 @@ int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_O Abc_NtkForEachObj( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) { - if ( Abc_NodeIsConst(pFanin) ) + if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) + continue; + if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) + continue; + if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) continue; if ( Counter++ == Step ) { @@ -166,6 +175,7 @@ int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_O ***********************************************************************/ Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 ) { + extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); Abc_Ntk_t * pNtk; Abc_Obj_t * pObj, * pFanin, * pConst; // copy the network @@ -185,9 +195,9 @@ Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 Abc_NtkDeleteAll_rec( pFanin ); Abc_NtkSweep( pNtk, 0 ); - Abc_NtkCleanupSeq( pNtk, 0 ); + Abc_NtkCleanupSeq( pNtk, 0, 0, 0 ); Abc_NtkLogicToSop( pNtk, 0 ); - Abc_NtkCycleInitStateSop( pNtk, 20, 0 ); + Abc_NtkCycleInitStateSop( pNtk, 50, 0 ); return pNtk; } diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c index b38012cd..200f4eec 100644 --- a/src/base/abci/abcDsd.c +++ b/src/base/abci/abcDsd.c @@ -55,31 +55,22 @@ static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int n ***********************************************************************/ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) { + DdManager * dd; Abc_Ntk_t * pNtkNew; - assert( Abc_NtkIsStrash(pNtk) ); - - // perform FPGA mapping - if ( Abc_NtkGlobalBdds(pNtk, 10000000, 0, 1, fVerbose) == NULL ) + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + if ( dd == NULL ) return NULL; if ( fVerbose ) - printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) ); - + printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); // transform the result of mapping into a BDD network pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort ); + Extra_StopManager( dd ); if ( pNtkNew == NULL ) - { - Cudd_Quit( pNtk->pManGlob ); - pNtk->pManGlob = NULL; return NULL; - } - Extra_StopManager( pNtk->pManGlob ); - pNtk->pManGlob = NULL; - + // copy EXDC network if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - - // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkDsdGlobal: The network check has failed.\n" ); @@ -102,26 +93,25 @@ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool ***********************************************************************/ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) { - DdManager * dd = pNtk->pManGlob; + char ** ppNamesCi, ** ppNamesCo; + Vec_Ptr_t * vFuncsGlob; Dsd_Manager_t * pManDsd; Abc_Ntk_t * pNtkNew; - DdNode * bFunc; - char ** ppNamesCi, ** ppNamesCo; + DdManager * dd; Abc_Obj_t * pObj; int i; // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) - { - bFunc = Vec_PtrEntry(pNtk->vFuncsGlob, i); - Vec_PtrWriteEntry(pNtk->vFuncsGlob, i, Cudd_NotCond(bFunc, Abc_ObjFaninC0(pObj)) ); - } + Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) ); // perform the decomposition - assert( Vec_PtrSize(pNtk->vFuncsGlob) == Abc_NtkCoNum(pNtk) ); + dd = Abc_NtkGlobalBddMan(pNtk); pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose ); - Dsd_Decompose( pManDsd, (DdNode **)pNtk->vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) ); - Abc_NtkFreeGlobalBdds( pNtk ); + Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) ); + Vec_PtrFree( vFuncsGlob ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); if ( pManDsd == NULL ) { Cudd_Quit( dd ); @@ -138,7 +128,6 @@ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bo Abc_NtkFinalize( pNtk, pNtkNew ); // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - if ( fPrint ) { ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 ); diff --git a/src/base/abci/abcFpgaFast.c b/src/base/abci/abcFpgaFast.c index 3ad29291..356b855e 100644 --- a/src/base/abci/abcFpgaFast.c +++ b/src/base/abci/abcFpgaFast.c @@ -118,7 +118,7 @@ Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) // clone the node pObj = Abc_NtkCloneObj( pObjAbc ); // set complemented functions - pObj->pData = Aig_Not( pObjAbc->pData ); + pObj->pData = Hop_Not( pObjAbc->pData ); // return the new node pObjAbc = pObj; } @@ -172,9 +172,9 @@ Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj Ivy_ManForEachNodeVec( pMan, vNodes, pNodeIvy, i ) { if ( i < Vec_IntSize(vSupp) ) - pNodeIvy->pEquiv = (Ivy_Obj_t *)Aig_IthVar( pNtkNew->pManFunc, i ); + pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_IthVar( pNtkNew->pManFunc, i ); else - pNodeIvy->pEquiv = (Ivy_Obj_t *)Aig_And( pNtkNew->pManFunc, (Aig_Obj_t *)Ivy_ObjChild0Equiv(pNodeIvy), (Aig_Obj_t *)Ivy_ObjChild1Equiv(pNodeIvy) ); + pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_And( pNtkNew->pManFunc, (Hop_Obj_t *)Ivy_ObjChild0Equiv(pNodeIvy), (Hop_Obj_t *)Ivy_ObjChild1Equiv(pNodeIvy) ); } // set the local function pObjAbc->pData = (Abc_Obj_t *)pObjIvy->pEquiv; diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c new file mode 100644 index 00000000..6b3e0e7c --- /dev/null +++ b/src/base/abci/abcIf.c @@ -0,0 +1,287 @@ +/**CFile**************************************************************** + + FileName [abcIf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); +static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj ); +static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Cut_t * pCut ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) +{ + Abc_Ntk_t * pNtkNew; + If_Man_t * pIfMan; + + assert( Abc_NtkIsStrash(pNtk) ); + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing FPGA mapping with choices.\n" ); + + // perform FPGA mapping + pIfMan = Abc_NtkToIf( pNtk, pPars ); + if ( pIfMan == NULL ) + return NULL; + if ( !If_ManPerformMapping( pIfMan ) ) + { + If_ManStop( pIfMan ); + return NULL; + } + + // transform the result of mapping into a BDD network + pNtkNew = Abc_NtkFromIf( pIfMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + If_ManStop( pIfMan ); + + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkIf: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) +{ + ProgressBar * pProgress; + If_Man_t * pIfMan; + Abc_Obj_t * pNode, * pFanin, * pPrev; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + + // start the mapping manager and set its parameters + pIfMan = If_ManStart( pPars ); + + // create PIs and remember them in the old nodes + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan ); + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)If_ManCreatePi( pIfMan ); + + // load the AIG into the mapper + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); + Abc_AigForEachAnd( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // add the node to the mapper + pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan, + (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode), + (If_Obj_t *)Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ); + // set up the choice node + if ( Abc_AigNodeIsChoice( pNode ) ) + for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) + If_ObjSetChoice( (If_Obj_t *)pPrev->pCopy, (If_Obj_t *)pFanin->pCopy ); + } + Extra_ProgressBarStop( pProgress ); + + // set the primary outputs without copying the phase + Abc_NtkForEachCo( pNtk, pNode, i ) + If_ManCreatePo( pIfMan, (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); + return pIfMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [Assuming the copy field of the mapped nodes are NULL.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + int i, nDupGates; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); + // prepare the mapping manager + If_ManCleanNodeCopy( pIfMan ); + If_ManCleanCutData( pIfMan ); + // make the mapper point to the new network + If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) ); + Abc_NtkForEachCi( pNtk, pNode, i ) + If_ObjSetCopy( If_ManPi(pIfMan, i), pNode->pCopy ); + // process the nodes in topological order + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManPo(pIfMan, i)) ); + pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManPo(pIfMan, i)) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + // remove the constant node if not used + pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) ); + if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) + Abc_NtkDeleteObj( pNodeNew ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && If_ManReadVerbose(pIfMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derive one node after FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj ) +{ + Abc_Obj_t * pNodeNew; + If_Cut_t * pCutBest; + If_Obj_t * pIfLeaf; + int i; + // return if the result if known + pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj ); + if ( pNodeNew ) + return pNodeNew; + assert( pIfObj->Type == IF_AND ); + // get the parameters of the best cut + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pCutBest = If_ObjCutBest( pIfObj ); + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) + Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf) ); + // derive the function of this node + pNodeNew->pData = Abc_NodeIfToHop( pNtkNew->pManFunc, pIfMan, pCutBest ); + If_ObjSetCopy( pIfObj, pNodeNew ); + return pNodeNew; +} + + +/**Function************************************************************* + + Synopsis [Recursively derives the truth table for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Ptr_t * vVisited ) +{ + Hop_Obj_t * gFunc, * gFunc0, * gFunc1; + // if the cut is visited, return the result + if ( If_CutData(pCut) ) + return If_CutData(pCut); + // compute the functions of the children + gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pCut->pOne, vVisited ); + gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pCut->pTwo, vVisited ); + // get the function of the cut + gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pCut->fCompl0), Hop_NotCond(gFunc1, pCut->fCompl1) ); + gFunc = Hop_NotCond( gFunc, pCut->Phase ); + assert( If_CutData(pCut) == NULL ); + If_CutSetData( pCut, gFunc ); + // add this cut to the visited list + Vec_PtrPush( vVisited, pCut ); + return gFunc; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Cut_t * pCut ) +{ + Hop_Obj_t * gFunc; + If_Obj_t * pLeaf; + int i; + assert( pCut->nLeaves > 1 ); + // set the leaf variables + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetData( If_ObjCutTriv(pLeaf), Hop_IthVar(pHopMan, i) ); + // recursively compute the function while collecting visited cuts + Vec_PtrClear( pIfMan->vTemp ); + gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pCut, pIfMan->vTemp ); +// printf( "%d ", Vec_PtrSize(p->vTemp) ); + // clean the cuts + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetData( If_ObjCutTriv(pLeaf), NULL ); + Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i ) + If_CutSetData( pCut, NULL ); + return gFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c index 30ed21cf..be8b8ec5 100644 --- a/src/base/abci/abcIvy.c +++ b/src/base/abci/abcIvy.c @@ -53,6 +53,8 @@ static inline Abc_Obj_t * Abc_ObjFanin1Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { static Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ); +extern int timeRetime; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -72,6 +74,7 @@ Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ) { Ivy_Man_t * pMan; int fCleanup = 1; +//timeRetime = clock(); assert( !Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkIsSeq(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) @@ -107,6 +110,7 @@ Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ) Vec_IntFree( vInit ); // Ivy_ManPrintStats( pMan ); } +//timeRetime = clock() - timeRetime; return pMan; } @@ -184,17 +188,22 @@ Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int { Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan; - int i; +// int i; pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); if ( pMan == NULL ) return NULL; +//timeRetime = clock(); Ivy_ManHaigStart( pMan, fVerbose ); // Ivy_ManRewriteSeq( pMan, 0, 0 ); - for ( i = 0; i < nIters; i++ ) - Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 ); - Ivy_ManHaigPostprocess( pMan, fVerbose ); +// for ( i = 0; i < nIters; i++ ) +// Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 ); + Ivy_ManRewriteSeq( pMan, 0, 0 ); + Ivy_ManRewriteSeq( pMan, 1, 0 ); +//printf( "Haig size = %d.\n", Ivy_ManNodeNum(pMan->pHaig) ); +// Ivy_ManHaigPostprocess( pMan, fVerbose ); +//timeRetime = clock() - timeRetime; // write working AIG into the current network // pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); @@ -246,7 +255,9 @@ Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroC pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; +//timeRetime = clock(); Ivy_ManRewritePre( pMan, fUpdateLevel, fUseZeroCost, fVerbose ); +//timeRetime = clock() - timeRetime; pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); Ivy_ManStop( pMan ); return pNtkAig; @@ -270,7 +281,9 @@ Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbo pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); if ( pMan == NULL ) return NULL; +//timeRetime = clock(); Ivy_ManRewriteSeq( pMan, fUseZeroCost, fVerbose ); +//timeRetime = clock() - timeRetime; // Ivy_ManRewriteSeq( pMan, 1, 0 ); // Ivy_ManRewriteSeq( pMan, 1, 0 ); pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); diff --git a/src/base/abci/abcLut.c b/src/base/abci/abcLut.c index 61b1ce78..afa76cc8 100644 --- a/src/base/abci/abcLut.c +++ b/src/base/abci/abcLut.c @@ -104,7 +104,7 @@ int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int Abc_NtkForEachCi( pNtk, pObj, i ) pObj->Level = 0; -//Abc_NtkGetLevelNum( pNtk ); +//Abc_NtkLevel( pNtk ); // start the managers pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 ); diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c index 014eafd3..dc90bee0 100644 --- a/src/base/abci/abcMini.c +++ b/src/base/abci/abcMini.c @@ -24,8 +24,8 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static Aig_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtk ); -static Abc_Ntk_t * Abc_NtkFromAig( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ); +static Hop_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkFromAig( Abc_Ntk_t * pNtkOld, Hop_Man_t * pMan ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -45,29 +45,29 @@ static Abc_Ntk_t * Abc_NtkFromAig( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ); Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkAig; - Aig_Man_t * pMan, * pTemp; + Hop_Man_t * pMan, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); // convert to the AIG manager pMan = Abc_NtkToAig( pNtk ); if ( pMan == NULL ) return NULL; - if ( !Aig_ManCheck( pMan ) ) + if ( !Hop_ManCheck( pMan ) ) { printf( "AIG check has failed.\n" ); - Aig_ManStop( pMan ); + Hop_ManStop( pMan ); return NULL; } // perform balance - Aig_ManPrintStats( pMan ); -// Aig_ManDumpBlif( pMan, "aig_temp.blif" ); - pMan = Aig_ManBalance( pTemp = pMan, 1 ); - Aig_ManStop( pTemp ); - Aig_ManPrintStats( pMan ); + Hop_ManPrintStats( pMan ); +// Hop_ManDumpBlif( pMan, "aig_temp.blif" ); + pMan = Hop_ManBalance( pTemp = pMan, 1 ); + Hop_ManStop( pTemp ); + Hop_ManPrintStats( pMan ); // convert from the AIG manager pNtkAig = Abc_NtkFromAig( pNtk, pMan ); if ( pNtkAig == NULL ) return NULL; - Aig_ManStop( pMan ); + Hop_ManStop( pMan ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkAig ) ) { @@ -89,24 +89,24 @@ Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Aig_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtk ) +Hop_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtk ) { - Aig_Man_t * pMan; + Hop_Man_t * pMan; Abc_Obj_t * pObj; int i; // create the manager - pMan = Aig_ManStart(); + pMan = Hop_ManStart(); // transfer the pointers to the basic nodes - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan); Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreatePi(pMan); + pObj->pCopy = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); // perform the conversion of the internal nodes (assumes DFS ordering) Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) ); + pObj->pCopy = (Abc_Obj_t *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) ); // create the POs Abc_NtkForEachCo( pNtk, pObj, i ) - Aig_ObjCreatePo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) ); - Aig_ManCleanup( pMan ); + Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) ); + Hop_ManCleanup( pMan ); return pMan; } @@ -121,26 +121,26 @@ Aig_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromAig( Abc_Ntk_t * pNtk, Aig_Man_t * pMan ) +Abc_Ntk_t * Abc_NtkFromAig( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; - Aig_Obj_t * pObj; + Hop_Obj_t * pObj; int i; // perform strashing pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // transfer the pointers to the basic nodes - Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); - Aig_ManForEachPi( pMan, pObj, i ) + Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Hop_ManForEachPi( pMan, pObj, i ) pObj->pData = Abc_NtkCi(pNtkNew, i); // rebuild the AIG - vNodes = Aig_ManDfs( pMan ); + vNodes = Hop_ManDfs( pMan ); Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // connect the PO nodes - Aig_ManForEachPo( pMan, pObj, i ) - Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + Hop_ManForEachPo( pMan, pObj, i ) + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkFromAig(): Network check has failed.\n" ); return pNtkNew; diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index f99f7bce..bd035eb0 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -27,7 +27,7 @@ static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node ); -static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, ProgressBar * pProgress, int * pCounter, int fVerbose ); +static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -243,85 +243,63 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * SeeAlso [] ***********************************************************************/ -DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly, int fReorder, int fVerbose ) +DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) { ProgressBar * pProgress; - Vec_Ptr_t * vFuncsGlob; Abc_Obj_t * pObj, * pFanin; - DdNode * bFunc; + Vec_Att_t * pAttMan; DdManager * dd; + DdNode * bFunc; int i, k, Counter; // remove dangling nodes Abc_AigCleanup( pNtk->pManFunc ); // start the manager - assert( pNtk->pManGlob == NULL ); + assert( Abc_NtkGlobalBdds(pNtk) == NULL ); dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, dd, Extra_StopManager, NULL, Cudd_RecursiveDeref ); + Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD, pAttMan ); + // set reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - // clean storage for local BDDs - Abc_NtkCleanCopy( pNtk ); - // set the elementary variables - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - { - pObj->pCopy = (Abc_Obj_t *)dd->vars[i]; - Cudd_Ref( dd->vars[i] ); - } // assign the constant node BDD pObj = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pObj) > 0 ) { - pObj->pCopy = (Abc_Obj_t *)dd->one; + Abc_ObjSetGlobalBdd( pObj, dd->one ); Cudd_Ref( dd->one ); } + // set the elementary variables + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + { + Abc_ObjSetGlobalBdd( pObj, dd->vars[i] ); + Cudd_Ref( dd->vars[i] ); + } // collect the global functions of the COs Counter = 0; - vFuncsGlob = Vec_PtrAlloc( 100 ); - if ( fLatchOnly ) + // construct the BDDs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) { - // construct the BDDs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); - Abc_NtkForEachLatchInput( pNtk, pObj, i ) + bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); + if ( bFunc == NULL ) { - bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, pProgress, &Counter, fVerbose ); - if ( bFunc == NULL ) - { - if ( fVerbose ) - printf( "Constructing global BDDs is aborted.\n" ); - Vec_PtrFree( vFuncsGlob ); - Cudd_Quit( dd ); - return NULL; - } - bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); - Vec_PtrPush( vFuncsGlob, bFunc ); - } - Extra_ProgressBarStop( pProgress ); - } - else - { - // construct the BDDs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, pProgress, &Counter, fVerbose ); - if ( bFunc == NULL ) - { - if ( fVerbose ) - printf( "Constructing global BDDs is aborted.\n" ); - Vec_PtrFree( vFuncsGlob ); - Cudd_Quit( dd ); - return NULL; - } - bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); - Vec_PtrPush( vFuncsGlob, bFunc ); + if ( fVerbose ) + printf( "Constructing global BDDs is aborted.\n" ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + Cudd_Quit( dd ); + return NULL; } - Extra_ProgressBarStop( pProgress ); + bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); + Abc_ObjSetGlobalBdd( pObj, bFunc ); } + Extra_ProgressBarStop( pProgress ); + /* // derefence the intermediate BDDs Abc_NtkForEachNode( pNtk, pObj, i ) @@ -336,9 +314,9 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly Abc_NtkForEachObj( pNtk, pObj, i ) { if ( pObj->pCopy != NULL ) - printf( "Abc_NtkGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id ); + printf( "Abc_NtkBuildGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id ); if ( pObj->vFanouts.nSize > 0 ) - printf( "Abc_NtkGlobalBdds() error: Node %d has refs assigned\n", pObj->Id ); + printf( "Abc_NtkBuildGlobalBdds() error: Node %d has refs assigned\n", pObj->Id ); } */ // reset references @@ -353,8 +331,6 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); Cudd_AutodynDisable( dd ); } - pNtk->pManGlob = dd; - pNtk->vFuncsGlob = vFuncsGlob; // Cudd_PrintInfo( dd, stdout ); return dd; } @@ -370,9 +346,10 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly SeeAlso [] ***********************************************************************/ -DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, ProgressBar * pProgress, int * pCounter, int fVerbose ) +DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) { DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC; + int fDetectMuxes = 1; assert( !Abc_ObjIsComplement(pNode) ); if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) { @@ -383,14 +360,14 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSize return NULL; } // if the result is available return - if ( pNode->pCopy == NULL ) + if ( Abc_ObjGlobalBdd(pNode) == NULL ) { Abc_Obj_t * pNodeC, * pNode0, * pNode1; pNode0 = Abc_ObjFanin0(pNode); pNode1 = Abc_ObjFanin1(pNode); // check for the special case when it is MUX/EXOR -// if ( 0 ) - if ( pNode0->pCopy == NULL && pNode1->pCopy == NULL && + if ( fDetectMuxes && + Abc_ObjGlobalBdd(pNode0) == NULL && Abc_ObjGlobalBdd(pNode1) == NULL && Abc_ObjIsNode(pNode0) && Abc_ObjFanoutNum(pNode0) == 1 && Abc_ObjIsNode(pNode1) && Abc_ObjFanoutNum(pNode1) == 1 && Abc_NodeIsMuxType(pNode) ) @@ -405,15 +382,15 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSize pNodeC->vFanouts.nSize--; // compute the result for all branches - bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, pProgress, pCounter, fVerbose ); + bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFuncC == NULL ) return NULL; Cudd_Ref( bFuncC ); - bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, pProgress, pCounter, fVerbose ); + bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc0 == NULL ) return NULL; Cudd_Ref( bFunc0 ); - bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, pProgress, pCounter, fVerbose ); + bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc1 == NULL ) return NULL; Cudd_Ref( bFunc1 ); @@ -432,11 +409,11 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSize else { // compute the result for both branches - bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, pProgress, pCounter, fVerbose ); + bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc0 == NULL ) return NULL; Cudd_Ref( bFunc0 ); - bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, pProgress, pCounter, fVerbose ); + bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc1 == NULL ) return NULL; Cudd_Ref( bFunc1 ); @@ -450,26 +427,26 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSize (*pCounter)++; } // set the result - assert( pNode->pCopy == NULL ); - pNode->pCopy = (Abc_Obj_t *)bFunc; + assert( Abc_ObjGlobalBdd(pNode) == NULL ); + Abc_ObjSetGlobalBdd( pNode, bFunc ); // increment the progress bar if ( pProgress ) Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); } // prepare the return value - bFunc = (DdNode *)pNode->pCopy; + bFunc = Abc_ObjGlobalBdd(pNode); // dereference BDD at the node - if ( --pNode->vFanouts.nSize == 0 ) + if ( --pNode->vFanouts.nSize == 0 && fDropInternal ) { Cudd_Deref( bFunc ); - pNode->pCopy = NULL; + Abc_ObjSetGlobalBdd( pNode, NULL ); } return bFunc; } /**Function************************************************************* - Synopsis [Dereferences global BDDs of the network.] + Synopsis [Frees the global BDDs of the network.] Description [] @@ -478,16 +455,9 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSize SeeAlso [] ***********************************************************************/ -void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk ) -{ - DdNode * bFunc; - int i; - assert( pNtk->pManGlob ); - assert( pNtk->vFuncsGlob ); - Vec_PtrForEachEntry( pNtk->vFuncsGlob, bFunc, i ) - Cudd_RecursiveDeref( pNtk->pManGlob, bFunc ); - Vec_PtrFree( pNtk->vFuncsGlob ); - pNtk->vFuncsGlob = NULL; +DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ) +{ + return Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, fFreeMan ); } /**Function************************************************************* @@ -503,6 +473,7 @@ void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk ) ***********************************************************************/ double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) { + /* Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pNodeR; DdManager * dd; @@ -521,7 +492,7 @@ double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) Vec_PtrForEachEntry( vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)dd->vars[i]; // build the BDD of the cone - bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, NULL, NULL, 1 ); Cudd_Ref( bFunc ); + bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, 1, NULL, NULL, 1 ); Cudd_Ref( bFunc ); bFunc = Cudd_NotCond( bFunc, pNode != pNodeR ); // count minterms Result = Cudd_CountMinterm( dd, bFunc, dd->size ); @@ -533,6 +504,8 @@ double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) Cudd_Quit( dd ); Vec_PtrFree( vNodes ); return Result; + */ + return 0.0; } diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index bdca4a8e..40bf30a6 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -113,9 +113,9 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) } if ( Abc_NtkIsStrash(pNtk) ) - fprintf( pFile, " lev = %3d", Abc_AigGetLevelNum(pNtk) ); + fprintf( pFile, " lev = %3d", Abc_AigLevel(pNtk) ); else if ( !Abc_NtkIsSeq(pNtk) ) - fprintf( pFile, " lev = %3d", Abc_NtkGetLevelNum(pNtk) ); + fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) ); fprintf( pFile, "\n" ); // print the statistic into a file @@ -126,7 +126,7 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) fprintf( pTable, "%s ", pNtk->pName ); fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); - fprintf( pTable, "%d ", Abc_AigGetLevelNum(pNtk) ); + fprintf( pTable, "%d ", Abc_AigLevel(pNtk) ); fprintf( pTable, "\n" ); fclose( pTable ); } @@ -150,7 +150,7 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) FILE * pTable; pTable = fopen( "fpga/fpga_stats.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%d ", Abc_NtkGetLevelNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) ); fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) ); @@ -159,23 +159,41 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) } */ -/* + // print the statistic into a file { static int Counter = 0; extern int timeRetime; FILE * pTable; Counter++; - pTable = fopen( "sap/stats_retime.txt", "a+" ); + pTable = fopen( "a/ret__stats.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); - fprintf( pTable, "%d ", Abc_NtkGetLevelNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); if ( Counter % 4 == 0 ) fprintf( pTable, "\n" ); fclose( pTable ); } + +/* + // print the statistic into a file + { + static int Counter = 0; + extern int timeRetime; + FILE * pTable; + Counter++; + pTable = fopen( "d/stats.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pName ); +// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } */ /* @@ -214,7 +232,8 @@ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ) fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, " %s", Abc_ObjName(pObj) ); + fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj), + Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); fprintf( pFile, "\n" ); } @@ -500,7 +519,7 @@ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListN if ( fListNodes ) { int nLevels; - nLevels = Abc_NtkGetLevelNum(pNtk); + nLevels = Abc_NtkLevel(pNtk); printf( "Nodes by level:\n" ); for ( i = 0; i <= nLevels; i++ ) { @@ -553,7 +572,7 @@ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListN int nOutsSum, nOutsTotal; if ( !Abc_NtkIsStrash(pNtk) ) - Abc_NtkGetLevelNum(pNtk); + Abc_NtkLevel(pNtk); LevelMax = 0; Abc_NtkForEachCo( pNtk, pNode, i ) @@ -838,41 +857,6 @@ void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk ) } } -/**Function************************************************************* - - Synopsis [Prints information about the clock skew schedule.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll ) { - - Abc_Obj_t * pObj; - int i; - int nNonZero = 0; - float skew, sum = 0.0, avg; - - if (fPrintAll) fprintf( pFile, "Full Clock Skew Schedule:\n\tGlobal Skew = %.2f\n", pNtk->globalSkew ); - - Abc_NtkForEachLatch( pNtk, pObj, i ) { - skew = Abc_NtkGetLatSkew( pNtk, i ); - if ( skew != 0.0 ) { - nNonZero++; - sum += ABS( skew ); - } - if (fPrintAll) fprintf( pFile, "\tLatch %d (Id = %d) \t Endpoint Skew = %.2f\n", i, pObj->Id, skew); - } - - avg = sum / Abc_NtkLatchNum( pNtk ); - - fprintf( pFile, "Endpoint Skews : Total |Skew| = %.2f\t Avg |Skew| = %.2f\t Non-Zero Skews = %d\n", - sum, avg, nNonZero ); -} - /**Function************************************************************* Synopsis [Prints information about the object.] @@ -942,6 +926,12 @@ void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ) Abc_ObjForEachFanin( pObj, pFanin, i ) fprintf( pFile, "%d ", pFanin->Id ); fprintf( pFile, ") " ); +/* + fprintf( pFile, " Fanouts ( " ); + Abc_ObjForEachFanout( pObj, pFanin, i ) + fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' ); + fprintf( pFile, ") " ); +*/ // print the logic function if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) ) fprintf( pFile, " %s", pObj->pData ); diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c index c9e5bfd7..fcd44d30 100644 --- a/src/base/abci/abcProve.c +++ b/src/base/abci/abcProve.c @@ -310,7 +310,7 @@ void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose if ( !fVerbose ) return; printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), - Abc_NtkIsStrash(pNtk)? Abc_AigGetLevelNum(pNtk) : Abc_NtkGetLevelNum(pNtk) ); + Abc_NtkIsStrash(pNtk)? Abc_AigLevel(pNtk) : Abc_NtkLevel(pNtk) ); PRT( pString, clock() - clk ); } diff --git a/src/base/abci/abcRefactor.c b/src/base/abci/abcRefactor.c index 3d301cd6..0328d8d3 100644 --- a/src/base/abci/abcRefactor.c +++ b/src/base/abci/abcRefactor.c @@ -156,7 +156,7 @@ pManRef->timeTotal = clock() - clkStart; if ( fUpdateLevel ) Abc_NtkStopReverseLevels( pNtk ); else - Abc_NtkGetLevelNum( pNtk ); + Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { diff --git a/src/base/abci/abcRestruct.c b/src/base/abci/abcRestruct.c index 9dc84999..2d4f50fb 100644 --- a/src/base/abci/abcRestruct.c +++ b/src/base/abci/abcRestruct.c @@ -183,7 +183,7 @@ pManRst->timeTotal = clock() - clkStart; if ( fUpdateLevel ) Abc_NtkStopReverseLevels( pNtk ); else - Abc_NtkGetLevelNum( pNtk ); + Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c index 9fcc6979..19e6c50a 100644 --- a/src/base/abci/abcResub.c +++ b/src/base/abci/abcResub.c @@ -232,7 +232,7 @@ pManRes->timeTotal = clock() - clkStart; if ( fUpdateLevel ) Abc_NtkStopReverseLevels( pNtk ); else - Abc_NtkGetLevelNum( pNtk ); + Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { diff --git a/src/base/abci/abcRewrite.c b/src/base/abci/abcRewrite.c index 2af10271..151b5256 100644 --- a/src/base/abci/abcRewrite.c +++ b/src/base/abci/abcRewrite.c @@ -158,7 +158,7 @@ Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart ); if ( fUpdateLevel ) Abc_NtkStopReverseLevels( pNtk ); else - Abc_NtkGetLevelNum( pNtk ); + Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { diff --git a/src/base/abci/abcRr.c b/src/base/abci/abcRr.c index 63beac6c..b9fab415 100644 --- a/src/base/abci/abcRr.c +++ b/src/base/abci/abcRr.c @@ -104,7 +104,7 @@ int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFa p->nFaninLevels = nFaninLevels; p->nFanoutLevels = nFanoutLevels; p->nNodesOld = Abc_NtkNodeNum(pNtk); - p->nLevelsOld = Abc_AigGetLevelNum(pNtk); + p->nLevelsOld = Abc_AigLevel(pNtk); // remember latch values // Abc_NtkForEachLatch( pNtk, pNode, i ) // pNode->pNext = pNode->pData; @@ -220,7 +220,7 @@ int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFa // pNode->pData = pNode->pNext, pNode->pNext = NULL; // put the nodes into the DFS order and reassign their IDs Abc_NtkReassignIds( pNtk ); - Abc_NtkGetLevelNum( pNtk ); + Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { @@ -298,7 +298,7 @@ void Abc_RRManPrintStats( Abc_RRMan_t * p ) printf( "Edges tried = %6d.\n", p->nEdgesTried ); printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried ); printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio ); - printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigGetLevelNum(p->pNtk) ); + printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) ); PRT( "Windowing ", p->timeWindow ); PRT( "Miter ", p->timeMiter ); PRT( " Construct ", p->timeMiter - p->timeProve ); diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c index 8d5dd2a7..55498288 100644 --- a/src/base/abci/abcSat.c +++ b/src/base/abci/abcSat.c @@ -458,7 +458,7 @@ int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk, int fJFront ) int i, k, fUseMuxes = 1; int clk1 = clock(), clk; int fOrderCiVarsFirst = 0; - int nLevelsMax = Abc_AigGetLevelNum(pNtk); + int nLevelsMax = Abc_AigLevel(pNtk); int RetValue = 0; assert( Abc_NtkIsStrash(pNtk) ); diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c index e8dc9793..a3719b10 100644 --- a/src/base/abci/abcStrash.c +++ b/src/base/abci/abcStrash.c @@ -1,6 +1,6 @@ /**CFile**************************************************************** - FileName [aigStrash.c] + FileName [abcStrash.c] SystemName [ABC: Logic synthesis and verification system.] @@ -14,7 +14,7 @@ Date [Ver. 1.0. Started - June 20, 2005.] - Revision [$Id: aigStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ @@ -46,10 +46,12 @@ static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, bool fA ***********************************************************************/ Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ) { + extern int timeRetime; Abc_Ntk_t * pNtkAig; Abc_Obj_t * pObj; - int i, nNodes; + int i, nNodes, RetValue; assert( Abc_NtkIsStrash(pNtk) ); +//timeRetime = clock(); // print warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); @@ -58,7 +60,7 @@ Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ) // restrash the nodes (assuming a topological order of the old network) Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // finalize the network + //l finalize the network Abc_NtkFinalize( pNtk, pNtkAig ); // print warning about self-feed latches // if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) @@ -76,6 +78,9 @@ Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ) Abc_NtkDelete( pNtkAig ); return NULL; } +//timeRetime = clock() - timeRetime; + if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) + printf( "Modified %d self-feeding latches. The result will not verify.\n", RetValue ); return pNtkAig; } @@ -106,7 +111,7 @@ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup ) return NULL; } // perform strashing - Abc_NtkCleanCopy( pNtk ); +// Abc_NtkCleanCopy( pNtk ); pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes ); Abc_NtkFinalize( pNtk, pNtkAig ); @@ -205,13 +210,17 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ) ***********************************************************************/ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, bool fAllNodes ) { + extern Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ); ProgressBar * pProgress; Vec_Ptr_t * vNodes; Abc_Obj_t * pNodeOld; - int i; + int i, clk = clock(); assert( Abc_NtkIsLogic(pNtkOld) ); assert( Abc_NtkIsStrash(pNtkNew) ); - vNodes = Abc_NtkDfs( pNtkOld, fAllNodes ); +// vNodes = Abc_NtkDfs( pNtkOld, fAllNodes ); + vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes ); +//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) ); +//PRT( "Time", clock() - clk ); pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( vNodes, pNodeOld, i ) { @@ -233,16 +242,16 @@ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, bool fAllNo SeeAlso [] ***********************************************************************/ -void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Aig_Obj_t * pObj ) +void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj ) { - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; - Abc_NodeStrash_rec( pMan, Aig_ObjFanin0(pObj) ); - Abc_NodeStrash_rec( pMan, Aig_ObjFanin1(pObj) ); - pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); + Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) ); + Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) ); + pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* @@ -258,8 +267,8 @@ void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Aig_Obj_t * pObj ) ***********************************************************************/ Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ) { - Aig_Man_t * pMan; - Aig_Obj_t * pRoot; + Hop_Man_t * pMan; + Hop_Obj_t * pRoot; Abc_Obj_t * pFanin; int i; assert( Abc_ObjIsNode(pNodeOld) ); @@ -269,15 +278,15 @@ Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ) pRoot = pNodeOld->pData; // check the constant case if ( Abc_NodeIsConst(pNodeOld) ) - return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Aig_IsComplement(pRoot) ); + return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) ); // set elementary variables Abc_ObjForEachFanin( pNodeOld, pFanin, i ) - Aig_IthVar(pMan, i)->pData = pFanin->pCopy; + Hop_IthVar(pMan, i)->pData = pFanin->pCopy; // strash the AIG of this node - Abc_NodeStrash_rec( pNtkNew->pManFunc, Aig_Regular(pRoot) ); - Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); + Abc_NodeStrash_rec( pNtkNew->pManFunc, Hop_Regular(pRoot) ); + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); // return the final node - return Abc_ObjNotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); + return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } @@ -328,7 +337,7 @@ Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkCoNum(pNtk) == 1 ); // get the cutoff level - LevelCut = ABC_MAX( 0, Abc_AigGetLevelNum(pNtk) - nLevels ); + LevelCut = ABC_MAX( 0, Abc_AigLevel(pNtk) - nLevels ); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); diff --git a/src/base/abci/abcSweep.c b/src/base/abci/abcSweep.c index db926d17..1b63b23c 100644 --- a/src/base/abci/abcSweep.c +++ b/src/base/abci/abcSweep.c @@ -79,7 +79,7 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose ) if ( fUseTrick ) { extern void * Abc_FrameReadLibGen(); - Aig_ManStop( pNtk->pManFunc ); + Hop_ManStop( pNtk->pManFunc ); pNtk->pManFunc = Abc_FrameReadLibGen(); pNtk->ntkFunc = ABC_FUNC_MAP; Abc_NtkForEachNode( pNtk, pObj, i ) @@ -269,7 +269,7 @@ void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, if ( stmm_count(tEquiv) == 0 ) return; // assign levels to the nodes of the network - Abc_NtkGetLevelNum( pNtk ); + Abc_NtkLevel( pNtk ); // merge nodes in the classes if ( Abc_NtkHasMapping( pNtk ) ) { @@ -897,7 +897,7 @@ int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fVerbose ) +int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ) { Vec_Ptr_t * vNodes; int Counter; @@ -910,20 +910,26 @@ int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fVerbose ) if ( fVerbose ) printf( "Cleanup removed %4d dangling objects.\n", Counter ); // check if some of the latches can be removed - Counter = Abc_NtkLatchSweep( pNtk ); - if ( fVerbose ) - printf( "Cleanup removed %4d redundant latches.\n", Counter ); + if ( fLatchSweep ) + { + Counter = Abc_NtkLatchSweep( pNtk ); + if ( fVerbose ) + printf( "Cleanup removed %4d redundant latches.\n", Counter ); + } // detect the autonomous components - vNodes = Abc_NtkDfsSeqReverse( pNtk ); - Vec_PtrFree( vNodes ); - // replace them by PIs - Counter = Abc_NtkReplaceAutonomousLogic( pNtk ); - if ( fVerbose ) - printf( "Cleanup added %4d additional PIs.\n", Counter ); - // remove the non-marked nodes - Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); - if ( fVerbose ) - printf( "Cleanup removed %4d autonomous objects.\n", Counter ); + if ( fAutoSweep ) + { + vNodes = Abc_NtkDfsSeqReverse( pNtk ); + Vec_PtrFree( vNodes ); + // replace them by PIs + Counter = Abc_NtkReplaceAutonomousLogic( pNtk ); + if ( fVerbose ) + printf( "Cleanup added %4d additional PIs.\n", Counter ); + // remove the non-marked nodes + Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); + if ( fVerbose ) + printf( "Cleanup removed %4d autonomous objects.\n", Counter ); + } // check if ( !Abc_NtkCheck( pNtk ) ) printf( "Abc_NtkCleanupSeq: The network check has failed.\n" ); diff --git a/src/base/abci/abcSymm.c b/src/base/abci/abcSymm.c index fad3bd92..d3fcb7c9 100644 --- a/src/base/abci/abcSymm.c +++ b/src/base/abci/abcSymm.c @@ -88,7 +88,7 @@ void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) // compute the global functions clk = clock(); - dd = Abc_NtkGlobalBdds( pNtk, 10000000, 0, 1, fVerbose ); + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); Cudd_AutodynDisable( dd ); Cudd_zddVarsFromBddVars( dd, 2 ); clkBdd = clock() - clk; @@ -97,9 +97,10 @@ clk = clock(); Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose ); clkSym = clock() - clk; // undo the global functions - Abc_NtkFreeGlobalBdds( pNtk ); - Extra_StopManager( dd ); - pNtk->pManGlob = NULL; +// Abc_NtkFreeGlobalBdds( pNtk ); +// Extra_StopManager( dd ); +// pNtk->pManGlob = NULL; + Abc_NtkFreeGlobalBdds( pNtk, 1 ); PRT( "Constructing BDDs", clkBdd ); PRT( "Computing symms ", clkSym ); @@ -129,7 +130,8 @@ void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVer // compute symmetry info for each PO Abc_NtkForEachCo( pNtk, pNode, i ) { - bFunc = pNtk->vFuncsGlob->pArray[i]; +// bFunc = pNtk->vFuncsGlob->pArray[i]; + bFunc = Abc_ObjGlobalBdd( pNode ); nSupps += Cudd_SupportSize( dd, bFunc ); if ( Cudd_IsConstant(bFunc) ) continue; diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c index af06436f..93fa3fa5 100644 --- a/src/base/abci/abcTiming.c +++ b/src/base/abci/abcTiming.c @@ -648,8 +648,8 @@ void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk ) int i, k, nLevelsCur; // assert( Abc_NtkIsStrash(pNtk) ); // remember the maximum number of direct levels -// pNtk->LevelMax = Abc_AigGetLevelNum(pNtk); - pNtk->LevelMax = Abc_NtkGetLevelNum(pNtk); +// pNtk->LevelMax = Abc_AigLevel(pNtk); + pNtk->LevelMax = Abc_NtkLevel(pNtk); // start the reverse levels pNtk->vLevelsR = Vec_IntAlloc( 0 ); Vec_IntFill( pNtk->vLevelsR, Abc_NtkObjNumMax(pNtk), 0 ); diff --git a/src/base/abci/abcUnate.c b/src/base/abci/abcUnate.c index 48b7eb92..8fd2a12f 100644 --- a/src/base/abci/abcUnate.c +++ b/src/base/abci/abcUnate.c @@ -66,20 +66,22 @@ void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ) Abc_Obj_t * pNode; Extra_UnateInfo_t * p; DdManager * dd; // the BDD manager used to hold shared BDDs - DdNode ** pbGlobal; // temporary storage for global BDDs +// DdNode ** pbGlobal; // temporary storage for global BDDs int TotalSupps = 0; int TotalUnate = 0; int i, clk = clock(); int clkBdd, clkUnate; // compute the global BDDs - if ( Abc_NtkGlobalBdds(pNtk, 10000000, 0, 1, fVerbose) == NULL ) + dd = Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose); + if ( dd == NULL ) return; clkBdd = clock() - clk; // get information about the network - dd = pNtk->pManGlob; - pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob ); +// dd = pNtk->pManGlob; +// dd = Abc_NtkGlobalBddMan( pNtk ); +// pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob ); // print the size of the BDDs printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); @@ -89,7 +91,8 @@ clkBdd = clock() - clk; { Abc_NtkForEachCo( pNtk, pNode, i ) { - p = Extra_UnateComputeSlow( dd, pbGlobal[i] ); +// p = Extra_UnateComputeSlow( dd, pbGlobal[i] ); + p = Extra_UnateComputeSlow( dd, Abc_ObjGlobalBdd(pNode) ); if ( fVerbose ) Extra_UnateInfoPrint( p ); TotalSupps += p->nVars; @@ -104,7 +107,8 @@ clkBdd = clock() - clk; Cudd_zddVarsFromBddVars( dd, 2 ); Abc_NtkForEachCo( pNtk, pNode, i ) { - p = Extra_UnateComputeFast( dd, pbGlobal[i] ); +// p = Extra_UnateComputeFast( dd, pbGlobal[i] ); + p = Extra_UnateComputeFast( dd, Abc_ObjGlobalBdd(pNode) ); if ( fVerbose ) Extra_UnateInfoPrint( p ); TotalSupps += p->nVars; @@ -122,10 +126,11 @@ clkUnate = clock() - clk - clkBdd; PRT( "Total ", clock() - clk ); // deref the PO functions - Abc_NtkFreeGlobalBdds( pNtk ); +// Abc_NtkFreeGlobalBdds( pNtk ); // stop the global BDD manager - Extra_StopManager( pNtk->pManGlob ); - pNtk->pManGlob = NULL; +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + Abc_NtkFreeGlobalBdds( pNtk, 1 ); } /**Function************************************************************* diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c index e4873986..acd63771 100644 --- a/src/base/abci/abcUnreach.c +++ b/src/base/abci/abcUnreach.c @@ -58,7 +58,7 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) } // compute the global BDDs of the latches - dd = Abc_NtkGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); if ( dd == NULL ) return 0; if ( fVerbose ) @@ -92,7 +92,7 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach ); Cudd_RecursiveDeref( dd, bUnreach ); Extra_StopManager( dd ); - pNtk->pManGlob = NULL; +// pNtk->pManGlob = NULL; // make sure that everything is okay if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) ) @@ -137,13 +137,15 @@ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbo Abc_NtkForEachLatch( pNtk, pNode, i ) { bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); - bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); +// bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); + bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } // free the global BDDs - Abc_NtkFreeGlobalBdds( pNtk ); +// Abc_NtkFreeGlobalBdds( pNtk ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); // quantify the PI variables bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs ); diff --git a/src/base/abci/module.make b/src/base/abci/module.make index 7db26629..04ed07a7 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -15,6 +15,7 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcFraig.c \ src/base/abci/abcFxu.c \ src/base/abci/abcGen.c \ + src/base/abci/abcIf.c \ src/base/abci/abcIvy.c \ src/base/abci/abcLut.c \ src/base/abci/abcMap.c \ @@ -22,7 +23,6 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcMiter.c \ src/base/abci/abcNtbdd.c \ src/base/abci/abcOrder.c \ - src/base/abci/abcPga.c \ src/base/abci/abcPrint.c \ src/base/abci/abcProve.c \ src/base/abci/abcReconv.c \ diff --git a/src/base/io/io.c b/src/base/io/io.c index 7a661664..b1ea03c1 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -1339,12 +1339,6 @@ int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( !Abc_NtkHasAig(pAbc->pNtkCur) ) - { - fprintf( stdout, "IoCommandWriteDot(): Currently can only process AIGs.\n" ); - return 0; - } - if ( argc != globalUtilOptind + 1 ) { goto usage; @@ -1354,13 +1348,13 @@ int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) FileName = argv[globalUtilOptind]; // write the file vNodes = Abc_NtkCollectObjects( pAbc->pNtkCur ); - Io_WriteDotAig( pAbc->pNtkCur, vNodes, NULL, FileName, 0 ); + Io_WriteDotNtk( pAbc->pNtkCur, vNodes, NULL, FileName, 0, 0 ); Vec_PtrFree( vNodes ); return 0; usage: fprintf( pAbc->Err, "usage: write_dot [-h] \n" ); - fprintf( pAbc->Err, "\t write the AIG into a DOT file\n" ); + fprintf( pAbc->Err, "\t write the current network into a DOT file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; @@ -1598,13 +1592,13 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; } - if ( Abc_NtkGetLevelNum(pNtk) > 1 ) + if ( Abc_NtkLevel(pNtk) > 1 ) { fprintf( pAbc->Out, "PLA writing is available for collapsed networks.\n" ); return 0; } - if ( Abc_NtkGetLevelNum(pNtk) > 1 ) + if ( Abc_NtkLevel(pNtk) > 1 ) { fprintf( pAbc->Out, "PLA writing is available for collapsed networks.\n" ); return 0; diff --git a/src/base/io/io.h b/src/base/io/io.h index c42d2016..e7971b8d 100644 --- a/src/base/io/io.h +++ b/src/base/io/io.h @@ -86,8 +86,8 @@ extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteCnf.c ==========================================================*/ extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteDot.c ==========================================================*/ -extern void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fMulti ); -extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames ); +extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); +extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); /*=== abcWriteEqn.c ==========================================================*/ extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWriteGml.c ==========================================================*/ diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index dff27dd1..fa2d6f25 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -132,7 +132,7 @@ Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); Abc_ObjAddFanin( pNet, pTerm ); // set latch name - Abc_ObjAssignName( pLatch, pNetLO, "_latch" ); + Abc_ObjAssignName( pLatch, pNetLO, "L" ); return pLatch; } diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index 3cc3fcfe..084bd111 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -21,7 +21,6 @@ #include "io.h" #include "main.h" #include "mio.h" -//#include "seqInt.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -36,7 +35,7 @@ static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ); /**Function************************************************************* - Synopsis [Writes the graph structure of AIG for DOT.] + Synopsis [Writes the graph structure of network for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] @@ -46,14 +45,15 @@ static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ); SeeAlso [] ***********************************************************************/ -void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fMulti ) +void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) { FILE * pFile; - Abc_Obj_t * pNode, * pTemp, * pPrev; - int LevelMin, LevelMax, fHasCos, Level, i; + Abc_Obj_t * pNode, * pFanin; + char * pSopString; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; int Limit = 300; - assert( Abc_NtkHasAig(pNtk) ); + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); if ( vNodes->nSize < 1 ) { @@ -74,6 +74,16 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho return; } + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); + return; + } + } + // mark the nodes from the set Vec_PtrForEachEntry( vNodes, pNode, i ) pNode->fMarkC = 1; @@ -81,6 +91,17 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho Vec_PtrForEachEntry( vNodesShow, pNode, i ) pNode->fMarkB = 1; + // get the levels of nodes + LevelMax = Abc_NtkLevel( pNtk ); + if ( fUseReverse ) + { + LevelMin = Abc_NtkLevelReverse( pNtk ); + assert( LevelMax == LevelMin ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_ObjIsNode(pNode) ) + pNode->Level = LevelMax - pNode->Level + 1; + } + // find the largest and the smallest levels LevelMin = 10000; LevelMax = -1; @@ -110,9 +131,9 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho } // write the DOT header - fprintf( pFile, "# %s\n", "AIG structure generated by ABC" ); + fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); fprintf( pFile, "\n" ); - fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "digraph network {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "size = \"10,8.5\";\n" ); // fprintf( pFile, "size = \"14,11\";\n" ); @@ -169,7 +190,7 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); - fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "%s", "Network structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); @@ -187,7 +208,10 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); - fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); + if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) + fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); + else + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); @@ -207,9 +231,11 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho { if ( !Abc_ObjIsCo(pNode) ) continue; - fprintf( pFile, " Node%d%s [label = \"%s%s\"", pNode->Id, - (Abc_ObjIsLatch(pNode)? "_in":""), Abc_ObjName(pNode), (Abc_ObjIsLatch(pNode)? "_in":"") ); - fprintf( pFile, ", shape = %s", (Abc_ObjIsLatch(pNode)? "box":"invtriangle") ); + fprintf( pFile, " Node%d [label = \"%s%s\"", + pNode->Id, + (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), + (Abc_ObjIsBi(pNode)? "_in":"") ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); @@ -231,7 +257,17 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho { if ( (int)pNode->Level != Level ) continue; - fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); +// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + if ( Abc_NtkIsStrash(pNtk) ) + pSopString = ""; + else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) + pSopString = Mio_GateReadName(pNode->pData); + else if ( Abc_NtkHasMapping(pNtk) ) + pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); + else + pSopString = Abc_NtkPrintSop(pNode->pData); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); @@ -249,7 +285,7 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMin ); - // generat the PO nodes + // generate the PO nodes Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( !Abc_ObjIsCi(pNode) ) @@ -266,9 +302,10 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho } continue; } - fprintf( pFile, " Node%d%s [label = \"%s%s\"", pNode->Id, - (Abc_ObjIsLatch(pNode)? "_out":""), Abc_ObjName(pNode), (Abc_ObjIsLatch(pNode)? "_out":"") ); - fprintf( pFile, ", shape = %s", (Abc_ObjIsLatch(pNode)? "box":"triangle") ); + fprintf( pFile, " Node%d [label = \"%s\"", + pNode->Id, + (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); @@ -285,88 +322,30 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho { if ( (int)pNode->Level != LevelMax ) continue; - fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, - (Abc_ObjIsLatch(pNode)? "_in":"") ); + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); } // generate edges Vec_PtrForEachEntry( vNodes, pNode, i ) { - if ( Abc_ObjFaninNum(pNode) == 0 ) - continue; - - if ( Abc_ObjIsBo(pNode) ) - continue; - - if ( fMulti && Abc_ObjIsNode(pNode) ) - { - Vec_Ptr_t * vSuper; - Abc_Obj_t * pFanin; - int k, fCompl; - vSuper = (Vec_Ptr_t *)pNode->pCopy; - assert( vSuper != NULL ); - Vec_PtrForEachEntry( vSuper, pFanin, k ) - { - fCompl = Abc_ObjIsComplement(pFanin); - pFanin = Abc_ObjRegular(pFanin); - if ( !pFanin->fMarkC ) - continue; - - if ( Abc_ObjIsBi(pFanin) ) - continue; - - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", pFanin->Id, (Abc_ObjIsLatch(pFanin)? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", fCompl? "dotted" : "bold" ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - } - continue; - } - // generate the edge from this node to the next - if ( Abc_ObjFanin0(pNode)->fMarkC && !Abc_ObjIsBi(Abc_ObjFanin0(pNode)) ) - { - fprintf( pFile, "Node%d%s", pNode->Id, (Abc_ObjIsLatch(pNode)? "_in":"") ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Abc_ObjFaninId0(pNode), (Abc_ObjIsLatch(Abc_ObjFanin0(pNode))? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", Abc_ObjFaninC0(pNode)? "dotted" : "bold" ); -// if ( Abc_NtkIsSeq(pNode->pNtk) && Seq_ObjFaninL0(pNode) > 0 ) -// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - } - if ( Abc_ObjFaninNum(pNode) == 1 ) + if ( Abc_ObjIsLatch(pNode) ) continue; - // generate the edge from this node to the next - if ( Abc_ObjFanin1(pNode)->fMarkC && !Abc_ObjIsBi(Abc_ObjFanin1(pNode)) ) + Abc_ObjForEachFanin( pNode, pFanin, k ) { + if ( Abc_ObjIsLatch(pFanin) ) + continue; + fCompl = 0; + if ( Abc_NtkIsStrash(pNtk) ) + fCompl = Abc_ObjFaninC(pNode, k); + // generate the edge from this node to the next fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Abc_ObjFaninId1(pNode), (Abc_ObjIsLatch(Abc_ObjFanin1(pNode))? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", Abc_ObjFaninC1(pNode)? "dotted" : "bold" ); -// if ( Abc_NtkIsSeq(pNode->pNtk) && Seq_ObjFaninL1(pNode) > 0 ) -// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); + fprintf( pFile, "Node%d", pFanin->Id ); + fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); +// fprintf( pFile, ", label = \"%c\"", 'a' + k ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } - // generate the edges between the equivalent nodes - pPrev = pNode; - for ( pTemp = pNode->pData; pTemp; pTemp = pTemp->pData ) - { - if ( pTemp->fMarkC ) - { - fprintf( pFile, "Node%d", pPrev->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pTemp->Id ); - fprintf( pFile, " [style = %s]", (pPrev->fPhase ^ pTemp->fPhase)? "dotted" : "bold" ); - fprintf( pFile, ";\n" ); - pPrev = pTemp; - } - } } fprintf( pFile, "}" ); @@ -380,8 +359,13 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho if ( vNodesShow ) Vec_PtrForEachEntry( vNodesShow, pNode, i ) pNode->fMarkB = 0; + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); } + /**Function************************************************************* Synopsis [Writes the graph structure of network for DOT.] @@ -394,15 +378,15 @@ void Io_WriteDotAig( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho SeeAlso [] ***********************************************************************/ -void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames ) +void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) { FILE * pFile; Abc_Obj_t * pNode, * pFanin; char * pSopString; - int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; int Limit = 300; - assert( !Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); if ( vNodes->nSize < 1 ) { @@ -441,7 +425,15 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho pNode->fMarkB = 1; // get the levels of nodes - Abc_NtkGetLevelNum( pNtk ); + LevelMax = Abc_NtkLevel( pNtk ); + if ( fUseReverse ) + { + LevelMin = Abc_NtkLevelReverse( pNtk ); + assert( LevelMax == LevelMin ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_ObjIsNode(pNode) ) + pNode->Level = LevelMax - pNode->Level + 1; + } // find the largest and the smallest levels LevelMin = 10000; @@ -474,12 +466,15 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho // write the DOT header fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); fprintf( pFile, "\n" ); - fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "digraph network {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "size = \"10,8.5\";\n" ); +// fprintf( pFile, "size = \"14,11\";\n" ); +// fprintf( pFile, "page = \"8,11\";\n" ); // fprintf( pFile, "ranksep = 0.5;\n" ); // fprintf( pFile, "nodesep = 0.5;\n" ); fprintf( pFile, "center = true;\n" ); -// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); @@ -546,7 +541,10 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); - fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); + if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) + fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); + else + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); @@ -564,11 +562,10 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho // generate the PO nodes Vec_PtrForEachEntry( vNodes, pNode, i ) { - if ( !Abc_ObjIsCo(pNode) ) + if ( !Abc_ObjIsPo(pNode) ) continue; - fprintf( pFile, " Node%d%s [label = \"%s%s\"", pNode->Id, - (Abc_ObjIsLatch(pNode)? "_in":""), Abc_ObjName(pNode), (Abc_ObjIsLatch(pNode)? "_in":"") ); - fprintf( pFile, ", shape = %s", (Abc_ObjIsLatch(pNode)? "box":"invtriangle") ); + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = %s", "invtriangle" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); @@ -586,12 +583,14 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); - Vec_PtrForEachEntry( vNodes, pNode, i ) + Abc_NtkForEachNode( pNtk, pNode, i ) { if ( (int)pNode->Level != Level ) continue; // fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - if ( Abc_NtkHasMapping(pNtk) && fGateNames ) + if ( Abc_NtkIsStrash(pNtk) ) + pSopString = ""; + else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) pSopString = Mio_GateReadName(pNode->pData); else if ( Abc_NtkHasMapping(pNtk) ) pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); @@ -619,7 +618,9 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho // generate the PO nodes Vec_PtrForEachEntry( vNodes, pNode, i ) { - if ( !Abc_ObjIsCi(pNode) ) + if ( pNode->Level > 0 ) + continue; + if ( !Abc_ObjIsPi(pNode) ) { // check if the costant node is present if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) @@ -633,9 +634,8 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho } continue; } - fprintf( pFile, " Node%d%s [label = \"%s%s\"", pNode->Id, - (Abc_ObjIsLatch(pNode)? "_out":""), Abc_ObjName(pNode), (Abc_ObjIsLatch(pNode)? "_out":"") ); - fprintf( pFile, ", shape = %s", (Abc_ObjIsLatch(pNode)? "box":"triangle") ); + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = %s", "triangle" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); @@ -646,34 +646,61 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho fprintf( pFile, "\n" ); } +// fprintf( pFile, "{\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsLatch(pNode) ) + continue; + fprintf( pFile, "Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = box" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } +// fprintf( pFile, "}" ); +// fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + // generate invisible edges from the square down fprintf( pFile, "title1 -> title2 [style = invis];\n" ); Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( (int)pNode->Level != LevelMax ) continue; - fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, - (Abc_ObjIsLatch(pNode)? "_in":"") ); + if ( !Abc_ObjIsPo(pNode) ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); } // generate edges Vec_PtrForEachEntry( vNodes, pNode, i ) { + if ( Abc_ObjIsBi(pNode) || Abc_ObjIsBo(pNode) ) + continue; Abc_ObjForEachFanin( pNode, pFanin, k ) { - if ( !Abc_ObjFanin0(pNode)->fMarkC ) - continue; - - // added to fix the bug after adding boxes - if ( Abc_ObjIsBo(pNode) || Abc_ObjIsBi(pFanin) ) + fCompl = 0; + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( Abc_ObjIsBi(pFanin) ) + fCompl = Abc_ObjFaninC(pFanin, k); + else + fCompl = Abc_ObjFaninC(pNode, k); + } + if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + if ( !pFanin->fMarkC ) continue; // generate the edge from this node to the next - fprintf( pFile, "Node%d%s", pNode->Id, (Abc_ObjIsLatch(pNode)? "_in":"") ); + fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Abc_ObjFaninId(pNode,k), (Abc_ObjIsLatch(Abc_ObjFanin(pNode,k))? "_out":"") ); - fprintf( pFile, " [style = bold" ); - fprintf( pFile, ", label = \"%c\"", 'a' + k ); + fprintf( pFile, "Node%d", pFanin->Id ); + fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); +// fprintf( pFile, ", label = \"%c\"", 'a' + k ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } @@ -696,6 +723,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho Abc_NtkSopToBdd(pNtk); } + /**Function************************************************************* Synopsis [Computes the printable SOP form.] diff --git a/src/base/io/ioWritePla.c b/src/base/io/ioWritePla.c index 4da8aca8..b119751c 100644 --- a/src/base/io/ioWritePla.c +++ b/src/base/io/ioWritePla.c @@ -47,7 +47,7 @@ int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName ) FILE * pFile; assert( Abc_NtkIsSopNetlist(pNtk) ); - assert( Abc_NtkGetLevelNum(pNtk) == 1 ); + assert( Abc_NtkLevel(pNtk) == 1 ); pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) diff --git a/src/base/io/ioWriteVer.c b/src/base/io/ioWriteVer.c index 381e6e28..9be3d8b3 100644 --- a/src/base/io/ioWriteVer.c +++ b/src/base/io/ioWriteVer.c @@ -463,7 +463,7 @@ void Io_WriteVerilogVerLibStyle( FILE * pFile, Abc_Ntk_t * pNtk ) Vec_Vec_t * vLevels; Abc_Ntk_t * pNtkGate; Abc_Obj_t * pObj, * pTerm, * pFanin; - Aig_Obj_t * pFunc; + Hop_Obj_t * pFunc; int i, k, Counter, nDigits; Counter = 1; @@ -495,13 +495,13 @@ void Io_WriteVerilogVerLibStyle( FILE * pFile, Abc_Ntk_t * pNtk ) fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjFanout0(pObj)) ); // set the input names Abc_ObjForEachFanin( pObj, pFanin, k ) - Aig_IthVar(pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(pFanin)); + Hop_IthVar(pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(pFanin)); // write the formula - Aig_ObjPrintVerilog( pFile, pFunc, vLevels, 0 ); + Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 ); fprintf( pFile, ";\n" ); // clear the input names Abc_ObjForEachFanin( pObj, pFanin, k ) - free( Aig_IthVar(pNtk->pManFunc, k)->pData ); + free( Hop_IthVar(pNtk->pManFunc, k)->pData ); } Vec_VecFree( vLevels ); } diff --git a/src/base/main/libSupport.c b/src/base/main/libSupport.c index cdfd98b8..471ea09e 100644 --- a/src/base/main/libSupport.c +++ b/src/base/main/libSupport.c @@ -49,7 +49,7 @@ void open_libs() { env = getenv ("ABC_LIB_PATH"); if (env == NULL) { - printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n"); +// printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n"); init_p = malloc (2*sizeof(char)); init_p[0]='.'; init_p[1] = 0; } else { @@ -67,7 +67,7 @@ void open_libs() { dirp = opendir(p); if (dirp == NULL) { - printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p); +// printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p); continue; } diff --git a/src/base/ver/module.make b/src/base/ver/module.make new file mode 100644 index 00000000..2cc37803 --- /dev/null +++ b/src/base/ver/module.make @@ -0,0 +1,4 @@ +SRC += src/base/ver/verCore.c \ + src/base/ver/verFormula.c \ + src/base/ver/verParse.c \ + src/base/ver/verStream.c diff --git a/src/base/ver/ver.h b/src/base/ver/ver.h new file mode 100644 index 00000000..c7c18f79 --- /dev/null +++ b/src/base/ver/ver.h @@ -0,0 +1,114 @@ +/**CFile**************************************************************** + + FileName [ver.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: ver.h,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VER_H__ +#define __VER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ver_Man_t_ Ver_Man_t; +typedef struct Ver_Stream_t_ Ver_Stream_t; + +struct Ver_Man_t_ +{ + // input file stream + char * pFileName; + Ver_Stream_t * pReader; + ProgressBar * pProgress; + // current network and library + Abc_Ntk_t * pNtkCur; // the network under construction + Abc_Lib_t * pDesign; // the current design + // parameters + int fUseMemMan; // allocate memory manager in the networks + int fCheck; // checks network for currectness + // error recovery + FILE * Output; + int fTopLevel; + int fError; + char sError[2000]; + // intermediate structures + Vec_Ptr_t * vNames; + Vec_Ptr_t * vStackFn; + Vec_Int_t * vStackOp; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== verCore.c ========================================================*/ +extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); +extern void Ver_ParsePrintErrorMessage( Ver_Man_t * p ); +/*=== verFormula.c ========================================================*/ +extern void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ); +extern void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ); +/*=== verParse.c ========================================================*/ +extern int Ver_ParseSkipComments( Ver_Man_t * p ); +extern char * Ver_ParseGetName( Ver_Man_t * p ); +/*=== verStream.c ========================================================*/ +extern Ver_Stream_t * Ver_StreamAlloc( char * pFileName ); +extern void Ver_StreamFree( Ver_Stream_t * p ); +extern char * Ver_StreamGetFileName( Ver_Stream_t * p ); +extern int Ver_StreamGetFileSize( Ver_Stream_t * p ); +extern int Ver_StreamGetCurPosition( Ver_Stream_t * p ); +extern int Ver_StreamGetLineNumber( Ver_Stream_t * p ); + +extern int Ver_StreamIsOkey( Ver_Stream_t * p ); +extern char Ver_StreamScanChar( Ver_Stream_t * p ); +extern char Ver_StreamPopChar( Ver_Stream_t * p ); +extern void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ); +extern void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ); +extern char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/base/ver/verCore.c b/src/base/ver/verCore.c new file mode 100644 index 00000000..9048337b --- /dev/null +++ b/src/base/ver/verCore.c @@ -0,0 +1,1092 @@ +/**CFile**************************************************************** + + FileName [verCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Parses several flavors of structural Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// types of verilog signals +typedef enum { + VER_SIG_NONE = 0, + VER_SIG_INPUT, + VER_SIG_OUTPUT, + VER_SIG_INOUT, + VER_SIG_REG, + VER_SIG_WIRE +} Ver_SignalType_t; + +// types of verilog gates +typedef enum { + VER_GATE_AND = 0, + VER_GATE_OR, + VER_GATE_XOR, + VER_GATE_BUF, + VER_GATE_NAND, + VER_GATE_NOR, + VER_GATE_XNOR, + VER_GATE_NOT +} Ver_GateType_t; + +static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ); +static void Ver_ParseStop( Ver_Man_t * p ); +static void Ver_ParseFreeData( Ver_Man_t * p ); +static void Ver_ParseInternal( Ver_Man_t * p ); +static int Ver_ParseModule( Ver_Man_t * p ); +static int Ver_ParseSignal( Ver_Man_t * p, Ver_SignalType_t SigType ); +static int Ver_ParseAssign( Ver_Man_t * p ); +static int Ver_ParseAlways( Ver_Man_t * p ); +static int Ver_ParseInitial( Ver_Man_t * p ); +static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtkGate ); +static int Ver_ParseGateStandard( Ver_Man_t * pMan, Ver_GateType_t GateType ); + +static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ); +static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ); +static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ) +{ + Ver_Man_t * p; + Abc_Lib_t * pDesign; + // start the parser + p = Ver_ParseStart( pFileName, pGateLib ); + p->fCheck = fCheck; + p->fUseMemMan = fUseMemMan; + // parse the file + Ver_ParseInternal( p ); + // save the result + pDesign = p->pDesign; + p->pDesign = NULL; + // stop the parser + Ver_ParseStop( p ); + return pDesign; +} + +/**Function************************************************************* + + Synopsis [Start parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ) +{ + Ver_Man_t * p; + p = ALLOC( Ver_Man_t, 1 ); + memset( p, 0, sizeof(Ver_Man_t) ); + p->pFileName = pFileName; + p->pReader = Ver_StreamAlloc( pFileName ); + p->Output = stdout; + p->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(p->pReader) ); + p->vNames = Vec_PtrAlloc( 100 ); + p->vStackFn = Vec_PtrAlloc( 100 ); + p->vStackOp = Vec_IntAlloc( 100 ); + // create the design library and assign the technology library + p->pDesign = Abc_LibCreate( pFileName ); + p->pDesign->pLibrary = pGateLib; + return p; +} + +/**Function************************************************************* + + Synopsis [Stop parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseStop( Ver_Man_t * p ) +{ + assert( p->pNtkCur == NULL ); + Ver_StreamFree( p->pReader ); + Extra_ProgressBarStop( p->pProgress ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vStackFn ); + Vec_IntFree( p->vStackOp ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseInternal( Ver_Man_t * pMan ) +{ + char * pToken; + while ( 1 ) + { + // get the next token + pToken = Ver_ParseGetName( pMan ); + if ( pToken == NULL ) + break; + if ( strcmp( pToken, "module" ) ) + { + sprintf( pMan->sError, "Cannot read \"module\" directive." ); + Ver_ParsePrintErrorMessage( pMan ); + return; + } + + // parse the module + if ( !Ver_ParseModule( pMan ) ) + return; + + // check the network for correctness + if ( pMan->fCheck && !Abc_NtkCheckRead( pMan->pNtkCur ) ) + { + pMan->fTopLevel = 1; + sprintf( pMan->sError, "The network check has failed.", pMan->pNtkCur->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return; + } + // add the module to the hash table + if ( st_is_member( pMan->pDesign->tModules, pMan->pNtkCur->pName ) ) + { + pMan->fTopLevel = 1; + sprintf( pMan->sError, "Module \"%s\" is defined more than once.", pMan->pNtkCur->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return; + } + Vec_PtrPush( pMan->pDesign->vModules, pMan->pNtkCur ); + st_insert( pMan->pDesign->tModules, pMan->pNtkCur->pName, (char *)pMan->pNtkCur ); + pMan->pNtkCur = NULL; + } +} + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseFreeData( Ver_Man_t * p ) +{ + if ( p->pNtkCur ) + { + p->pNtkCur->pManFunc = NULL; + Abc_NtkDelete( p->pNtkCur ); + p->pNtkCur = NULL; + } + if ( p->pDesign ) + { + Abc_LibFree( p->pDesign ); + p->pDesign = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParsePrintErrorMessage( Ver_Man_t * p ) +{ + p->fError = 1; + if ( p->fTopLevel ) // the line number is not given + fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); + else // print the error message with the line number + fprintf( p->Output, "%s (line %d): %s\n", + p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError ); + // free the data + Ver_ParseFreeData( p ); +} + + + +/**Function************************************************************* + + Synopsis [Parses one Verilog module.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseModule( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Ntk_t * pNtk, * pNtkTemp; + Abc_Obj_t * pNet; + char * pWord, Symbol; + int RetValue; + + // start the current network + assert( pMan->pNtkCur == NULL ); + pNtk = pMan->pNtkCur = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan ); + pNtk->ntkFunc = ABC_FUNC_AIG; + pNtk->pManFunc = pMan->pDesign->pManFunc; + + // get the network name + pWord = Ver_ParseGetName( pMan ); + pNtk->pName = Extra_UtilStrsav( pWord ); + pNtk->pSpec = NULL; + + // create constant nets + Abc_NtkFindOrCreateNet( pNtk, "1'b0" ); + Abc_NtkFindOrCreateNet( pNtk, "1'b1" ); + + // make sure we stopped at the opening paranthesis + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot find \"(\" after \"module\".", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // skip to the end of parantheses + do { + if ( Ver_ParseGetName( pMan ) == NULL ) + return 0; + Symbol = Ver_StreamPopChar(p); + } while ( Symbol == ',' ); + assert( Symbol == ')' ); + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + Symbol = Ver_StreamPopChar(p); + assert( Symbol == ';' ); + + // parse the inputs/outputs/registers/wires/inouts + while ( 1 ) + { + Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + if ( !strcmp( pWord, "input" ) ) + RetValue = Ver_ParseSignal( pMan, VER_SIG_INPUT ); + else if ( !strcmp( pWord, "output" ) ) + RetValue = Ver_ParseSignal( pMan, VER_SIG_OUTPUT ); + else if ( !strcmp( pWord, "reg" ) ) + RetValue = Ver_ParseSignal( pMan, VER_SIG_REG ); + else if ( !strcmp( pWord, "wire" ) ) + RetValue = Ver_ParseSignal( pMan, VER_SIG_WIRE ); + else if ( !strcmp( pWord, "inout" ) ) + RetValue = Ver_ParseSignal( pMan, VER_SIG_INOUT ); + else + break; + if ( RetValue == 0 ) + return 0; + } + + // parse the remaining statements + while ( 1 ) + { + Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); + + if ( !strcmp( pWord, "and" ) ) + RetValue = Ver_ParseGateStandard( pMan, VER_GATE_AND ); + else if ( !strcmp( pWord, "or" ) ) + RetValue = Ver_ParseGateStandard( pMan, VER_GATE_OR ); + else if ( !strcmp( pWord, "xor" ) ) + RetValue = Ver_ParseGateStandard( pMan, VER_GATE_XOR ); + else if ( !strcmp( pWord, "buf" ) ) + RetValue = Ver_ParseGateStandard( pMan, VER_GATE_BUF ); + else if ( !strcmp( pWord, "nand" ) ) + RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NAND ); + else if ( !strcmp( pWord, "nor" ) ) + RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NOR ); + else if ( !strcmp( pWord, "xnor" ) ) + RetValue = Ver_ParseGateStandard( pMan, VER_GATE_XNOR ); + else if ( !strcmp( pWord, "not" ) ) + RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NOT ); + + else if ( !strcmp( pWord, "assign" ) ) + RetValue = Ver_ParseAssign( pMan ); + else if ( !strcmp( pWord, "always" ) ) + RetValue = Ver_ParseAlways( pMan ); + else if ( !strcmp( pWord, "initial" ) ) + RetValue = Ver_ParseInitial( pMan ); + else if ( !strcmp( pWord, "endmodule" ) ) + break; + else if ( pMan->pDesign->pLibrary && st_lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library + RetValue = Ver_ParseGate( pMan, pNtkTemp ); + else if ( pMan->pDesign && st_lookup(pMan->pDesign->tModules, pWord, (char**)&pNtkTemp) ) // current design + RetValue = Ver_ParseGate( pMan, pNtkTemp ); + else + { + printf( "Cannot find \"%s\".\n", pWord ); + Ver_StreamSkipToChars( p, ";" ); + Ver_StreamPopChar(p); + +// sprintf( pMan->sError, "Cannot find \"%s\" in the library.", pWord ); +// Ver_ParsePrintErrorMessage( pMan ); +// return 0; + } + if ( RetValue == 0 ) + return 0; + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get new word + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + } + + // check if constant 0 net is used + pNet = Abc_NtkFindOrCreateNet( pNtk, "1'b0" ); + if ( Abc_ObjFanoutNum(pNet) == 0 ) + Abc_NtkDeleteObj(pNet); + else + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) ); + // check if constant 1 net is used + pNet = Abc_NtkFindOrCreateNet( pNtk, "1'b1" ); + if ( Abc_ObjFanoutNum(pNet) == 0 ) + Abc_NtkDeleteObj(pNet); + else + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) ); + + // fix the dangling nets + Abc_NtkFinalizeRead( pNtk ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSignal( Ver_Man_t * pMan, Ver_SignalType_t SigType ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Ntk_t * pNtk = pMan->pNtkCur; + char * pWord; + char Symbol; + while ( 1 ) + { + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePi( pNtk, pWord ); + if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePo( pNtk, pWord ); + if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) + Abc_NtkFindOrCreateNet( pNtk, pWord ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ',' ) + continue; + if ( Symbol == ';' ) + return 1; + break; + } + sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseAssign( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Ntk_t * pNtk = pMan->pNtkCur; + Abc_Obj_t * pNode, * pNet; + char * pWord, * pName, * pEquation; + Hop_Obj_t * pFunc; + char Symbol; + int i, Length, fReduction; + + // convert from the mapped netlist into the BDD netlist + if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) + { + pNtk->ntkFunc = ABC_FUNC_AIG; + assert( pNtk->pManFunc == NULL ); + pNtk->pManFunc = pMan->pDesign->pManFunc; + } + else if ( pNtk->ntkFunc != ABC_FUNC_AIG ) + { + sprintf( pMan->sError, "The network %s appears to mapped gates and assign statements. Currently such network are not allowed. One way to fix this problem is to replace assigns by buffers from the library.", pMan->pNtkCur ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + while ( 1 ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // consider the case of reduction operations + fReduction = (pWord[0] == '{'); + if ( fReduction ) + { + pWord++; + pWord[strlen(pWord)-1] = 0; + assert( pWord[0] != '\\' ); + } + // get the fanout net + pNet = Abc_NtkFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equal sign + if ( Ver_StreamPopChar(p) != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + if ( fReduction ) + pEquation = Ver_StreamGetWord( p, ";" ); + else + pEquation = Ver_StreamGetWord( p, ",;" ); + if ( pEquation == NULL ) + return 0; + + // parse the formula + if ( fReduction ) + pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError ); + else + pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError ); + if ( pFunc == NULL ) + { + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // create the node with the given inputs + pNode = Abc_NtkCreateNode( pMan->pNtkCur ); + pNode->pData = pFunc; + Abc_ObjAddFanin( pNet, pNode ); + // connect to fanin nets + for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ ) + { + // get the name of this signal + Length = (int)Vec_PtrEntry( pMan->vNames, 2*i ); + pName = Vec_PtrEntry( pMan->vNames, 2*i + 1 ); + pName[Length] = 0; + // find the corresponding net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %d is not defined).", pWord, pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Abc_ObjAddFanin( pNode, pNet ); + } + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ',' ) + continue; + if ( Symbol == ';' ) + return 1; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseAlways( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Ntk_t * pNtk = pMan->pNtkCur; + Abc_Obj_t * pNet, * pNet2; + char * pWord, * pWord2; + char Symbol; + // parse the directive + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + if ( strcmp( pWord, "begin" ) ) + { + sprintf( pMan->sError, "Cannot parse the always statement (expected \"begin\")." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // iterate over the initial states + while ( 1 ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // look for the end of directive + if ( !strcmp( pWord, "end" ) ) + break; + // get the fanout net + pNet = Abc_NtkFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equal sign + if ( Ver_StreamPopChar(p) != '=' ) + { + sprintf( pMan->sError, "Cannot read the always statement for %s (expected equality sign).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + pWord2 = Ver_ParseGetName( pMan ); + if ( pWord2 == NULL ) + return 0; + // get the fanin net + pNet2 = Abc_NtkFindNet( pNtk, pWord2 ); + if ( pNet2 == NULL ) + { + sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // create the latch + Ver_ParseCreateLatch( pNtk, pNet2->pData, pNet->pData ); + // remove the last symbol + Symbol = Ver_StreamPopChar(p); + assert( Symbol == ';' ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseInitial( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Ntk_t * pNtk = pMan->pNtkCur; + Abc_Obj_t * pNode, * pNet; + char * pWord, * pEquation; + char Symbol; + // parse the directive + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + if ( strcmp( pWord, "begin" ) ) + { + sprintf( pMan->sError, "Cannot parse the initial statement (expected \"begin\")." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // iterate over the initial states + while ( 1 ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // look for the end of directive + if ( !strcmp( pWord, "end" ) ) + break; + // get the fanout net + pNet = Abc_NtkFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equal sign + if ( Ver_StreamPopChar(p) != '=' ) + { + sprintf( pMan->sError, "Cannot read the initial statement for %s (expected equality sign).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + pEquation = Ver_StreamGetWord( p, ";" ); + if ( pEquation == NULL ) + return 0; + // find the corresponding latch + pNode = Abc_ObjFanin0(pNet); + assert( Abc_ObjIsLatch(pNode) ); + // set the initial state + if ( pEquation[0] == '2' ) + Abc_LatchSetInitDc( pNode ); + else if ( pEquation[0] == '1') + Abc_LatchSetInit1( pNode ); + else if ( pEquation[0] == '0' ) + Abc_LatchSetInit0( pNode ); + else + { + sprintf( pMan->sError, "Incorrect initial value of the latch %s (expected equality sign).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // remove the last symbol + Symbol = Ver_StreamPopChar(p); + assert( Symbol == ';' ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtkGate ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Ntk_t * pNtk = pMan->pNtkCur; + Abc_Obj_t * pNetFormal, * pNetActual; + Abc_Obj_t * pObj, * pNode; + char * pWord, Symbol, * pGateName; + int i, fCompl, fComplUsed = 0; + unsigned * pPolarity; + + // clean the PI/PO pointers + Abc_NtkForEachPi( pNtkGate, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachPo( pNtkGate, pObj, i ) + pObj->pCopy = NULL; + // parse the directive and set the pointers to the PIs/POs of the gate + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // this is gate name - throw it away + pGateName = pWord; + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot parse gate %s (expected opening paranthesis).", pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // parse pairs of formal/actural inputs + while ( 1 ) + { + // process one pair of formal/actual parameters + if ( Ver_StreamPopChar(p) != '.' ) + { + sprintf( pMan->sError, "Cannot parse gate %s (expected .).", pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the formal name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // get the formal net + if ( Abc_NtkIsNetlist(pNtkGate) ) + pNetFormal = Abc_NtkFindNet( pNtkGate, pWord ); + else // if ( Abc_NtkIsStrash(pNtkGate) ) + assert( 0 ); + if ( pNetFormal == NULL ) + { + sprintf( pMan->sError, "Formal net is missing in gate %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // open the paranthesis + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the actual name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // check if the name is complemented + fCompl = (pWord[0] == '~'); + if ( fCompl ) + { + fComplUsed = 1; + pWord++; + if ( pMan->pNtkCur->pData == NULL ) + pMan->pNtkCur->pData = Extra_MmFlexStart(); + } + // get the actual net + pNetActual = Abc_NtkFindNet( pMan->pNtkCur, pWord ); + if ( pNetActual == NULL ) + { + sprintf( pMan->sError, "Actual net is missing in gate %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // close the paranthesis + if ( Ver_StreamPopChar(p) != ')' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // process the pair + if ( Abc_ObjIsPi(Abc_ObjFanin0Ntk(pNetFormal)) ) // PI net (with polarity!) + Abc_ObjFanin0Ntk(pNetFormal)->pCopy = Abc_ObjNotCond( pNetActual, fCompl ); + else if ( Abc_ObjIsPo(Abc_ObjFanout0Ntk(pNetFormal)) ) // P0 net + { + assert( fCompl == 0 ); + Abc_ObjFanout0Ntk(pNetFormal)->pCopy = pNetActual; // Abc_ObjNotCond( pNetActual, fCompl ); + } + else + { + sprintf( pMan->sError, "Cannot match formal net %s with PI or PO of the gate %s.", pWord, pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ')' ) + break; + // skip comma + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ';' ) + { + sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // make sure each input net is driven + Abc_NtkForEachPi( pNtkGate, pObj, i ) + if ( pObj->pCopy == NULL ) + { + sprintf( pMan->sError, "Formal input %s of gate %s has no actual input.", Abc_ObjFanout0(pObj)->pData, pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } +/* + // make sure each output net is driving something + Abc_NtkForEachPo( pNtkGate, pObj, i ) + if ( pObj->pCopy == NULL ) + { + sprintf( pMan->sError, "Formal output %s of gate %s has no actual output.", Abc_ObjFanin0(pObj)->pData, pNtkGate->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } +*/ + + // allocate memory to remember the phase + pPolarity = NULL; + if ( fComplUsed ) + { + int nBytes = 4 * Abc_BitWordNum( Abc_NtkPiNum(pNtkGate) ); + pPolarity = (unsigned *)Extra_MmFlexEntryFetch( pMan->pNtkCur->pData, nBytes ); + memset( pPolarity, 0, nBytes ); + } + // create box to represent this gate + pNode = Abc_NtkCreateBlackbox( pMan->pNtkCur ); +/* + if ( pNode->Id == 57548 ) + { + int x = 0; + } +*/ + pNode->pNext = (Abc_Obj_t *)pPolarity; + pNode->pData = pNtkGate; + // connect to fanin nets + Abc_NtkForEachPi( pNtkGate, pObj, i ) + { + if ( pPolarity && Abc_ObjIsComplement(pObj->pCopy) ) + { + Abc_InfoSetBit( pPolarity, i ); + pObj->pCopy = Abc_ObjRegular( pObj->pCopy ); + } + assert( !Abc_ObjIsComplement(pObj->pCopy) ); + Abc_ObjAddFanin( pNode, pObj->pCopy ); + } + // connect to fanout nets + Abc_NtkForEachPo( pNtkGate, pObj, i ) + { + if ( pObj->pCopy ) + Abc_ObjAddFanin( pObj->pCopy, pNode ); + else + Abc_ObjAddFanin( Abc_NtkFindOrCreateNet(pNtk, NULL), pNode ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseGateStandard( Ver_Man_t * pMan, Ver_GateType_t GateType ) +{ + Ver_Stream_t * p = pMan->pReader; + Hop_Man_t * pAig = pMan->pNtkCur->pManFunc; + Abc_Obj_t * pNet, * pNode; + char * pWord, Symbol; + // this is gate name - throw it away + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + // create the node + pNode = Abc_NtkCreateNode( pMan->pNtkCur ); + // parse pairs of formal/actural inputs + while ( 1 ) + { + // parse the output name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // get the net corresponding to this output + pNet = Abc_NtkFindNet( pMan->pNtkCur, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // if this is the first net, add it as an output + if ( Abc_ObjFanoutNum(pNode) == 0 ) + Abc_ObjAddFanin( pNet, pNode ); + else + Abc_ObjAddFanin( pNode, pNet ); + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ')' ) + break; + // skip comma + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing paranthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 ) + { + sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ';' ) + { + sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // add logic function + if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND ) + pNode->pData = Hop_CreateAnd( pAig, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR ) + pNode->pData = Hop_CreateOr( pAig, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR ) + pNode->pData = Hop_CreateExor( pAig, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT ) + pNode->pData = Hop_CreateAnd( pAig, Abc_ObjFaninNum(pNode) ); + if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT ) + pNode->pData = Hop_Not( pNode->pData ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Creates PI terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PI net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet ) + printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PI node + pTerm = Abc_NtkCreatePi( pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) + printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create a latch with the given input/output.] + + Description [By default, the latch value is unknown (ABC_INIT_NONE).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) +{ + Abc_Obj_t * pLatch, * pNet; + // create a new latch and add it to the network + pLatch = Abc_NtkCreateLatch( pNtk ); + // get the LI net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI ); + Abc_ObjAddFanin( pLatch, pNet ); + // get the LO net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); + Abc_ObjAddFanin( pNet, pLatch ); + return pLatch; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/ver/verFormula.c b/src/base/ver/verFormula.c new file mode 100644 index 00000000..cfe3e0c8 --- /dev/null +++ b/src/base/ver/verFormula.c @@ -0,0 +1,469 @@ +/**CFile**************************************************************** + + FileName [verFormula.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Formula parser to read Verilog assign statements.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verFormula.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the list of operation symbols to be used in expressions +#define VER_PARSE_SYM_OPEN '(' // opening paranthesis +#define VER_PARSE_SYM_CLOSE ')' // closing paranthesis +#define VER_PARSE_SYM_CONST0 '0' // constant 0 +#define VER_PARSE_SYM_CONST1 '1' // constant 1 +#define VER_PARSE_SYM_NEGBEF1 '!' // negation before the variable +#define VER_PARSE_SYM_NEGBEF2 '~' // negation before the variable +#define VER_PARSE_SYM_AND '&' // logic AND +#define VER_PARSE_SYM_OR '|' // logic OR +#define VER_PARSE_SYM_XOR '^' // logic XOR +#define VER_PARSE_SYM_MUX1 '?' // first symbol of MUX +#define VER_PARSE_SYM_MUX2 ':' // second symbol of MUX + +// the list of opcodes (also specifying operation precedence) +#define VER_PARSE_OPER_NEG 7 // negation (highest precedence) +#define VER_PARSE_OPER_AND 6 // logic AND +#define VER_PARSE_OPER_XOR 5 // logic EXOR (a'b | ab') +#define VER_PARSE_OPER_OR 4 // logic OR +#define VER_PARSE_OPER_EQU 3 // equvalence (a'b'| ab ) +#define VER_PARSE_OPER_MUX 2 // MUX(a,b,c) (ab | a'c ) +#define VER_PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis + +// these are values of the internal Flag +#define VER_PARSE_FLAG_START 1 // after the opening parenthesis +#define VER_PARSE_FLAG_VAR 2 // after operation is received +#define VER_PARSE_FLAG_OPER 3 // after operation symbol is received +#define VER_PARSE_FLAG_ERROR 4 // when error is detected + +static Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ); +static int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Parser of the formula encountered in assign statements.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ) +{ + Hop_Obj_t * bFunc, * bTemp; + char * pTemp; + int nParans, Flag; + int Oper, Oper1, Oper2; + int v; + + // clear the stacks and the names + Vec_PtrClear( vNames ); + Vec_PtrClear( vStackFn ); + Vec_IntClear( vStackOp ); + + // make sure that the number of opening and closing parantheses is the same + nParans = 0; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + if ( *pTemp == '(' ) + nParans++; + else if ( *pTemp == ')' ) + nParans--; + if ( nParans != 0 ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." ); + return NULL; + } + + // add parantheses + pTemp = pFormula + strlen(pFormula) + 2; + *pTemp-- = 0; *pTemp = ')'; + while ( --pTemp != pFormula ) + *pTemp = *(pTemp - 1); + *pTemp = '('; + + // perform parsing + Flag = VER_PARSE_FLAG_START; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + { + switch ( *pTemp ) + { + // skip all spaces, tabs, and end-of-lines + case ' ': + case '\t': + case '\r': + case '\n': + continue; + + // treat Constant 0 as a variable + case VER_PARSE_SYM_CONST0: + Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( Hop_ManConst0(pMan) ); + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Flag = VER_PARSE_FLAG_VAR; + break; + + // the same for Constant 1 + case VER_PARSE_SYM_CONST1: + Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( Hop_ManConst1(pMan) ); + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Flag = VER_PARSE_FLAG_VAR; + break; + + case VER_PARSE_SYM_NEGBEF1: + case VER_PARSE_SYM_NEGBEF2: + if ( Flag == VER_PARSE_FLAG_VAR ) + {// if NEGBEF follows a variable, AND is assumed + sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG ); + break; + + case VER_PARSE_SYM_AND: + case VER_PARSE_SYM_OR: + case VER_PARSE_SYM_XOR: + case VER_PARSE_SYM_MUX1: + case VER_PARSE_SYM_MUX2: + if ( Flag != VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + if ( *pTemp == VER_PARSE_SYM_AND ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_AND ); + else if ( *pTemp == VER_PARSE_SYM_OR ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_OR ); + else if ( *pTemp == VER_PARSE_SYM_XOR ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR ); + else if ( *pTemp == VER_PARSE_SYM_MUX1 ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); +// else if ( *pTemp == VER_PARSE_SYM_MUX2 ) +// Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); + Flag = VER_PARSE_FLAG_OPER; + break; + + case VER_PARSE_SYM_OPEN: + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK ); + // after an opening bracket, it feels like starting over again + Flag = VER_PARSE_FLAG_START; + break; + + case VER_PARSE_SYM_CLOSE: + if ( Vec_IntSize( vStackOp ) ) + { + while ( 1 ) + { + if ( !Vec_IntSize( vStackOp ) ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Oper = Vec_IntPop( vStackOp ); + if ( Oper == VER_PARSE_OPER_MARK ) + break; + // skip the second MUX operation +// if ( Oper == VER_PARSE_OPER_MUX2 ) +// { +// Oper = Vec_IntPop( vStackOp ); +// assert( Oper == VER_PARSE_OPER_MUX1 ); +// } + + // perform the given operation + if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper ) == NULL ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); + return NULL; + } + } + } + else + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + if ( Flag != VER_PARSE_FLAG_ERROR ) + Flag = VER_PARSE_FLAG_VAR; + break; + + + default: + // scan the next name + v = Ver_FormulaParserFindVar( pTemp, vNames ); + if ( *pTemp == '\\' ) + pTemp++; + pTemp += (int)Vec_PtrEntry( vNames, 2*v ) - 1; + + // assume operation AND, if vars follow one another + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." ); + return NULL; + } + bTemp = Hop_IthVar( pMan, v ); + Vec_PtrPush( vStackFn, bTemp ); // Cudd_Ref( bTemp ); + Flag = VER_PARSE_FLAG_VAR; + break; + } + + if ( Flag == VER_PARSE_FLAG_ERROR ) + break; // error exit + else if ( Flag == VER_PARSE_FLAG_START ) + continue; // go on parsing + else if ( Flag == VER_PARSE_FLAG_VAR ) + while ( 1 ) + { // check if there are negations in the OpStack + if ( !Vec_IntSize(vStackOp) ) + break; + Oper = Vec_IntPop( vStackOp ); + if ( Oper != VER_PARSE_OPER_NEG ) + { + Vec_IntPush( vStackOp, Oper ); + break; + } + else + { +// Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) ); + Vec_PtrPush( vStackFn, Hop_Not(Vec_PtrPop(vStackFn)) ); + } + } + else // if ( Flag == VER_PARSE_FLAG_OPER ) + while ( 1 ) + { // execute all the operations in the OpStack + // with precedence higher or equal than the last one + Oper1 = Vec_IntPop( vStackOp ); // the last operation + if ( !Vec_IntSize(vStackOp) ) + { // if it is the only operation, push it back + Vec_IntPush( vStackOp, Oper1 ); + break; + } + Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one + if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) ) + { // if Oper2 precedence is higher or equal, execute it + if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper2 ) == NULL ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); + return NULL; + } + Vec_IntPush( vStackOp, Oper1 ); // push the last operation back + } + else + { // if Oper2 precedence is lower, push them back and done + Vec_IntPush( vStackOp, Oper2 ); + Vec_IntPush( vStackOp, Oper1 ); + break; + } + } + } + + if ( Flag != VER_PARSE_FLAG_ERROR ) + { + if ( Vec_PtrSize(vStackFn) ) + { + bFunc = Vec_PtrPop(vStackFn); + if ( !Vec_PtrSize(vStackFn) ) + if ( !Vec_IntSize(vStackOp) ) + { +// Cudd_Deref( bFunc ); + return bFunc; + } + else + sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" ); + else + sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" ); + } + else + sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" ); + } +// Cudd_Ref( bFunc ); +// Cudd_RecursiveDeref( dd, bFunc ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs the operation on the top entries in the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ) +{ + Hop_Obj_t * bArg0, * bArg1, * bArg2, * bFunc; + // perform the given operation + bArg2 = Vec_PtrPop( vStackFn ); + bArg1 = Vec_PtrPop( vStackFn ); + if ( Oper == VER_PARSE_OPER_AND ) + bFunc = Hop_And( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_XOR ) + bFunc = Hop_Exor( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_OR ) + bFunc = Hop_Or( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_EQU ) + bFunc = Hop_Not( Hop_Exor( pMan, bArg1, bArg2 ) ); + else if ( Oper == VER_PARSE_OPER_MUX ) + { + bArg0 = Vec_PtrPop( vStackFn ); +// bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 ); Cudd_Ref( bFunc ); + bFunc = Hop_Mux( pMan, bArg0, bArg1, bArg2 ); +// Cudd_RecursiveDeref( dd, bArg0 ); +// Cudd_Deref( bFunc ); + } + else + return NULL; +// Cudd_Ref( bFunc ); +// Cudd_RecursiveDeref( dd, bArg1 ); +// Cudd_RecursiveDeref( dd, bArg2 ); + Vec_PtrPush( vStackFn, bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns the index of the new variable found.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ) +{ + char * pTemp, * pTemp2; + int nLength, nLength2, i; + // start the string + pTemp = pString; + // find the end of the string delimited by other characters + if ( *pTemp == '\\' ) + { + pString++; + while ( *pTemp && *pTemp != ' ' ) + pTemp++; + } + else + { + while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' && *pTemp != '\r' && *pTemp != '\n' && *pTemp != ',' && *pTemp != '}' && + *pTemp != VER_PARSE_SYM_OPEN && *pTemp != VER_PARSE_SYM_CLOSE && + *pTemp != VER_PARSE_SYM_NEGBEF1 && *pTemp != VER_PARSE_SYM_NEGBEF2 && + *pTemp != VER_PARSE_SYM_AND && *pTemp != VER_PARSE_SYM_OR && *pTemp != VER_PARSE_SYM_XOR && + *pTemp != VER_PARSE_SYM_MUX1 && *pTemp != VER_PARSE_SYM_MUX2 ) + pTemp++; + } + // look for this string in the array + nLength = pTemp - pString; + for ( i = 0; i < Vec_PtrSize(vNames)/2; i++ ) + { + nLength2 = (int)Vec_PtrEntry( vNames, 2*i + 0 ); + if ( nLength2 != nLength ) + continue; + pTemp2 = Vec_PtrEntry( vNames, 2*i + 1 ); + if ( strncmp( pString, pTemp2, nLength ) ) + continue; + return i; + } + // could not find - add and return the number + Vec_PtrPush( vNames, (void *)nLength ); + Vec_PtrPush( vNames, pString ); + return i; +} + +/**Function************************************************************* + + Synopsis [Returns the AIG representation of the reduction formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ) +{ + Hop_Obj_t * pRes; + int v, fCompl; + char Symbol; + + // get the operation + Symbol = *pFormula++; + fCompl = ( Symbol == '~' ); + if ( fCompl ) + Symbol = *pFormula++; + // check the operation + if ( Symbol != '&' && Symbol != '|' && Symbol != '^' ) + { + sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol ); + return NULL; + } + // skip the brace + while ( *pFormula++ != '{' ); + // parse the names + Vec_PtrClear( vNames ); + while ( *pFormula != '}' ) + { + v = Ver_FormulaParserFindVar( pFormula, vNames ); + pFormula += (int)Vec_PtrEntry( vNames, 2*v ); + while ( *pFormula == ' ' || *pFormula == ',' ) + pFormula++; + } + // compute the function + if ( Symbol == '&' ) + pRes = Hop_CreateAnd( pMan, Vec_PtrSize(vNames)/2 ); + else if ( Symbol == '|' ) + pRes = Hop_CreateOr( pMan, Vec_PtrSize(vNames)/2 ); + else if ( Symbol == '^' ) + pRes = Hop_CreateExor( pMan, Vec_PtrSize(vNames)/2 ); + return Hop_NotCond( pRes, fCompl ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/ver/verParse.c b/src/base/ver/verParse.c new file mode 100644 index 00000000..8a78e75b --- /dev/null +++ b/src/base/ver/verParse.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [verParse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Performs some Verilog parsing tasks.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verParse.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Skips the comments of they are present.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSkipComments( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + char Symbol; + // skip spaces + Ver_StreamSkipChars( p, " \t\n\r" ); + if ( !Ver_StreamIsOkey(pMan->pReader) ) + return 1; + // read the first symbol + Symbol = Ver_StreamScanChar( p ); + if ( Symbol != '/' ) + return 1; + Ver_StreamPopChar( p ); + // read the second symbol + Symbol = Ver_StreamScanChar( p ); + if ( Symbol == '/' ) + { // skip till the end of line + Ver_StreamSkipToChars( p, "\n" ); + return Ver_ParseSkipComments( pMan ); + } + if ( Symbol == '*' ) + { // skip till the next occurance of */ + Ver_StreamPopChar( p ); + do { + Ver_StreamSkipToChars( p, "*" ); + Ver_StreamPopChar( p ); + } while ( Ver_StreamScanChar( p ) != '/' ); + Ver_StreamPopChar( p ); + return Ver_ParseSkipComments( pMan ); + } + sprintf( pMan->sError, "Cannot parse after symbol \"/\"." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Parses a Verilog name that can be being with a slash.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_ParseGetName( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + char Symbol; + char * pWord; + if ( !Ver_StreamIsOkey(p) ) + return NULL; + if ( !Ver_ParseSkipComments( pMan ) ) + return NULL; + Symbol = Ver_StreamScanChar( p ); + if ( Symbol == '\\' ) + { + Ver_StreamPopChar( p ); + pWord = Ver_StreamGetWord( p, " " ); + } + else + pWord = Ver_StreamGetWord( p, " \t\n\r(),;" ); + if ( !Ver_ParseSkipComments( pMan ) ) + return NULL; + return pWord; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/ver/verStream.c b/src/base/ver/verStream.c new file mode 100644 index 00000000..7956b13c --- /dev/null +++ b/src/base/ver/verStream.c @@ -0,0 +1,435 @@ +/**CFile**************************************************************** + + FileName [verStream.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Input file stream, which knows nothing about Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define VER_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory +#define VER_OFFSET_SIZE 4096 // 4K - load new data when less than this is left +#define VER_WORD_SIZE 4096 // 4K - the largest token that can be returned + +#define VER_MINIMUM(a,b) (((a) < (b))? (a) : (b)) + +struct Ver_Stream_t_ +{ + // the input file + char * pFileName; // the input file name + FILE * pFile; // the input file pointer + int nFileSize; // the total number of bytes in the file + int nFileRead; // the number of bytes currently read from file + int nLineCounter; // the counter of lines processed + // temporary storage for data + char * pBuffer; // the buffer + int nBufferSize; // the size of the buffer + char * pBufferCur; // the current reading position + char * pBufferEnd; // the first position not used by currently loaded data + char * pBufferStop; // the position where loading new data will be done + // tokens given to the user + char pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parantheses) + int nChars; // the total number of characters in the word + // status of the parser + int fStop; // this flag goes high when the end of file is reached +}; + +static void Ver_StreamReload( Ver_Stream_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the file reader for the given file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ver_Stream_t * Ver_StreamAlloc( char * pFileName ) +{ + Ver_Stream_t * p; + FILE * pFile; + int nCharsToRead; + // check if the file can be opened + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName ); + return NULL; + } + // start the file reader + p = ALLOC( Ver_Stream_t, 1 ); + memset( p, 0, sizeof(Ver_Stream_t) ); + p->pFileName = pFileName; + p->pFile = pFile; + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + p->nFileSize = ftell( pFile ); + rewind( pFile ); + // allocate the buffer + p->pBuffer = ALLOC( char, VER_BUFFER_SIZE+1 ); + p->nBufferSize = VER_BUFFER_SIZE; + p->pBufferCur = p->pBuffer; + // determine how many chars to read + nCharsToRead = VER_MINIMUM(p->nFileSize, VER_BUFFER_SIZE); + // load the first part into the buffer + fread( p->pBuffer, nCharsToRead, 1, p->pFile ); + p->nFileRead = nCharsToRead; + // set the ponters to the end and the stopping point + p->pBufferEnd = p->pBuffer + nCharsToRead; + p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; + // start the arrays + p->nLineCounter = 1; // 1-based line counting + return p; +} + +/**Function************************************************************* + + Synopsis [Loads new data into the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamReload( Ver_Stream_t * p ) +{ + int nCharsUsed, nCharsToRead; + assert( !p->fStop ); + assert( p->pBufferCur > p->pBufferStop ); + assert( p->pBufferCur < p->pBufferEnd ); + // figure out how many chars are still not processed + nCharsUsed = p->pBufferEnd - p->pBufferCur; + // move the remaining data to the beginning of the buffer + memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); + p->pBufferCur = p->pBuffer; + // determine how many chars we will read + nCharsToRead = VER_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); + // read the chars + fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); + p->nFileRead += nCharsToRead; + // set the ponters to the end and the stopping point + p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; + p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; +} + +/**Function************************************************************* + + Synopsis [Stops the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamFree( Ver_Stream_t * p ) +{ + if ( p->pFile ) + fclose( p->pFile ); + FREE( p->pBuffer ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_StreamGetFileName( Ver_Stream_t * p ) +{ + return p->pFileName; +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetFileSize( Ver_Stream_t * p ) +{ + return p->nFileSize; +} + +/**Function************************************************************* + + Synopsis [Returns the current reading position.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetCurPosition( Ver_Stream_t * p ) +{ + return p->nFileRead - (p->pBufferEnd - p->pBufferCur); +} + +/**Function************************************************************* + + Synopsis [Returns the line number for the given token.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetLineNumber( Ver_Stream_t * p ) +{ + return p->nLineCounter; +} + + + +/**Function************************************************************* + + Synopsis [Returns current symbol.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamIsOkey( Ver_Stream_t * p ) +{ + return !p->fStop; +} + +/**Function************************************************************* + + Synopsis [Returns current symbol.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Ver_StreamScanChar( Ver_Stream_t * p ) +{ + assert( !p->fStop ); + return *p->pBufferCur; +} + +/**Function************************************************************* + + Synopsis [Returns current symbol and moves to the next.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Ver_StreamPopChar( Ver_Stream_t * p ) +{ + assert( !p->fStop ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // check if there are symbols left + if ( p->pBufferCur == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return -1; + } + return *p->pBufferCur++; +} + +/**Function************************************************************* + + Synopsis [Skips the current symbol and all symbols from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ) +{ + char * pChar, * pTemp; + assert( !p->fStop ); + assert( pCharsToSkip != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + // skip symbols as long as they are in the list + for ( pTemp = pCharsToSkip; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + { + p->pBufferCur = pChar; + return; + } + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return; + } + printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName ); +} + +/**Function************************************************************* + + Synopsis [Skips all symbols until encountering one from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ) +{ + char * pChar, * pTemp; + assert( !p->fStop ); + assert( pCharsToStop != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + // skip symbols as long as they are NOT in the list + for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + continue; + // the symbol is found - move position and return + p->pBufferCur = pChar; + return; + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return; + } + printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName ); +} + +/**Function************************************************************* + + Synopsis [Returns current word delimited by the set of symbols.] + + Description [Modifies the stream by inserting 0 at the first encounter + of one of the symbols in the list.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ) +{ + char * pChar, * pTemp; + if ( p->fStop ) + return NULL; + assert( pCharsToStop != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + p->nChars = 0; + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + // skip symbols as long as they are NOT in the list + for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + { + p->pChars[p->nChars++] = *pChar; + if ( p->nChars == VER_WORD_SIZE ) + return NULL; + continue; + } + // the symbol is found - move the position, set the word end, return the word + p->pBufferCur = pChar; + p->pChars[p->nChars] = 0; + return p->pChars; + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + p->pChars[p->nChars] = 0; + return p->pChars; + } + printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName ); + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/ver/verWords.c b/src/base/ver/verWords.c new file mode 100644 index 00000000..f9d27010 --- /dev/null +++ b/src/base/ver/verWords.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [verWords.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Handles keywords that are currently supported.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verWords.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/ver/ver_.c b/src/base/ver/ver_.c new file mode 100644 index 00000000..76599dac --- /dev/null +++ b/src/base/ver/ver_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [ver_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Parses several flavors of structural Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: ver_.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/fpga/fpga.h b/src/map/fpga/fpga.h index d89f6dc9..188420b1 100644 --- a/src/map/fpga/fpga.h +++ b/src/map/fpga/fpga.h @@ -32,7 +32,7 @@ extern "C" { //////////////////////////////////////////////////////////////////////// // the maximum size of LUTs used for mapping -#define FPGA_MAX_LUTSIZE 10 +#define FPGA_MAX_LUTSIZE 32 //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// diff --git a/src/map/fpga/fpgaCut.c b/src/map/fpga/fpgaCut.c index 3bb5feb4..c2aba4a3 100644 --- a/src/map/fpga/fpgaCut.c +++ b/src/map/fpga/fpgaCut.c @@ -684,7 +684,8 @@ int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNo { min = i; for ( k = i+1; k < nTotal; k++ ) - if ( ppNodes[k] < ppNodes[min] ) +// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!) + if ( ppNodes[k]->Num < ppNodes[min]->Num ) min = k; pNodeTemp = ppNodes[i]; ppNodes[i] = ppNodes[min]; diff --git a/src/map/if/if.h b/src/map/if/if.h new file mode 100644 index 00000000..04e1541e --- /dev/null +++ b/src/map/if/if.h @@ -0,0 +1,255 @@ +/**CFile**************************************************************** + + FileName [if.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: if.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IF_H__ +#define __IF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "vec.h" +#include "mem.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// the maximum size of LUTs used for mapping (should be the same as FPGA_MAX_LUTSIZE defined in "fpga.h"!!!) +#define IF_MAX_LUTSIZE 32 + +// object types +typedef enum { + IF_NONE, // 0: non-existent object + IF_CONST1, // 1: constant 1 + IF_PI, // 2: primary input + IF_PO, // 3: primary output + IF_AND, // 4: AND node + IF_BI, // 5: box input + IF_BO, // 6: box output + IF_BOX, // 7: box + IF_VOID // 8: unused object +} Hop_Type_t; + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct If_Par_t_ If_Par_t; +typedef struct If_Lib_t_ If_Lib_t; +typedef struct If_Man_t_ If_Man_t; +typedef struct If_Obj_t_ If_Obj_t; +typedef struct If_Cut_t_ If_Cut_t; + +// parameters +struct If_Par_t_ +{ + int Mode; // the mapping mode + int nLutSize; // the LUT size + If_Lib_t * pLutLib; // the LUT library + int nCutsMax; // the max number of cuts + int fVerbose; // the verbosity flag + int fSeq; // sequential mapping + int fLatchPaths; // reset timing on latch paths + int nLatches; // the number of latches + float DelayTarget; // delay target + float * pTimesArr; // arrival times + float * pTimesReq; // required times +}; + +// the LUT library +struct If_Lib_t_ +{ + char * pName; // the name of the LUT library + int LutMax; // the maximum LUT size + float pLutAreas[IF_MAX_LUTSIZE+1]; // the areas of LUTs + float pLutDelays[IF_MAX_LUTSIZE+1];// the delays of LUTs +}; + +// manager +struct If_Man_t_ +{ + // mapping parameters + If_Par_t * pPars; + // mapping nodes + If_Obj_t * pConst1; // the constant 1 node + Vec_Ptr_t * vPis; // the primary inputs + Vec_Ptr_t * vPos; // the primary outputs + Vec_Ptr_t * vObjs; // all objects + Vec_Ptr_t * vMapped; // objects used in the mapping + Vec_Ptr_t * vTemp; // temporary array + int nObjs[IF_VOID];// the number of objects by type + // various data + int nLevelMax; // the max number of AIG levels + float fEpsilon; // epsilon used for comparison + float RequiredGlo; // global required times + float AreaGlo; // global area + // memory management + Mem_Fixed_t * pMem; // memory manager + int nEntrySize; // the size of the entry + int nEntryBase; // the size of the entry minus cut leaf arrays + // temporary cut storage + int nCuts; // the number of cuts used + If_Cut_t ** ppCuts; // the storage space for cuts +}; + +// priority cut +struct If_Cut_t_ +{ + float Delay; // the delay of the cut + float Flow; // the area flow of the cut + float Area; // the area of the cut + If_Cut_t * pOne; // the parent cut + If_Cut_t * pTwo; // the parent cut + char fCompl0; // the complemented attribute + char fCompl1; // the complemented attribute + char Phase; // the complemented attribute + char nLeaves; // the number of leaves + int * pLeaves; // the array of fanins +}; + +// node extension +struct If_Obj_t_ +{ + unsigned Type : 4; // object + unsigned fCompl0 : 1; // complemented attribute + unsigned fCompl1 : 1; // complemented attribute + unsigned fPhase : 1; // phase of the node + unsigned fMark : 1; // multipurpose mark + unsigned Level : 24; // logic level of the node + int Id; // integer ID + int nRefs; // the number of references + short nCuts; // the number of cuts + short iCut; // the number of the best cut + If_Obj_t * pFanin0; // the first fanin + If_Obj_t * pFanin1; // the second fanin + If_Obj_t * pEquiv; // the choice node + float EstRefs; // estimated reference counter + float Required; // required time of the onde + void * pCopy; // used for duplication + If_Cut_t Cuts[0]; // the cuts of the node +}; + +static inline If_Obj_t * If_ManConst1( If_Man_t * p ) { return p->pConst1; } +static inline If_Obj_t * If_ManPi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vPis, i ); } +static inline If_Obj_t * If_ManPo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vPos, i ); } +static inline If_Obj_t * If_ManObj( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } +static inline If_Cut_t * If_ManCut( If_Man_t * p, int i ) { return p->ppCuts[i]; } + +static inline int If_ObjIsConst1( If_Obj_t * pObj ) { return pObj->Type == IF_CONST1; } +static inline int If_ObjIsPi( If_Obj_t * pObj ) { return pObj->Type == IF_PI; } +static inline int If_ObjIsPo( If_Obj_t * pObj ) { return pObj->Type == IF_PO; } +static inline int If_ObjIsAnd( If_Obj_t * pObj ) { return pObj->Type == IF_AND; } +static inline int If_ObjIsBi( If_Obj_t * pObj ) { return pObj->Type == IF_BI; } +static inline int If_ObjIsBo( If_Obj_t * pObj ) { return pObj->Type == IF_BO; } +static inline int If_ObjIsBox( If_Obj_t * pObj ) { return pObj->Type == IF_BOX; } + +static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj ) { return pObj->pFanin0; } +static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj ) { return pObj->pFanin1; } +static inline int If_ObjFaninC0( If_Obj_t * pObj ) { return pObj->fCompl0; } +static inline int If_ObjFaninC1( If_Obj_t * pObj ) { return pObj->fCompl1; } +static inline void * If_ObjCopy( If_Obj_t * pObj ) { return pObj->pCopy; } +static inline void If_ObjSetCopy( If_Obj_t * pObj, void * pCopy ) { pObj->pCopy = pCopy; } +static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu; } + +static inline If_Cut_t * If_ObjCut( If_Obj_t * pObj, int iCut ) { return pObj->Cuts + iCut; } +static inline If_Cut_t * If_ObjCutTriv( If_Obj_t * pObj ) { return pObj->Cuts; } +static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return pObj->Cuts + pObj->iCut; } + +static inline void * If_CutData( If_Cut_t * pCut ) { return *(void **)pCut; } +static inline void If_CutSetData( If_Cut_t * pCut, void * pData ) { *(void **)pCut = pData; } + +static inline float If_CutLutDelay( If_Man_t * p, If_Cut_t * pCut ) { return p->pPars->pLutLib? p->pPars->pLutLib->pLutDelays[pCut->nLeaves] : (float)1.0; } +static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IF_MIN(a,b) (((a) < (b))? (a) : (b)) +#define IF_MAX(a,b) (((a) > (b))? (a) : (b)) + +// the small and large numbers (min/max float are 1.17e-38/3.40e+38) +#define IF_FLOAT_LARGE ((float)1.0e+20) +#define IF_FLOAT_SMALL ((float)1.0e-20) +#define IF_INT_LARGE (10000000) + +// iterator over the primary inputs +#define If_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPis, pObj, i ) +// iterator over the primary outputs +#define If_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPos, pObj, i ) +// iterator over the latches +#define If_ManForEachLatch( p, pObj, i ) \ + Vec_PtrForEachEntryStart( p->vPos, pObj, i, p->pPars->nLatches ) +// iterator over all objects, including those currently not used +#define If_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) +// iterator over logic nodes (AND and EXOR gates) +#define If_ManForEachNode( p, pObj, i ) \ + If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else +// iterator over cuts of the node +#define If_ObjForEachCut( pObj, pCut, i ) \ + for ( i = 0; (i < (int)(pObj)->nCuts) && ((pCut) = (pObj)->Cuts + i); i++ ) +// iterator over cuts of the node +#define If_ObjForEachCutStart( pObj, pCut, i, Start ) \ + for ( i = Start; (i < (int)(pObj)->nCuts) && ((pCut) = (pObj)->Cuts + i); i++ ) +// iterator leaves of the cut +#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \ + for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== ifMan.c ==========================================================*/ +extern If_Man_t * If_ManStart( If_Par_t * pPars ); +extern void If_ManStop( If_Man_t * p ); +extern If_Obj_t * If_ManCreatePi( If_Man_t * p ); +extern If_Obj_t * If_ManCreatePo( If_Man_t * p, If_Obj_t * pDriver, int fCompl0 ); +extern If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_t * pFan1, int fCompl1 ); +/*=== ifMap.c ==========================================================*/ +extern int If_ManPerformMapping( If_Man_t * p ); +/*=== ifUtil.c ==========================================================*/ +extern float If_ManDelayMax( If_Man_t * p ); +extern void If_ManCleanNodeCopy( If_Man_t * p ); +extern void If_ManCleanCutData( If_Man_t * p ); +extern float If_ManScanMapping( If_Man_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c new file mode 100644 index 00000000..4d7e92d0 --- /dev/null +++ b/src/map/if/ifCore.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [ifCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [The central part of the mapper.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifCore.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c new file mode 100644 index 00000000..0318e5e5 --- /dev/null +++ b/src/map/if/ifCut.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [ifCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifCut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c new file mode 100644 index 00000000..616c5cf6 --- /dev/null +++ b/src/map/if/ifMan.c @@ -0,0 +1,250 @@ +/**CFile**************************************************************** + + FileName [ifMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Mapping manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifMan.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static If_Obj_t * If_ManSetupObj( If_Man_t * p ); +static If_Cut_t ** If_ManSetupCuts( If_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Man_t * If_ManStart( If_Par_t * pPars ) +{ + If_Man_t * p; + // start the manager + p = ALLOC( If_Man_t, 1 ); + memset( p, 0, sizeof(If_Man_t) ); + p->pPars = pPars; + p->fEpsilon = (float)0.001; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + p->vObjs = Vec_PtrAlloc( 100 ); + p->vMapped = Vec_PtrAlloc( 100 ); + p->vTemp = Vec_PtrAlloc( 100 ); + // prepare the memory manager + p->nEntrySize = sizeof(If_Obj_t) + p->pPars->nCutsMax * (sizeof(If_Cut_t) + sizeof(int) * p->pPars->nLutSize); + p->nEntryBase = sizeof(If_Obj_t) + p->pPars->nCutsMax * (sizeof(If_Cut_t)); + p->pMem = Mem_FixedStart( p->nEntrySize ); + // create the constant node + p->pConst1 = If_ManSetupObj( p ); + p->pConst1->Type = IF_CONST1; + p->pConst1->fPhase = 1; + // create temporary cuts + p->ppCuts = If_ManSetupCuts( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManStop( If_Man_t * p ) +{ + If_Cut_t * pTemp; + int i; + Vec_PtrFree( p->vPis ); + Vec_PtrFree( p->vPos ); + Vec_PtrFree( p->vObjs ); + Vec_PtrFree( p->vMapped ); + Vec_PtrFree( p->vTemp ); + Mem_FixedStop( p->pMem, 0 ); + // free pars memory + if ( p->pPars->pTimesArr ) + FREE( p->pPars->pTimesArr ); + if ( p->pPars->pTimesReq ) + FREE( p->pPars->pTimesReq ); + // free temporary cut memory + pTemp = p->ppCuts[0]; + for ( i = 1; i < p->pPars->nCutsMax * p->pPars->nCutsMax; i++ ) + if ( pTemp > p->ppCuts[i] ) + pTemp = p->ppCuts[i]; + free( pTemp ); + free( p->ppCuts ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManCreatePi( If_Man_t * p ) +{ + If_Obj_t * pObj; + pObj = If_ManSetupObj( p ); + pObj->Type = IF_PI; + Vec_PtrPush( p->vPis, pObj ); + p->nObjs[IF_PI]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary output with the given driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManCreatePo( If_Man_t * p, If_Obj_t * pDriver, int fCompl0 ) +{ + If_Obj_t * pObj; + pObj = If_ManSetupObj( p ); + pObj->Type = IF_PO; + pObj->fCompl0 = fCompl0; + Vec_PtrPush( p->vPos, pObj ); + pObj->pFanin0 = pDriver; pDriver->nRefs++; + p->nObjs[IF_PO]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_t * pFan1, int fCompl1 ) +{ + If_Obj_t * pObj; + // get memory for the new object + pObj = If_ManSetupObj( p ); + pObj->Type = IF_AND; + pObj->fCompl0 = fCompl0; + pObj->fCompl1 = fCompl1; + pObj->pFanin0 = pFan0; pFan0->nRefs++; + pObj->pFanin1 = pFan1; pFan1->nRefs++; + pObj->fPhase = (fCompl0? !pFan0->fPhase : pFan0->fPhase) & (fCompl1? !pFan1->fPhase : pFan1->fPhase); + pObj->Level = 1 + IF_MAX( pFan0->Level, pFan1->Level ); + if ( p->nLevelMax < (int)pObj->Level ) + p->nLevelMax = (int)pObj->Level; + p->nObjs[IF_AND]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Prepares memory for the node with cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManSetupObj( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i, * pArrays; + // get memory for the object + pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMem ); + memset( pObj, 0, p->nEntryBase ); + // organize memory + pArrays = (int *)((char *)pObj + p->nEntryBase); + for ( i = 0; i < p->pPars->nCutsMax; i++ ) + pObj->Cuts[i].pLeaves = pArrays + i * p->pPars->nLutSize; + // assign ID and save + pObj->Id = Vec_PtrSize(p->vObjs); + Vec_PtrPush( p->vObjs, pObj ); + // assign elementary cut + pObj->nCuts = 1; + pObj->Cuts[0].nLeaves = 1; + pObj->Cuts[0].pLeaves[0] = pObj->Id; + pObj->iCut = 0; + // set the required times + pObj->Required = IF_FLOAT_LARGE; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Prepares memory for additional cuts of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Cut_t ** If_ManSetupCuts( If_Man_t * p ) +{ + If_Cut_t ** pCutStore; + int * pArrays, nCutSize, nCutsTotal, i; + nCutsTotal = p->pPars->nCutsMax * p->pPars->nCutsMax; + nCutSize = sizeof(If_Cut_t) + sizeof(int) * p->pPars->nLutSize; + pCutStore = (If_Cut_t **)ALLOC( If_Cut_t *, (nCutsTotal + 1) ); + memset( pCutStore, 0, sizeof(If_Cut_t *) * (nCutsTotal + 1) ); + pCutStore[0] = (If_Cut_t *)ALLOC( char, nCutSize * nCutsTotal ); + memset( pCutStore[0], 0, nCutSize * nCutsTotal ); + for ( i = 1; i < nCutsTotal; i++ ) + pCutStore[i] = (If_Cut_t *)((char *)pCutStore[0] + sizeof(If_Cut_t) * i); + pArrays = (int *)((char *)pCutStore[0] + sizeof(If_Cut_t) * nCutsTotal); + for ( i = 0; i < nCutsTotal; i++ ) + pCutStore[i]->pLeaves = pArrays + i * p->pPars->nLutSize; + return pCutStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c new file mode 100644 index 00000000..5f2c4133 --- /dev/null +++ b/src/map/if/ifMap.c @@ -0,0 +1,391 @@ +/**CFile**************************************************************** + + FileName [ifMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Mapping procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifMap.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutMerge( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC, int nLimit ) +{ + int i, k, c; + assert( pC0->nLeaves >= pC1->nLeaves ); + // the case of the largest cut sizes + if ( pC0->nLeaves == nLimit && pC1->nLeaves == nLimit ) + { + for ( i = 0; i < pC0->nLeaves; i++ ) + if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) + return 0; + for ( i = 0; i < pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + return 1; + } + // the case when one of the cuts is the largest + if ( pC0->nLeaves == nLimit ) + { + for ( i = 0; i < pC1->nLeaves; i++ ) + { + for ( k = pC0->nLeaves - 1; k >= 0; k-- ) + if ( pC0->pLeaves[k] == pC1->pLeaves[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < nLimit; c++ ) + { + if ( k == pC1->nLeaves ) + { + if ( i == pC0->nLeaves ) + { + pC->nLeaves = c; + return 1; + } + pC->pLeaves[c] = pC0->pLeaves[i++]; + continue; + } + if ( i == pC0->nLeaves ) + { + if ( k == pC1->nLeaves ) + { + pC->nLeaves = c; + return 1; + } + pC->pLeaves[c] = pC1->pLeaves[k++]; + continue; + } + if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) + { + pC->pLeaves[c] = pC0->pLeaves[i++]; + continue; + } + if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) + { + pC->pLeaves[c] = pC1->pLeaves[k++]; + continue; + } + pC->pLeaves[c] = pC0->pLeaves[i++]; + k++; + } + if ( i < pC0->nLeaves || k < pC1->nLeaves ) + return 0; + pC->nLeaves = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutCompareDelay( If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) +{ + If_Cut_t * pC0 = *ppC0; + If_Cut_t * pC1 = *ppC1; + if ( pC0->Delay < pC1->Delay ) + return -1; + if ( pC0->Delay > pC1->Delay ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Flow < pC1->Flow ) + return -1; + if ( pC0->Flow > pC1->Flow ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutCompareArea( If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) +{ + If_Cut_t * pC0 = *ppC0; + If_Cut_t * pC1 = *ppC1; + if ( pC0->Flow < pC1->Flow ) + return -1; + if ( pC0->Flow > pC1->Flow ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Delay < pC1->Delay ) + return -1; + if ( pC0->Delay > pC1->Delay ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Computes delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutDelay( If_Man_t * p, If_Cut_t * pCut ) +{ + If_Obj_t * pLeaf; + float Delay; + int i; + Delay = -IF_FLOAT_LARGE; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + Delay = IF_MAX( Delay, If_ObjCutBest(pLeaf)->Delay ); + return Delay + If_CutLutDelay(p, pCut); +} + +/**Function************************************************************* + + Synopsis [Computes area flow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutFlow( If_Man_t * p, If_Cut_t * pCut ) +{ + If_Obj_t * pLeaf; + float Flow; + int i; + Flow = If_CutLutArea(p, pCut); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + Flow += If_ObjCutBest(pLeaf)->Flow / pLeaf->EstRefs; + return Flow; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutArea1( If_Man_t * p, If_Cut_t * pCut ) +{ + If_Obj_t * pLeaf; + float Area; + int i; + Area = If_CutLutArea(p, pCut); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + if ( pLeaf->nRefs == 0 ) + Area += If_CutLutArea(p, If_ObjCutBest(pLeaf)); + return Area; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutRef1( If_Man_t * p, If_Cut_t * pCut ) +{ + If_Obj_t * pLeaf; + int i; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + pLeaf->nRefs++; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutDeref1( If_Man_t * p, If_Cut_t * pCut ) +{ + If_Obj_t * pLeaf; + int i; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + pLeaf->nRefs--; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc ) +{ + int * pArray; + pArray = pCutDest->pLeaves; + *pCutDest = *pCutSrc; + pCutDest->pLeaves = pArray; + memcpy( pCutDest->pLeaves, pCutSrc->pLeaves, sizeof(int) * pCutSrc->nLeaves ); +} + +/**Function************************************************************* + + Synopsis [Finds the best cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ObjPerformMapping( If_Man_t * p, If_Obj_t * pObj ) +{ + If_Cut_t * pCut0, * pCut1, * pCut; + int i, k; + // create cross-product of the cuts + p->nCuts = 0; + pCut = p->ppCuts[0]; + If_ObjForEachCut( pObj->pFanin0, pCut0, i ) + If_ObjForEachCut( pObj->pFanin1, pCut1, k ) + { + if ( pCut0->nLeaves < pCut1->nLeaves ) + { + if ( !If_CutMerge( pCut1, pCut0, pCut, p->pPars->nLutSize ) ) + continue; + } + else + { + if ( !If_CutMerge( pCut0, pCut1, pCut, p->pPars->nLutSize ) ) + continue; + } + // the cuts have been successfully merged + pCut->pOne = pCut0; pCut->fCompl0 = pObj->fCompl0; + pCut->pTwo = pCut1; pCut->fCompl1 = pObj->fCompl1; +// pCut->Phase = ... + pCut->Delay = If_CutDelay( p, pCut ); + pCut->Flow = If_CutFlow( p, pCut ); + // prepare room for the next cut + pCut = p->ppCuts[++p->nCuts]; + } + // sort the cuts + if ( p->pPars->Mode == 1 ) // delay + qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay ); + else + qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea ); + // take the first + pObj->nCuts = IF_MIN( p->nCuts + 1, p->pPars->nCutsMax ); + If_ObjForEachCutStart( pObj, pCut, i, 1 ) + If_CutCopy( pCut, p->ppCuts[i-1] ); + pObj->iCut = 1; +} + +/**Function************************************************************* + + Synopsis [Maps the nodes for delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManPerformMapping( If_Man_t * p ) +{ + If_Obj_t * pObj; + float DelayBest; + int i, clk = clock(); + // set arrival times and trivial cuts at const 1 and PIs + If_ManConst1(p)->Cuts[0].Delay = 0.0; + If_ManForEachPi( p, pObj, i ) + pObj->Cuts[0].Delay = p->pPars->pTimesArr[i]; + // set the initial fanout estimates + If_ManForEachObj( p, pObj, i ) + pObj->EstRefs = (float)pObj->nRefs; + // map the internal nodes + If_ManForEachNode( p, pObj, i ) + If_ObjPerformMapping( p, pObj ); + // get the best arrival time of the POs + DelayBest = If_ManDelayMax(p); + printf( "Best delay = %d. ", (int)DelayBest ); + PRT( "Time", clock() - clk ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/if/ifUtil.c b/src/map/if/ifUtil.c new file mode 100644 index 00000000..1144fa3f --- /dev/null +++ b/src/map/if/ifUtil.c @@ -0,0 +1,229 @@ +/**CFile**************************************************************** + + FileName [ifUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifUtil.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the max delay of the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_ManDelayMax( If_Man_t * p ) +{ + If_Obj_t * pObj; + float DelayBest; + int i; + DelayBest = -IF_FLOAT_LARGE; + If_ManForEachPo( p, pObj, i ) + if ( DelayBest < If_ObjCutBest( If_ObjFanin0(pObj) )->Delay ) + DelayBest = If_ObjCutBest( If_ObjFanin0(pObj) )->Delay; + return DelayBest; +} + +/**Function************************************************************* + + Synopsis [Sets all the node copy to NULL.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCleanNodeCopy( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i; + If_ManForEachObj( p, pObj, i ) + If_ObjSetCopy( pObj, NULL ); +} + +/**Function************************************************************* + + Synopsis [Sets all the cut data to NULL.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCleanCutData( If_Man_t * p ) +{ + If_Obj_t * pObj; + If_Cut_t * pCut; + int i, k; + If_ManForEachObj( p, pObj, i ) + If_ObjForEachCut( pObj, pCut, k ) + If_CutSetData( pCut, NULL ); +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_ManScanMapping_rec( If_Man_t * p, If_Obj_t * pObj, If_Obj_t ** ppStore ) +{ + If_Obj_t * pLeaf; + If_Cut_t * pCutBest; + float aArea; + int i; + if ( pObj->nRefs++ || If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) ) + return 0.0; + // store the node in the structure by level + assert( If_ObjIsAnd(pObj) ); + pObj->pCopy = (char *)ppStore[pObj->Level]; + ppStore[pObj->Level] = pObj; + // visit the transitive fanin of the selected cut + pCutBest = If_ObjCutBest(pObj); + aArea = If_CutLutArea( p, pCutBest ); + If_CutForEachLeaf( p, pCutBest, pLeaf, i ) + aArea += If_ManScanMapping_rec( p, pLeaf, ppStore ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [Collects the nodes in reverse topological order in array + p->vMapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_ManScanMapping( If_Man_t * p ) +{ + If_Obj_t * pObj, ** ppStore; + float aArea; + int i; + // clean all references + If_ManForEachObj( p, pObj, i ) + { + pObj->Required = IF_FLOAT_LARGE; + pObj->nRefs = 0; + } + // allocate place to store the nodes + ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 ); + memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); + // collect nodes reachable from POs in the DFS order through the best cuts + aArea = 0; + If_ManForEachPo( p, pObj, i ) + aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore ); + // reconnect the nodes in reverse topological order + Vec_PtrClear( p->vMapped ); + for ( i = p->nLevelMax; i >= 0; i-- ) + for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy ) + Vec_PtrPush( p->vMapped, pObj ); + free( ppStore ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes the required times of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManComputeRequired( If_Man_t * p, int fFirstTime ) +{ + If_Obj_t * pObj, * pLeaf; + If_Cut_t * pCutBest; + float Required; + int i, k; + // compute area, clean required times, collect nodes used in the mapping + p->AreaGlo = If_ManScanMapping( p ); + // get the global required times + p->RequiredGlo = If_ManDelayMax( p ); + // update the required times according to the target + if ( p->pPars->DelayTarget != -1 ) + { + if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon ) + { + if ( fFirstTime ) + printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget ); + } + else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon ) + { + if ( fFirstTime ) + printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget ); + p->RequiredGlo = p->pPars->DelayTarget; + } + } + // set the required times for the POs + if ( p->pPars->fLatchPaths ) + { + If_ManForEachLatch( p, pObj, i ) + If_ObjFanin0(pObj)->Required = p->RequiredGlo; + } + else + { + If_ManForEachPo( p, pObj, i ) + If_ObjFanin0(pObj)->Required = p->RequiredGlo; + } + // go through the nodes in the reverse topological order + Vec_PtrForEachEntry( p->vMapped, pObj, k ) + { + // get the best cut of the node + pCutBest = If_ObjCutBest(pObj); + // get the required times for the leaves of the cut + Required = pObj->Required - If_CutLutDelay( p, pCutBest ); + // update the required time of the leaves + If_CutForEachLeaf( p, pCutBest, pLeaf, i ) + pLeaf->Required = IF_MIN( pLeaf->Required, Required ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/if/if_.c b/src/map/if/if_.c new file mode 100644 index 00000000..d2960077 --- /dev/null +++ b/src/map/if/if_.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [if_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: if_.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/if/module.make b/src/map/if/module.make new file mode 100644 index 00000000..be044da2 --- /dev/null +++ b/src/map/if/module.make @@ -0,0 +1,4 @@ +SRC += src/map/if/ifCore.c \ + src/map/if/ifMan.c \ + src/map/if/ifMap.c \ + src/map/if/ifUtil.c diff --git a/src/map/pga/module.make b/src/map/pga/module.make deleted file mode 100644 index 2a45327e..00000000 --- a/src/map/pga/module.make +++ /dev/null @@ -1,4 +0,0 @@ -SRC += src/map/pga/pgaCore.c \ - src/map/pga/pgaMan.c \ - src/map/pga/pgaMatch.c \ - src/map/pga/pgaUtil.c diff --git a/src/map/pga/pga.h b/src/map/pga/pga.h deleted file mode 100644 index 4b2a9df4..00000000 --- a/src/map/pga/pga.h +++ /dev/null @@ -1,80 +0,0 @@ -/**CFile**************************************************************** - - FileName [pga.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapper.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pga.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PGA_H__ -#define __PGA_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Pga_ManStruct_t_ Pga_Man_t; -typedef struct Pga_ParamsStruct_t_ Pga_Params_t; - -struct Pga_ParamsStruct_t_ -{ - // data for mapping - Abc_Ntk_t * pNtk; // the network to be mapped - Fpga_LutLib_t * pLutLib; // the LUT library - float * pSwitching; // switching activity for each node - // mapping parameters - int fDropCuts; // enables cut dropping - int fAreaFlow; // enables area flow minimization - int fArea; // enables area minimization - int fSwitching; // enables switching activity minimization - int fVerbose; // enables verbose output -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== pgaApi.c ==========================================================*/ -extern Vec_Ptr_t * Pga_DoMapping( Pga_Man_t * p ); -/*=== pgaMan.c ==========================================================*/ -extern Pga_Man_t * Pga_ManStart( Pga_Params_t * pParams ); -extern void Pga_ManStop( Pga_Man_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/pga/pgaCore.c b/src/map/pga/pgaCore.c deleted file mode 100644 index 240c24fd..00000000 --- a/src/map/pga/pgaCore.c +++ /dev/null @@ -1,152 +0,0 @@ -/**CFile**************************************************************** - - FileName [pgaCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapper.] - - Synopsis [External APIs of the FPGA manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pgaCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Pga_MappingInitCis( Pga_Man_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs technology mapping for the given object graph.] - - Description [The object graph is stored in the mapping manager. - First, all the AND-nodes, which fanout into the POs, are collected - in the DFS fashion. Next, three steps are performed: the k-feasible - cuts are computed for each node, the truth tables are computed for - each cut, and the delay-optimal matches are assigned for each node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Pga_DoMapping( Pga_Man_t * p ) -{ - int fShowSwitching = 0; - float aAreaTotalCur; - int Iter, clk, clkTotal = clock(); - - // assign the arrival times of the PIs - Pga_MappingInitCis( p ); - - // map the AIG for delay -clk = clock(); - Pga_MappingMatches( p, 0 ); -p->timeDelay = clock() - clk; - - // compute area, set references, and collect nodes used in the mapping - Iter = 1; - aAreaTotalCur = Pga_MappingSetRefsAndArea( p ); -if ( p->pParams->fVerbose ) -{ -printf( "Iteration %dD : Area = %8.1f ", Iter++, aAreaTotalCur ); -if ( fShowSwitching ) -printf( "Switch = %8.1f ", Pga_MappingGetSwitching(p) ); -PRT( "Time", p->timeDelay ); -} - - if ( p->pParams->fAreaFlow ) - { -clk = clock(); - // compute the required times and the fanouts - Pga_MappingComputeRequired( p ); - // remap topologically - Pga_MappingMatches( p, 1 ); -p->timeAreaFlow = clock() - clk; - // get the resulting area - aAreaTotalCur = Pga_MappingSetRefsAndArea( p ); - // note that here we do not update the reference counter - // for some reason, this works better on benchmarks -if ( p->pParams->fVerbose ) -{ -printf( "Iteration %dF : Area = %8.1f ", Iter++, aAreaTotalCur ); -if ( fShowSwitching ) -printf( "Switch = %8.1f ", Pga_MappingGetSwitching(p) ); -PRT( "Time", p->timeAreaFlow ); -} - } - - if ( p->pParams->fArea ) - { -clk = clock(); - // compute the required times and the fanouts - Pga_MappingComputeRequired( p ); - // remap topologically - if ( p->pParams->fSwitching ) - Pga_MappingMatches( p, 3 ); - else - Pga_MappingMatches( p, 2 ); -p->timeArea = clock() - clk; - // get the resulting area - aAreaTotalCur = Pga_MappingSetRefsAndArea( p ); -if ( p->pParams->fVerbose ) -{ -printf( "Iteration %d%s : Area = %8.1f ", Iter++, (p->pParams->fSwitching?"S":"A"), aAreaTotalCur ); -if ( fShowSwitching ) -printf( "Switch = %8.1f ", Pga_MappingGetSwitching(p) ); -PRT( "Time", p->timeArea ); -} - } - p->AreaGlobal = aAreaTotalCur; - - if ( p->pParams->fVerbose ) - Pga_MappingPrintOutputArrivals( p ); - - // return the mapping - return Pga_MappingResults( p ); -} - -/**Function************************************************************* - - Synopsis [Initializes the CI node arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pga_MappingInitCis( Pga_Man_t * p ) -{ - Pga_Node_t * pNode; - float * pCiArrs; - int i; - // get the CI arrival times - pCiArrs = Abc_NtkGetCiArrivalFloats( p->pParams->pNtk ); - // assign the arrival times of the PIs - Pga_ManForEachCi( p, pNode, i ) - pNode->Match.Delay = pCiArrs[i]; - free( pCiArrs ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/pga/pgaInt.h b/src/map/pga/pgaInt.h deleted file mode 100644 index da9aa9a9..00000000 --- a/src/map/pga/pgaInt.h +++ /dev/null @@ -1,132 +0,0 @@ -/**CFile**************************************************************** - - FileName [pgaInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapper.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pgaInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PGA_INT_H__ -#define __PGA_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "abc.h" -#include "fraig.h" -#include "fpga.h" -#include "cut.h" -#include "pga.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Pga_NodeStruct_t_ Pga_Node_t; -typedef struct Pga_MatchStruct_t_ Pga_Match_t; - -struct Pga_ManStruct_t_ -{ - // mapping parameters - Pga_Params_t * pParams; // input data - // mapping structures - Pga_Node_t * pMemory; // the memory for all mapping structures - Vec_Ptr_t * vStructs; // mapping structures one-to-one with ABC nodes - Vec_Ptr_t * vOrdering; // mapping nodes ordered by level - // k-feasible cuts - int nVarsMax; // the "k" of k-feasible cuts - Cut_Man_t * pManCut; // the cut manager - // LUT library - float * pLutDelays; // the delay of the LUTs - float * pLutAreas; // the areas of the LUTs - float Epsilon; - // global parameters - float AreaGlobal; // the total area of this mapping - float ArrivalGlobal; // the largest delay of any path - float RequiredGlobal;// the global required time (may be different from largest delay) - float RequiredUser; // the required time given by the user - // runtime stats - int timeToMap; // the time to start the mapper - int timeCuts; // the time to compute the cuts - int timeDelay; // the time to compute delay - int timeAreaFlow; // the time to perform area flow optimization - int timeArea; // the time to perform area flow optimization - int timeToNet; // the time to transform back to network - int timeTotal; // the total time - int time1; // temporary - int time2; // temporary -}; - -struct Pga_MatchStruct_t_ -{ - Cut_Cut_t * pCut; // the best cut - float Delay; // the arrival time of this cut - float Area; // the area of this cut -}; - -struct Pga_NodeStruct_t_ -{ - int Id; // ID of the node - int nRefs; // the number of references - float EstRefs; // the estimated reference counter - float Required; // the required time - float Switching; // the switching activity - Pga_Match_t Match; // the best match at the node -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline Pga_Node_t * Pga_Node( Pga_Man_t * p, int Id ) { return p->vStructs->pArray[Id]; } - -// iterator through the CIs -#define Pga_ManForEachCi( p, pCi, i ) \ - for ( i = 0; (i < Abc_NtkCiNum(p->pParams->pNtk)) && (((pCi) = Pga_Node(p, Abc_NtkCi(p->pParams->pNtk,i)->Id)), 1); i++ ) -// iterator through the CO derivers -#define Pga_ManForEachCoDriver( p, pCo, i ) \ - for ( i = 0; (i < Abc_NtkCoNum(p->pParams->pNtk)) && (((pCo) = Pga_Node(p, Abc_ObjFaninId0(Abc_NtkCo(p->pParams->pNtk,i)))), 1); i++ ) -// iterators through the CIs and internal nodes -#define Pga_ManForEachObjDirect( p, pNode, i ) \ - Vec_PtrForEachEntry( p->vOrdering, pNode, i ) -#define Pga_ManForEachObjReverse( p, pNode, i ) \ - Vec_PtrForEachEntryReverse( p->vOrdering, pNode, i ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== pgaMatch.c ==========================================================*/ -extern void Pga_MappingMatches( Pga_Man_t * p, int Mode ); -/*=== pgaUtil.c ==========================================================*/ -extern Vec_Ptr_t * Pga_MappingResults( Pga_Man_t * p ); -extern float Pga_TimeComputeArrivalMax( Pga_Man_t * p ); -extern void Pga_MappingComputeRequired( Pga_Man_t * p ); -extern float Pga_MappingSetRefsAndArea( Pga_Man_t * p ); -extern float Pga_MappingGetSwitching( Pga_Man_t * p ); -extern void Pga_MappingPrintOutputArrivals( Pga_Man_t * p ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/pga/pgaMan.c b/src/map/pga/pgaMan.c deleted file mode 100644 index 4ecc2ca7..00000000 --- a/src/map/pga/pgaMan.c +++ /dev/null @@ -1,180 +0,0 @@ -/**CFile**************************************************************** - - FileName [pgaMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapper.] - - Synopsis [Mapping manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pgaMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Cut_Man_t * Pga_ManStartCutMan( Pga_Params_t * pParamsPga ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pga_Man_t * Pga_ManStart( Pga_Params_t * pParams ) -{ - Pga_Man_t * p; - Pga_Node_t * pNode; - Cut_Man_t * pManCut; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pObj; - int i, Counter; - int clk = clock(); - - // make sure the network is given - pNtk = pParams->pNtk; - if ( pNtk == NULL ) - { - printf( "Network is not specified.\n" ); - return NULL; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - printf( "Mapping can only be applied to an AIG.\n" ); - return NULL; - } - // the cut manager if given should be in sinc - pManCut = pNtk->pManCut; - if ( pManCut && Cut_ManReadVarsMax(pManCut) != Fpga_LutLibReadVarMax(pParams->pLutLib) ) - { - printf( "The precomputed cuts have different size.\n" ); - return NULL; - } - // make sure the nodes are in the topological order - if ( !Abc_NtkIsDfsOrdered(pNtk) ) - { - printf( "The nodes of the network are not DFS ordered.\n" ); -// Abc_NtkReassignIds( pNtk ); - return NULL; - } - // make sure there are no dangling nodes (unless they are choices) - - // start the mapping manager - p = ALLOC( Pga_Man_t, 1 ); - memset( p, 0, sizeof(Pga_Man_t) ); - p->pParams = pParams; - p->nVarsMax = Fpga_LutLibReadVarMax(pParams->pLutLib); - p->pManCut = pManCut? pManCut : Pga_ManStartCutMan(pParams); - p->vOrdering = Abc_AigGetLevelizedOrder(pNtk, 0); // what happens with dangling nodes??? - p->pLutAreas = Fpga_LutLibReadLutAreas(pParams->pLutLib); - p->pLutDelays = Fpga_LutLibReadLutDelays(pParams->pLutLib); - p->Epsilon = (float)0.00001; - - // allocate mapping structures - p->pMemory = ALLOC( Pga_Node_t, Abc_NtkObjNum(pNtk) ); - memset( p->pMemory, 0, sizeof(Pga_Node_t) * Abc_NtkObjNum(pNtk) ); - p->vStructs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); - Counter = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - { - pNode = p->pMemory + Counter++; - pNode->Id = pObj->Id; - pNode->nRefs = pObj->vFanouts.nSize; - pNode->Required = ABC_INFINITY; - pNode->Match.Area = ABC_INFINITY; - // skip secondary nodes - if ( Abc_ObjFanoutNum(pObj) == 0 ) - continue; - Vec_PtrWriteEntry( p->vStructs, pObj->Id, pNode ); - } - assert( Counter == Abc_NtkObjNum(pNtk) ); - // update order to depend on mapping nodes - Vec_PtrForEachEntry( p->vOrdering, pObj, i ) - Vec_PtrWriteEntry( p->vOrdering, i, Pga_Node(p,pObj->Id) ); -p->timeToMap = clock() - clk; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pga_ManStop( Pga_Man_t * p ) -{ - Cut_ManStop( p->pManCut ); - Vec_PtrFree( p->vOrdering ); - Vec_PtrFree( p->vStructs ); - free( p->pMemory ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Starts the cut manager for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Pga_ManStartCutMan( Pga_Params_t * pParamsPga ) -{ - static Cut_Params_t Params, * pParams = &Params; - Abc_Ntk_t * pNtk = pParamsPga->pNtk; - Cut_Man_t * pManCut; - Abc_Obj_t * pObj; - int i; - // start the cut manager - memset( pParams, 0, sizeof(Cut_Params_t) ); - pParams->nVarsMax = Fpga_LutLibReadVarMax(pParamsPga->pLutLib); // max cut size - pParams->nKeepMax = 250; // the max number of cuts kept at a node - pParams->fTruth = 0; // compute truth tables - pParams->fFilter = 1; // filter dominated cuts - pParams->fSeq = 0; // compute sequential cuts - pParams->fDrop = pParamsPga->fDropCuts; // drop cuts on the fly - pParams->fVerbose = 0; // the verbosiness flag - pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); - pManCut = Cut_ManStart( pParams ); - if ( pParams->fDrop ) - Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); - // set cuts for PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_NodeSetTriv( pManCut, pObj->Id ); - return pManCut; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/pga/pgaMatch.c b/src/map/pga/pgaMatch.c deleted file mode 100644 index 186fbf64..00000000 --- a/src/map/pga/pgaMatch.c +++ /dev/null @@ -1,378 +0,0 @@ -/**CFile**************************************************************** - - FileName [pgaMatch.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapper.] - - Synopsis [Mapping procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pgaMatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static char * s_Modes[4] = { "Delay", "Flow", "Area", "Switch" }; - -static int Pga_MappingMatchNode( Pga_Man_t * p, int NodeId, Cut_Cut_t * pList, int Mode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs mapping for delay, area-flow, area, switching.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pga_MappingMatches( Pga_Man_t * p, int Mode ) -{ - ProgressBar * pProgress; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pObj; - Cut_Cut_t * pList; - int i, clk; - - assert( Mode >= 0 && Mode <= 2 ); - - // match LUTs with nodes in the topological order - pNtk = p->pParams->pNtk; - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - // skip the CIs - if ( Abc_ObjIsCi(pObj) ) - continue; - // when we reached a CO, it is time to deallocate the cuts - if ( Abc_ObjIsCo(pObj) ) - { - if ( p->pParams->fDropCuts ) - Cut_NodeTryDroppingCuts( p->pManCut, Abc_ObjFaninId0(pObj) ); - continue; - } - // skip constant node, it has no cuts -// if ( Abc_NodeIsConst(pObj) ) -// continue; - // get the cuts -clk = clock(); - pList = Abc_NodeGetCutsRecursive( p->pManCut, pObj, 0, 0 ); -p->timeCuts += clock() - clk; - // match the node - Pga_MappingMatchNode( p, pObj->Id, pList, Mode ); - Extra_ProgressBarUpdate( pProgress, i, s_Modes[Mode] ); - } - Extra_ProgressBarStop( pProgress ); -} - - - - -/**Function************************************************************* - - Synopsis [Computes the match of the cut.] - - Description [Returns 1 if feasible.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Pga_CutGetArrival( Pga_Man_t * p, Cut_Cut_t * pCut ) -{ - float DelayCur, DelayWorst; - unsigned i; - assert( pCut->nLeaves > 1 ); - DelayWorst = -ABC_INFINITY; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - DelayCur = Pga_Node(p, pCut->pLeaves[i])->Match.Delay; - if ( DelayWorst < DelayCur ) - DelayWorst = DelayCur; - } - DelayWorst += p->pLutDelays[pCut->nLeaves]; - return DelayWorst; -} - -/**Function************************************************************* - - Synopsis [Computes the match of the cut.] - - Description [Returns 1 if feasible.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Pga_CutGetAreaFlow( Pga_Man_t * p, Cut_Cut_t * pCut ) -{ - float Flow; - Pga_Node_t * pNode; - unsigned i; - assert( pCut->nLeaves > 1 ); - Flow = p->pLutAreas[pCut->nLeaves]; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pNode = Pga_Node(p, pCut->pLeaves[i]); - assert( pNode->EstRefs > 0 ); - Flow += pNode->Match.Area / pNode->EstRefs; - } - return Flow; -} - -/**function************************************************************* - - synopsis [References the cut.] - - description [This procedure is similar to the procedure NodeReclaim.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Pga_CutRef( Pga_Man_t * p, Pga_Node_t * pNode, Cut_Cut_t * pCut ) -{ - Pga_Node_t * pFanin; - float aArea; - unsigned i; - // start the area of this cut - aArea = p->pLutAreas[pCut->nLeaves]; - // go through the children - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pFanin = Pga_Node(p, pCut->pLeaves[i]); - assert( pFanin->nRefs >= 0 ); - if ( pFanin->nRefs++ > 0 ) - continue; - if ( pFanin->Match.pCut == NULL ) - continue; - aArea += Pga_CutRef( p, pFanin, pFanin->Match.pCut ); - } - return aArea; -} - -/**function************************************************************* - - synopsis [Dereferences the cut.] - - description [This procedure is similar to the procedure NodeRecusiveDeref.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Pga_CutDeref( Pga_Man_t * p, Pga_Node_t * pNode, Cut_Cut_t * pCut ) -{ - Pga_Node_t * pFanin; - float aArea; - unsigned i; - // start the area of this cut - aArea = p->pLutAreas[pCut->nLeaves]; - // go through the children - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pFanin = Pga_Node(p, pCut->pLeaves[i]); - assert( pFanin->nRefs > 0 ); - if ( --pFanin->nRefs > 0 ) - continue; - if ( pFanin->Match.pCut == NULL ) - continue; - aArea += Pga_CutDeref( p, pFanin, pFanin->Match.pCut ); - } - return aArea; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [Assumes that the cut is deferenced.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -static inline float Pga_CutGetAreaDerefed( Pga_Man_t * p, Pga_Node_t * pNode, Cut_Cut_t * pCut ) -{ - float aResult, aResult2; - assert( pCut->nLeaves > 1 ); - aResult2 = Pga_CutRef( p, pNode, pCut ); - aResult = Pga_CutDeref( p, pNode, pCut ); - assert( aResult == aResult2 ); - return aResult; -} - - - -/**Function************************************************************* - - Synopsis [Computes the match of the cut.] - - Description [Returns 1 if feasible.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Pga_MappingMatchCut( Pga_Man_t * p, Pga_Node_t * pNode, Cut_Cut_t * pCut, int Mode, Pga_Match_t * pMatch ) -{ - // compute the arrival time of the cut and its area flow - pMatch->Delay = Pga_CutGetArrival( p, pCut ); - // drop the cut if it does not meet the required times - if ( pMatch->Delay > pNode->Required + p->Epsilon ) - return 0; - // get the second parameter - if ( Mode == 0 || Mode == 1 ) - pMatch->Area = Pga_CutGetAreaFlow( p, pCut ); - else if ( Mode == 2 ) - pMatch->Area = Pga_CutGetAreaDerefed( p, pNode, pCut ); -// else if ( Mode == 3 ) -// pMatch->Area = Pga_CutGetSwitching( p, pNode, pCut ); - // if no cut is assigned, use the current one - pMatch->pCut = pCut; - return 1; -} - -/**Function************************************************************* - - Synopsis [Compares two matches.] - - Description [Returns 1 if the second match is better.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Pga_MappingCompareMatches( Pga_Man_t * p, Pga_Match_t * pMatchBest, Pga_Match_t * pMatchCur, int Mode ) -{ - if ( pMatchBest->pCut == NULL ) - return 1; - if ( Mode == 0 ) - { - // compare delays - if ( pMatchBest->Delay < pMatchCur->Delay - p->Epsilon ) - return 0; - if ( pMatchBest->Delay > pMatchCur->Delay + p->Epsilon ) - return 1; - // compare areas - if ( pMatchBest->Area < pMatchCur->Area - p->Epsilon ) - return 0; - if ( pMatchBest->Area > pMatchCur->Area + p->Epsilon ) - return 1; - // if equal, do not update - return 0; - } - else - { - // compare areas - if ( pMatchBest->Area < pMatchCur->Area - p->Epsilon ) - return 0; - if ( pMatchBest->Area > pMatchCur->Area + p->Epsilon ) - return 1; - // compare delays - if ( pMatchBest->Delay < pMatchCur->Delay - p->Epsilon ) - return 0; - if ( pMatchBest->Delay > pMatchCur->Delay + p->Epsilon ) - return 1; - // if equal, do not update - return 0; - } -} - - -/**Function************************************************************* - - Synopsis [Computes the best matching for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pga_MappingMatchNode( Pga_Man_t * p, int NodeId, Cut_Cut_t * pList, int Mode ) -{ - Pga_Match_t MatchCur, * pMatchCur = &MatchCur; - Pga_Match_t MatchBest, * pMatchBest = &MatchBest; - Pga_Node_t * pNode; - Cut_Cut_t * pCut; - - // get the mapping node - pNode = Pga_Node( p, NodeId ); - - // prepare for mapping - if ( Mode == 0 ) - pNode->EstRefs = (float)pNode->nRefs; - else if ( Mode == 1 ) - pNode->EstRefs = (float)((2.0 * pNode->EstRefs + pNode->nRefs) / 3.0); - else if ( Mode == 2 && pNode->nRefs > 0 ) - Pga_CutDeref( p, pNode, pNode->Match.pCut ); -// else if ( Mode == 3 && pNode->nRefs > 0 ) -// Pga_CutDerefSwitch( p, pNode, pNode->Match.pCut ); - - // start the best match - pMatchBest->pCut = NULL; - - // go through the other cuts - assert( pList->pNext ); - for ( pCut = pList->pNext; pCut; pCut = pCut->pNext ) - { - // compute match for this cut - if ( !Pga_MappingMatchCut( p, pNode, pCut, Mode, pMatchCur ) ) - continue; - // compare matches - if ( !Pga_MappingCompareMatches( p, pMatchBest, pMatchCur, Mode ) ) - continue; - // the best match should be updated - *pMatchBest = *pMatchCur; - } - - // make sure the match is found - if ( pMatchBest->pCut != NULL ) - pNode->Match = *pMatchBest; - else - { - assert( 0 ); -// Pga_MappingMatchCut( p, pNode, pCut, Mode, pNode->Match ); - } - - // reference the best cut - if ( Mode == 2 && pNode->nRefs > 0 ) - Pga_CutRef( p, pNode, pNode->Match.pCut ); -// else if ( Mode == 3 && pNode->nRefs > 0 ) -// Pga_CutRefSwitch( p, pNode, pNode->Match.pCut ); - return 1; -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/pga/pgaUtil.c b/src/map/pga/pgaUtil.c deleted file mode 100644 index c79e3515..00000000 --- a/src/map/pga/pgaUtil.c +++ /dev/null @@ -1,320 +0,0 @@ -/**CFile**************************************************************** - - FileName [pgaUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapper.] - - Synopsis [Verious utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pgaUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "pgaInt.h" - -#define PGA_CO_LIST_SIZE 5 - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the results of mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Pga_MappingResults( Pga_Man_t * p ) -{ - Vec_Ptr_t * vResult; - Pga_Node_t * pNode; - int i; - vResult = Vec_PtrAlloc( 1000 ); - Pga_ManForEachObjDirect( p, pNode, i ) - { - // skip the CIs and nodes not used in the mapping - if ( !pNode->Match.pCut || !pNode->nRefs ) - continue; - pNode->Match.pCut->uSign = pNode->Id; - Vec_PtrPush( vResult, pNode->Match.pCut ); - } - return vResult; -} - -/**Function************************************************************* - - Synopsis [Computes the maximum arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Pga_TimeComputeArrivalMax( Pga_Man_t * p ) -{ - Pga_Node_t * pNode; - float ArrivalMax; - int i; - ArrivalMax = -ABC_INFINITY; - Pga_ManForEachCoDriver( p, pNode, i ) - ArrivalMax = ABC_MAX( ArrivalMax, pNode->Match.Delay ); - return ArrivalMax; -} - - -/**Function************************************************************* - - Synopsis [Computes required times of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pga_MappingComputeRequired( Pga_Man_t * p ) -{ - Pga_Node_t * pNode, * pFanin; - Cut_Cut_t * pCutBest; - float RequiredNew; - int i, k; - // clean the required times of all nodes - Pga_ManForEachObjDirect( p, pNode, i ) - pNode->Required = ABC_INFINITY; - // get the global required times - p->AreaGlobal = Pga_TimeComputeArrivalMax( p ); - p->RequiredGlobal = ABC_MAX( p->AreaGlobal, p->RequiredUser ); - // set the global required times of the CO drivers - Pga_ManForEachCoDriver( p, pNode, i ) - pNode->Required = p->RequiredGlobal; - // propagate the required times in the reverse topological order - Pga_ManForEachObjReverse( p, pNode, i ) - { - // skip the CIs and nodes not used in the mapping - if ( !pNode->Match.pCut || !pNode->nRefs ) - continue; - // get the required time for children - pCutBest = pNode->Match.pCut; - RequiredNew = pNode->Required - p->pLutDelays[pCutBest->nLeaves]; - // update the required time of the children - for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) - { - pFanin = Pga_Node( p, pCutBest->pLeaves[k] ); - pFanin->Required = ABC_MIN( pFanin->Required, RequiredNew ); - } - } - // check that the required times does not contradict the arrival times - Pga_ManForEachObjDirect( p, pNode, i ) - assert( !pNode->Match.pCut || pNode->Match.Delay < pNode->Required + p->Epsilon ); - -} - -/**Function************************************************************* - - Synopsis [Sets references and computes area for the current mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Pga_MappingSetRefsAndArea( Pga_Man_t * p ) -{ - Pga_Node_t * pNode, * pFanin; - Cut_Cut_t * pCutBest; - float AreaTotal; - int i, k; - // clean all the references - Pga_ManForEachObjDirect( p, pNode, i ) - pNode->nRefs = 0; - // set the references of the CO drivers - Pga_ManForEachCoDriver( p, pNode, i ) - pNode->nRefs++; - // go through the nodes in the reverse order - AreaTotal = 0.0; - Pga_ManForEachObjReverse( p, pNode, i ) - { - // skip the CIs and nodes not used in the mapping - if ( !pNode->Match.pCut || !pNode->nRefs ) - continue; - // increate the reference count of the children - pCutBest = pNode->Match.pCut; - AreaTotal += p->pLutAreas[pCutBest->nLeaves]; - // update the required time of the children - for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) - { - pFanin = Pga_Node( p, pCutBest->pLeaves[k] ); - pFanin->nRefs++; - } - } - return AreaTotal; -} - -/**Function************************************************************* - - Synopsis [Computes switching activity of the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Pga_MappingGetSwitching( Pga_Man_t * p ) -{ - float Switching; - Pga_Node_t * pNode; - int i; - Switching = 0; - Pga_ManForEachObjDirect( p, pNode, i ) - { - // skip the CIs and nodes not used in the mapping - if ( !pNode->Match.pCut || !pNode->nRefs ) - continue; - Switching += pNode->Switching; - } - return Switching; -} - -/**Function************************************************************* - - Synopsis [Compares the outputs by their arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pga_MappingCompareOutputDelay( Pga_Node_t ** ppNode1, Pga_Node_t ** ppNode2 ) -{ - Pga_Node_t * pNode1 = *ppNode1; - Pga_Node_t * pNode2 = *ppNode2; - float Arrival1 = pNode1->Match.Delay; - float Arrival2 = pNode2->Match.Delay; - if ( Arrival1 < Arrival2 ) - return -1; - if ( Arrival1 > Arrival2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Finds given number of latest arriving COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pga_MappingFindLatest( Pga_Man_t * p, int * pNodes, int nNodesMax ) -{ - Pga_Node_t * pNodeI, * pNodeK; - Abc_Obj_t * pObjCo; - int nNodes, i, k, v; - assert( Abc_NtkCoNum(p->pParams->pNtk) >= nNodesMax ); - pNodes[0] = 0; - nNodes = 1; -// for ( i = 1; i < p->nOutputs; i++ ) - Pga_ManForEachCoDriver( p, pNodeI, i ) - { - for ( k = nNodes - 1; k >= 0; k-- ) - { - pObjCo = Abc_NtkCo( p->pParams->pNtk, pNodes[k] ); - pNodeK = Pga_Node( p, Abc_ObjFaninId0(pObjCo) ); - if ( Pga_MappingCompareOutputDelay( &pNodeK, &pNodeI ) >= 0 ) - break; - } - if ( k == nNodesMax - 1 ) - continue; - if ( nNodes < nNodesMax ) - nNodes++; - for ( v = nNodes - 1; v > k+1; v-- ) - pNodes[v] = pNodes[v-1]; - pNodes[k+1] = i; - } -} - -/**Function************************************************************* - - Synopsis [Prints a bunch of latest arriving outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pga_MappingPrintOutputArrivals( Pga_Man_t * p ) -{ - int pSorted[PGA_CO_LIST_SIZE]; - Abc_Ntk_t * pNtk = p->pParams->pNtk; - Abc_Obj_t * pObjCo; - Pga_Node_t * pNode; - int Limit, MaxNameSize, i; - - // determine the number of nodes to print - Limit = (Abc_NtkCoNum(pNtk) < PGA_CO_LIST_SIZE)? Abc_NtkCoNum(pNtk) : PGA_CO_LIST_SIZE; - - // determine the order - Pga_MappingFindLatest( p, pSorted, Limit ); - - // determine max size of the node's name - MaxNameSize = 0; - for ( i = 0; i < Limit; i++ ) - { - pObjCo = Abc_NtkCo( pNtk, pSorted[i] ); - if ( MaxNameSize < (int)strlen( Abc_ObjName(pObjCo) ) ) - MaxNameSize = strlen( Abc_ObjName(pObjCo) ); - } - - // print the latest outputs - for ( i = 0; i < Limit; i++ ) - { - // get the i-th latest output - pObjCo = Abc_NtkCo( pNtk, pSorted[i] ); - pNode = Pga_Node( p, pObjCo->Id ); - // print out the best arrival time - printf( "Output %-*s : ", MaxNameSize + 3, Abc_ObjName(pObjCo) ); - printf( "Delay = %8.2f ", (double)pNode->Match.Delay ); - if ( Abc_ObjFaninC0(pObjCo) ) - printf( "NEG" ); - else - printf( "POS" ); - printf( "\n" ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/vec/vec.h b/src/misc/vec/vec.h index a3943f2d..f23cc178 100644 --- a/src/misc/vec/vec.h +++ b/src/misc/vec/vec.h @@ -38,6 +38,7 @@ extern "C" { #include "vecStr.h" #include "vecPtr.h" #include "vecVec.h" +#include "vecAtt.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// diff --git a/src/misc/vec/vecAtt.h b/src/misc/vec/vecAtt.h new file mode 100644 index 00000000..bfe3eac8 --- /dev/null +++ b/src/misc/vec/vecAtt.h @@ -0,0 +1,392 @@ +/**CFile**************************************************************** + + FileName [vecAtt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [Array of user-specified attiributes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vecAtt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __Vec_Att_H__ +#define __Vec_Att_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// various attributes +typedef enum { + VEC_ATTR_NONE = 0, // 0 + VEC_ATTR_COPY, // 1 + VEC_ATTR_LOCAL_AIG, // 2 + VEC_ATTR_LOCAL_SOP, // 3 + VEC_ATTR_LOCAL_BDD, // 4 + VEC_ATTR_GLOBAL_AIG, // 5 + VEC_ATTR_GLOBAL_SOP, // 6 + VEC_ATTR_GLOBAL_BDD, // 7 + VEC_ATTR_LEVEL, // 8 + VEC_ATTR_LEVEL_REV, // 9 + VEC_ATTR_RETIME_LAG, // 10 + VEC_ATTR_FRAIG, // 11 + VEC_ATTR_DATA1, // 12 + VEC_ATTR_DATA2, // 13 + VEC_ATTR_DATA3, // 14 + VEC_ATTR_TOTAL_NUM // 15 +} Vec_AttrType_t; + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Vec_Att_t_ Vec_Att_t; +struct Vec_Att_t_ +{ + // storage for attributes + int nCap; // the size of array allocated + int * pArrayInt; // the integer attribute array + void ** pArrayPtr; // the pointer attribute array + // attribute specific info + void * pMan; // the manager for this attribute + void (*pFuncFreeMan) (void *); // the procedure to free the manager + void*(*pFuncStartObj)(void *); // the procedure to start one attribute + void (*pFuncFreeObj) (void *, void *); // the procedure to free one attribute +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Att_t * Vec_AttAlloc( + int fInteger, int nSize, void * pMan, + void (*pFuncFreeMan) (void *), + void*(*pFuncStartObj)(void *), + void (*pFuncFreeObj) (void *, void *) ) +{ + Vec_Att_t * p; + p = ALLOC( Vec_Att_t, 1 ); + memset( p, 0, sizeof(Vec_Att_t) ); + p->pMan = pMan; + p->pFuncFreeMan = pFuncFreeMan; + p->pFuncStartObj = pFuncStartObj; + p->pFuncFreeObj = pFuncFreeObj; + p->nCap = nSize? nSize : 16; + if ( fInteger ) + { + p->pArrayInt = ALLOC( int, p->nCap ); + memset( p->pArrayInt, 0xff, sizeof(int) * p->nCap ); + } + else + { + p->pArrayPtr = ALLOC( void *, p->nCap ); + memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_AttFree( Vec_Att_t * p, int fFreeMan ) +{ + void * pMan; + if ( p == NULL ) + return NULL; + // free the attributes of objects + if ( p->pFuncFreeObj ) + { + int i; + if ( p->pArrayInt ) + { + for ( i = 0; i < p->nCap; i++ ) + if ( p->pArrayInt[i] ) + p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); + } + else + { + for ( i = 0; i < p->nCap; i++ ) + if ( p->pArrayPtr[i] ) + p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] ); + } + } + // free the memory manager + pMan = fFreeMan? NULL : p->pMan; + if ( p->pMan && fFreeMan ) + p->pFuncFreeMan( p->pMan ); + FREE( p->pArrayInt ); + FREE( p->pArrayPtr ); + FREE( p ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Clears the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttClear( Vec_Att_t * p ) +{ + // free the attributes of objects + if ( p->pFuncFreeObj ) + { + int i; + if ( p->pArrayInt ) + { + if ( p->pFuncFreeObj ) + for ( i = 0; i < p->nCap; i++ ) + if ( p->pArrayInt[i] ) + p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); + } + else + { + if ( p->pFuncFreeObj ) + for ( i = 0; i < p->nCap; i++ ) + if ( p->pArrayPtr[i] ) + p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] ); + } + } + if ( p->pArrayInt ) + memset( p->pArrayInt, 0xff, sizeof(int) * p->nCap ); + else + memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap ); + +} + +/**Function************************************************************* + + Synopsis [Deletes one entry from the attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttFreeEntry( Vec_Att_t * p, int i ) +{ + if ( i >= p->nCap ) + return; + if ( p->pMan ) + { + if ( p->pArrayInt[i] && p->pFuncFreeObj ) + p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); + if ( p->pArrayPtr[i] && p->pFuncFreeObj ) + p->pFuncFreeObj( p->pMan, (void *)p->pArrayPtr[i] ); + } + if ( p->pArrayInt ) + p->pArrayInt[i] = ~(unsigned)0; + else + p->pArrayPtr[i] = NULL; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttGrow( Vec_Att_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + if ( p->pArrayInt ) + { + p->pArrayInt = REALLOC( int, p->pArrayInt, nCapMin ); + memset( p->pArrayInt + nCapMin, 0xff, sizeof(int) * (nCapMin - p->nCap) ); + } + else + { + p->pArrayPtr = REALLOC( void *, p->pArrayPtr, nCapMin ); + memset( p->pArrayPtr + nCapMin, 0, sizeof(void *) * (nCapMin - p->nCap) ); + } + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [Writes the entry into its place.] + + Description [Only works if the manager is not defined.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttWriteEntry( Vec_Att_t * p, int i, void * pEntry ) +{ + assert( p->pArrayPtr ); + assert( p->pFuncStartObj == NULL ); + if ( i >= p->nCap ) + Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i ); + p->pArrayPtr[i] = pEntry; +} + +/**Function************************************************************* + + Synopsis [Writes the entry into its place.] + + Description [Only works if the manager is not defined.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttWriteEntryInt( Vec_Att_t * p, int i, int Entry ) +{ + assert( p->pArrayInt ); + assert( p->pFuncStartObj == NULL ); + if ( i >= p->nCap ) + Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i ); + p->pArrayInt[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [Returns the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_AttEntry( Vec_Att_t * p, int i ) +{ + assert( p->pArrayPtr ); + if ( i >= p->nCap ) + Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i ); + if ( p->pArrayPtr[i] == NULL && p->pFuncStartObj ) + p->pArrayPtr[i] = p->pFuncStartObj( p->pMan ); + return p->pArrayPtr[i]; +} + +/**Function************************************************************* + + Synopsis [Returns the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_AttEntryInt( Vec_Att_t * p, int i ) +{ + assert( p->pArrayInt ); + assert( p->pMan == NULL ); + if ( i >= p->nCap ) + Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i ); + return p->pArrayInt[i]; +} + +/**Function************************************************************* + + Synopsis [Returns the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_AttMan( Vec_Att_t * p ) +{ + return p->pMan; +} + +/**Function************************************************************* + + Synopsis [Returns the array of attributes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void ** Vec_AttArray( Vec_Att_t * p ) +{ + return p->pArrayPtr; +} + +/**Function************************************************************* + + Synopsis [Returns the array of attributes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Vec_AttArrayInt( Vec_Att_t * p ) +{ + return p->pArrayInt; +} + +#endif + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/opt/cut/abcCut.c b/src/opt/cut/abcCut.c index 35814593..3b70e9c1 100644 --- a/src/opt/cut/abcCut.c +++ b/src/opt/cut/abcCut.c @@ -218,6 +218,7 @@ void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) ***********************************************************************/ Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) { +/* Cut_Man_t * p; Abc_Obj_t * pObj, * pNode; int i, nIters, fStatus; @@ -303,6 +304,7 @@ printf( "Converged after %d iterations.\n", nIters ); } //Abc_NtkPrintCuts( p, pNtk, 1 ); return p; +*/ } /**Function************************************************************* diff --git a/src/opt/dec/decAbc.c b/src/opt/dec/decAbc.c index 23d60826..bd960c14 100644 --- a/src/opt/dec/decAbc.c +++ b/src/opt/dec/decAbc.c @@ -214,26 +214,26 @@ void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpda SeeAlso [] ***********************************************************************/ -Aig_Obj_t * Dec_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph ) +Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph ) { Dec_Node_t * pNode; - Aig_Obj_t * pAnd0, * pAnd1; + Hop_Obj_t * pAnd0, * pAnd1; int i; // check for constant function if ( Dec_GraphIsConst(pGraph) ) - return Aig_NotCond( Aig_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); + return Hop_NotCond( Hop_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) - return Aig_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + return Hop_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph Dec_GraphForEachNode( pGraph, pNode, i ) { - pAnd0 = Aig_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Aig_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Aig_And( pMan, pAnd0, pAnd1 ); + pAnd0 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); } // complement the result if necessary - return Aig_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); + return Hop_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } /**Function************************************************************* @@ -247,9 +247,9 @@ Aig_Obj_t * Dec_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph ) SeeAlso [] ***********************************************************************/ -Aig_Obj_t * Dec_GraphFactorSop( Aig_Man_t * pMan, char * pSop ) +Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ) { - Aig_Obj_t * pFunc; + Hop_Obj_t * pFunc; Dec_Graph_t * pFForm; Dec_Node_t * pNode; int i; @@ -257,7 +257,7 @@ Aig_Obj_t * Dec_GraphFactorSop( Aig_Man_t * pMan, char * pSop ) pFForm = Dec_Factor( pSop ); // collect the fanins Dec_GraphForEachLeaf( pFForm, pNode, i ) - pNode->pFunc = Aig_IthVar( pMan, i ); + pNode->pFunc = Hop_IthVar( pMan, i ); // perform strashing pFunc = Dec_GraphToNetworkAig( pMan, pFForm ); Dec_GraphFree( pFForm ); diff --git a/src/opt/ret/module.make b/src/opt/ret/module.make index c65021c4..4b14365e 100644 --- a/src/opt/ret/module.make +++ b/src/opt/ret/module.make @@ -3,5 +3,6 @@ SRC += src/opt/ret/retArea.c \ src/opt/ret/retDelay.c \ src/opt/ret/retFlow.c \ src/opt/ret/retIncrem.c \ - src/opt/ret/retInit.c + src/opt/ret/retInit.c \ + src/opt/ret/retLvalue.c diff --git a/src/opt/ret/retArea.c b/src/opt/ret/retArea.c index 41d19592..5eec8e80 100644 --- a/src/opt/ret/retArea.c +++ b/src/opt/ret/retArea.c @@ -24,12 +24,9 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static int Abc_NtkRetimeMinAreaFwd( Abc_Ntk_t * pNtk, int fVerbose ); -static Abc_Ntk_t * Abc_NtkRetimeMinAreaBwd( Abc_Ntk_t * pNtk, int fVerbose ); +static Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); static void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ); -static Vec_Ptr_t * Abc_NtkRetimeMinAreaAddBuffers( Abc_Ntk_t * pNtk ); -static void Abc_NtkRetimeMinAreaRemoveBuffers( Abc_Ntk_t * pNtk, Vec_Ptr_t * vBuffers ); -static void Abc_NtkRetimeMinAreaInitValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); +static void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); static Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); static void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); @@ -55,6 +52,7 @@ int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, Abc_Ntk_t * pNtkTotal = NULL, * pNtkBottom; Vec_Int_t * vValuesNew = NULL, * vValues; int nLatches = Abc_NtkLatchNum(pNtk); + int fOneFrame = 0; assert( !fForwardOnly || !fBackwardOnly ); // there should not be black boxes assert( Abc_NtkIsSopLogic(pNtk) ); @@ -62,17 +60,24 @@ int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, // reorder CI/CO/latch inputs Abc_NtkOrderCisCos( pNtk ); // perform forward retiming -// Abc_NtkRetimeMinAreaFwd( pNtk, fVerbose ); -// pNtkTotal = Abc_NtkRetimeMinAreaBwd( pNtk, fVerbose ); if ( !fBackwardOnly ) - while ( Abc_NtkRetimeMinAreaFwd( pNtk, fVerbose ) ); + { + if ( fOneFrame ) + Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ); + else + while ( Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ) ); + } // remember initial values vValues = Abc_NtkCollectLatchValues( pNtk ); // perform backward retiming if ( !fForwardOnly ) -// pNtkTotal = Abc_NtkRetimeMinAreaBwd( pNtk, fVerbose ); - while ( pNtkBottom = Abc_NtkRetimeMinAreaBwd( pNtk, fVerbose ) ) - pNtkTotal = Abc_NtkAttachBottom( pNtkTotal, pNtkBottom ); + { + if ( fOneFrame ) + pNtkTotal = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose ); + else + while ( pNtkBottom = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose ) ) + pNtkTotal = Abc_NtkAttachBottom( pNtkTotal, pNtkBottom ); + } // compute initial values vValuesNew = Abc_NtkRetimeInitialValues( pNtkTotal, vValues, fVerbose ); if ( pNtkTotal ) Abc_NtkDelete( pNtkTotal ); @@ -80,8 +85,8 @@ int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, Abc_NtkInsertLatchValues( pNtk, vValuesNew ); if ( vValuesNew ) Vec_IntFree( vValuesNew ); if ( vValues ) Vec_IntFree( vValues ); - // fix the COs - Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + // fix the COs (this changes the circuit structure) +// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); // check for correctness if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkRetimeMinArea(): Network check has failed.\n" ); @@ -91,7 +96,7 @@ int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, /**Function************************************************************* - Synopsis [Performs min-area retiming forward.] + Synopsis [Performs min-area retiming backward.] Description [] @@ -100,33 +105,35 @@ int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, SeeAlso [] ***********************************************************************/ -int Abc_NtkRetimeMinAreaFwd( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Vec_Ptr_t * vBuffers, * vMinCut; +Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew = NULL; + Vec_Ptr_t * vMinCut; int nLatches = Abc_NtkLatchNum(pNtk); - // mark current latches and TFO(PIs) - Abc_NtkRetimeMinAreaPrepare( pNtk, 1 ); - // add buffers on edges feeding into the marked nodes - vBuffers = Abc_NtkRetimeMinAreaAddBuffers( pNtk ); + // mark current latches and TFI(POs) + Abc_NtkRetimeMinAreaPrepare( pNtk, fForward ); // run the maximum forward flow - vMinCut = Abc_NtkMaxFlow( pNtk, 1, fVerbose ); - assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) ); + vMinCut = Abc_NtkMaxFlow( pNtk, fForward, fVerbose ); +// assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) ); // create new latch boundary if there is improvement if ( Vec_PtrSize(vMinCut) < Abc_NtkLatchNum(pNtk) ) { - Abc_NtkRetimeMinAreaInitValue( pNtk, vMinCut ); - Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, 1 ); + pNtkNew = (Abc_Ntk_t *)1; + if ( fForward ) + Abc_NtkRetimeMinAreaInitValues( pNtk, vMinCut ); + else + pNtkNew = Abc_NtkRetimeMinAreaConstructNtk( pNtk, vMinCut ); + Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, fForward ); } // clean up - Abc_NtkRetimeMinAreaRemoveBuffers( pNtk, vBuffers ); Vec_PtrFree( vMinCut ); Abc_NtkCleanMarkA( pNtk ); - return nLatches - Abc_NtkLatchNum(pNtk); + return pNtkNew; } /**Function************************************************************* - Synopsis [Performs min-area retiming backward.] + Synopsis [Marks the cone with MarkA.] Description [] @@ -135,26 +142,23 @@ int Abc_NtkRetimeMinAreaFwd( Abc_Ntk_t * pNtk, int fVerbose ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkRetimeMinAreaBwd( Abc_Ntk_t * pNtk, int fVerbose ) +void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ) { - Abc_Ntk_t * pNtkNew = NULL; - Vec_Ptr_t * vMinCut; - int nLatches = Abc_NtkLatchNum(pNtk); - // mark current latches and TFI(POs) - Abc_NtkRetimeMinAreaPrepare( pNtk, 0 ); - // run the maximum forward flow - vMinCut = Abc_NtkMaxFlow( pNtk, 0, fVerbose ); - assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) ); - // create new latch boundary if there is improvement - if ( Vec_PtrSize(vMinCut) < Abc_NtkLatchNum(pNtk) ) + Abc_Obj_t * pNext; + int i; + if ( pObj->fMarkA ) + return; + pObj->fMarkA = 1; + if ( fForward ) + { + Abc_ObjForEachFanout( pObj, pNext, i ) + Abc_NtkMarkCone_rec( pNext, fForward ); + } + else { - pNtkNew = Abc_NtkRetimeMinAreaConstructNtk( pNtk, vMinCut ); - Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, 0 ); + Abc_ObjForEachFanin( pObj, pNext, i ) + Abc_NtkMarkCone_rec( pNext, fForward ); } - // clean up - Vec_PtrFree( vMinCut ); - Abc_NtkCleanMarkA( pNtk ); - return pNtkNew; } /**Function************************************************************* @@ -168,22 +172,22 @@ Abc_Ntk_t * Abc_NtkRetimeMinAreaBwd( Abc_Ntk_t * pNtk, int fVerbose ) SeeAlso [] ***********************************************************************/ -void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ) +void Abc_NtkUnmarkCone_rec( Abc_Obj_t * pObj, int fForward ) { Abc_Obj_t * pNext; int i; - if ( pObj->fMarkA ) + if ( !pObj->fMarkA || Abc_ObjIsLatch(pObj) ) return; - pObj->fMarkA = 1; + pObj->fMarkA = 0; if ( fForward ) { Abc_ObjForEachFanout( pObj, pNext, i ) - Abc_NtkMarkCone_rec( pNext, fForward ); + Abc_NtkUnmarkCone_rec( pNext, fForward ); } else { Abc_ObjForEachFanin( pObj, pNext, i ) - Abc_NtkMarkCone_rec( pNext, fForward ); + Abc_NtkUnmarkCone_rec( pNext, fForward ); } } @@ -200,8 +204,9 @@ void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ) ***********************************************************************/ void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ) { - Abc_Obj_t * pObj; - int i; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin; + int i, k; if ( fForward ) { // mark the frontier @@ -212,9 +217,20 @@ void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ) pObj->fMarkA = 1; Abc_ObjFanin0(pObj)->fMarkA = 1; } - // mark the nodes reachable from the POs + // mark the nodes reachable from the PIs Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkMarkCone_rec( pObj, fForward ); + // collect the unmarked fanins of the marked nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->fMarkA ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !pFanin->fMarkA ) + Vec_PtrPush( vNodes, pFanin ); + // mark these nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->fMarkA = 1; + Vec_PtrFree( vNodes ); } else { @@ -232,81 +248,6 @@ void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ) } } -/**Function************************************************************* - - Synopsis [Add extra buffers.] - - Description [This is needed to make sure that forward retiming - works correctly. This has to do with the nodes in the TFO cone - of the PIs having multiple incoming edges.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkRetimeMinAreaAddBuffers( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vFeeds, * vFanouts; - Abc_Obj_t * pObj, * pFanin, * pFanout, * pBuffer; - int i, k; - // collect all nodes that are feeding into the marked nodes - Abc_NtkIncrementTravId(pNtk); - vFeeds = Vec_PtrAlloc( 100 ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( !pObj->fMarkA ) - continue; - Abc_ObjForEachFanin( pObj, pFanin, k ) - if ( !pFanin->fMarkA && !Abc_NodeIsTravIdCurrent(pFanin) ) - { - Abc_NodeSetTravIdCurrent( pFanin ); - Vec_PtrPush( vFeeds, pFanin ); - } - } - // add buffers for each such node - vFanouts = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( vFeeds, pObj, i ) - { - // create and remember the buffers - pBuffer = Abc_NtkCreateNodeBuf( pNtk, pObj ); - Vec_PtrWriteEntry( vFeeds, i, pBuffer ); - // patch the fanin of each marked fanout to point to the buffer - Abc_NodeCollectFanouts( pObj, vFanouts ); - Vec_PtrForEachEntry( vFanouts, pFanout, k ) - if ( pFanout->fMarkA ) - Abc_ObjPatchFanin( pFanout, pObj, pBuffer ); - } - Vec_PtrFree( vFanouts ); - // mark the new buffers - Vec_PtrForEachEntry( vFeeds, pObj, i ) - pObj->fMarkA = 1; - return vFeeds; -} - -/**Function************************************************************* - - Synopsis [Removes extra buffers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeMinAreaRemoveBuffers( Abc_Ntk_t * pNtk, Vec_Ptr_t * vBuffers ) -{ - Abc_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( vBuffers, pObj, i ) - { - Abc_ObjTransferFanout( pObj, Abc_ObjFanin0(pObj) ); - Abc_NtkDeleteObj( pObj ); - } - Vec_PtrFree( vBuffers ); -} - /**Function************************************************************* Synopsis [Compute initial values.] @@ -318,7 +259,7 @@ void Abc_NtkRetimeMinAreaRemoveBuffers( Abc_Ntk_t * pNtk, Vec_Ptr_t * vBuffers ) SeeAlso [] ***********************************************************************/ -int Abc_NtkRetimeMinAreaInitValue_rec( Abc_Obj_t * pObj ) +int Abc_NtkRetimeMinAreaInitValues_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; @@ -330,13 +271,13 @@ int Abc_NtkRetimeMinAreaInitValue_rec( Abc_Obj_t * pObj ) if ( Abc_ObjIsBo(pObj) ) { assert( Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ); - pObj->pCopy = (void *)Abc_NtkRetimeMinAreaInitValue_rec( Abc_ObjFanin0(pObj) ); + pObj->pCopy = (void *)Abc_NtkRetimeMinAreaInitValues_rec( Abc_ObjFanin0(pObj) ); return (int)pObj->pCopy; } assert( Abc_ObjIsNode(pObj) ); // visit the fanins Abc_ObjForEachFanin( pObj, pFanin, i ) - Abc_NtkRetimeMinAreaInitValue_rec( pFanin ); + Abc_NtkRetimeMinAreaInitValues_rec( pFanin ); // compute the value of the node pObj->pCopy = (void *)Abc_ObjSopSimulate(pObj); return (int)pObj->pCopy; @@ -353,7 +294,7 @@ int Abc_NtkRetimeMinAreaInitValue_rec( Abc_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -void Abc_NtkRetimeMinAreaInitValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) +void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) { Abc_Obj_t * pObj; int i; @@ -366,7 +307,10 @@ void Abc_NtkRetimeMinAreaInitValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) } // propagate initial values Vec_PtrForEachEntry( vMinCut, pObj, i ) - Abc_NtkRetimeMinAreaInitValue_rec( pObj ); + Abc_NtkRetimeMinAreaInitValues_rec( pObj ); + // unmark the latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NodeSetTravIdPrevious( pObj ); } /**Function************************************************************* @@ -439,6 +383,9 @@ Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMin // unmark the nodes in the cut Vec_PtrForEachEntry( vMinCut, pObj, i ) Abc_NodeSetTravIdPrevious( pObj ); + // unmark the latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NodeSetTravIdPrevious( pObj ); // assign dummy node names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); @@ -447,81 +394,12 @@ Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMin return pNtkNew; } -/**Function************************************************************* - - Synopsis [Mark the inside of the min-cut with current traversal ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeMinAreaMarkInside_rec( Abc_Obj_t * pObj, int fForward ) -{ - Abc_Obj_t * pNext; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return; - Abc_NodeSetTravIdCurrent( pObj ); - // make sure we never reach PIs/POs/latches - if ( Abc_ObjIsPi(pObj) || Abc_ObjIsPo(pObj) || Abc_ObjIsLatch(pObj) ) - printf( "Abc_NtkRetimeMinAreaMarkInside(): The set of nodes is not a cut. Internal error!!!\n" ); - // continue to explore the cone - if ( fForward ) - { - Abc_ObjForEachFanout( pObj, pNext, i ) - Abc_NtkRetimeMinAreaMarkInside_rec( pNext, fForward ); - } - else - { - Abc_ObjForEachFanin( pObj, pNext, i ) - Abc_NtkRetimeMinAreaMarkInside_rec( pNext, fForward ); - } -} - -/**Function************************************************************* - - Synopsis [Marks the inside of the min-cut with current traversal ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeMinAreaMarkInside( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) -{ - Abc_Obj_t * pObj; - int i; - // mark the mincut - Abc_NtkIncrementTravId(pNtk); - Vec_PtrForEachEntry( vMinCut, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // mark the area inside of the cut - if ( fForward ) - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_NtkRetimeMinAreaMarkInside_rec( Abc_ObjFanout0(pObj), fForward ); - } - else - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_NtkRetimeMinAreaMarkInside_rec( Abc_ObjFanin0(pObj), fForward ); - // unmark the nodes in the cut - Vec_PtrForEachEntry( vMinCut, pObj, i ) - Abc_NodeSetTravIdPrevious( pObj ); - } -} - /**Function************************************************************* Synopsis [Updates the network after backward retiming.] - Description [] + Description [Assumes that fMarkA denotes all nodes reachabe from + the latches toward the cut.] SideEffects [] @@ -530,11 +408,9 @@ void Abc_NtkRetimeMinAreaMarkInside( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int ***********************************************************************/ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) { - Vec_Ptr_t * vCis, * vCos, * vBoxes, * vBoxesNew, * vNodes; - Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut, * pNext; + Vec_Ptr_t * vCis, * vCos, * vBoxes, * vBoxesNew, * vNodes, * vBuffers; + Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut, * pNext, * pBuffer; int i, k; - // mark the inside of min-cut with new trav ID - Abc_NtkRetimeMinAreaMarkInside( pNtk, vMinCut, fForward ); // create new latches Vec_PtrShrink( pNtk->vCis, Abc_NtkCiNum(pNtk) - Abc_NtkLatchNum(pNtk) ); Vec_PtrShrink( pNtk->vCos, Abc_NtkCoNum(pNtk) - Abc_NtkLatchNum(pNtk) ); @@ -548,6 +424,7 @@ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, i Vec_PtrPush( vBoxesNew, pObj ); // create or reuse latches vNodes = Vec_PtrAlloc( 100 ); + vBuffers = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( vMinCut, pObj, i ) { if ( Abc_ObjIsCi(pObj) && fForward ) @@ -558,6 +435,27 @@ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, i assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) ); // mark the latch as reused Abc_NodeSetTravIdCurrent( pLatch ); + + // check if there are marked fanouts + // (these are fanouts to be connected to the latch input) + Abc_ObjForEachFanout( pObj, pNext, k ) + if ( pNext->fMarkA ) + break; + if ( k < Abc_ObjFanoutNum(pObj) ) + { + // add the buffer + pBuffer = Abc_NtkCreateNodeBuf( pNtk, Abc_ObjFanin0(pLatchIn) ); + Abc_ObjPatchFanin( pLatchIn, Abc_ObjFanin0(pLatchIn), pBuffer ); + Vec_PtrPush( vBuffers, pBuffer ); + // redirect edges to the unvisited fanouts of the node + Abc_NodeCollectFanouts( pObj, vNodes ); + Vec_PtrForEachEntry( vNodes, pNext, k ) + if ( pNext->fMarkA ) + Abc_ObjPatchFanin( pNext, pObj, pBuffer ); + } + assert( Abc_ObjFanoutNum(pObj) > 0 ); +// if ( Abc_ObjFanoutNum(pObj) == 0 ) +// Abc_NtkDeleteObj_rec( pObj, 0 ); } else if ( Abc_ObjIsCo(pObj) && !fForward ) { @@ -567,14 +465,15 @@ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, i assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) ); // mark the latch as reused Abc_NodeSetTravIdCurrent( pLatch ); + assert( !Abc_ObjFanin0(pLatchIn)->fMarkA ); } else { pLatchOut = Abc_NtkCreateBo(pNtk); pLatch = Abc_NtkCreateLatch(pNtk); pLatchIn = Abc_NtkCreateBi(pNtk); - Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatchOut), NULL ); - Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatchIn), NULL ); + Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" ); + Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" ); // connect Abc_ObjAddFanin( pLatchOut, pLatch ); Abc_ObjAddFanin( pLatch, pLatchIn ); @@ -584,7 +483,7 @@ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, i // redirect edges to the unvisited fanouts of the node Abc_NodeCollectFanouts( pObj, vNodes ); Vec_PtrForEachEntry( vNodes, pNext, k ) - if ( !Abc_NodeIsTravIdCurrent(pNext) ) + if ( !pNext->fMarkA ) Abc_ObjPatchFanin( pNext, pObj, pLatchOut ); } else @@ -592,7 +491,7 @@ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, i // redirect edges to the visited fanouts of the node Abc_NodeCollectFanouts( pObj, vNodes ); Vec_PtrForEachEntry( vNodes, pNext, k ) - if ( Abc_NodeIsTravIdCurrent(pNext) ) + if ( pNext->fMarkA ) Abc_ObjPatchFanin( pNext, pObj, pLatchOut ); } // connect latch to the node @@ -603,6 +502,13 @@ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, i Vec_PtrPush( vCos, pLatchIn ); } Vec_PtrFree( vNodes ); + // remove buffers + Vec_PtrForEachEntry( vBuffers, pObj, i ) + { + Abc_ObjTransferFanout( pObj, Abc_ObjFanin0(pObj) ); + Abc_NtkDeleteObj( pObj ); + } + Vec_PtrFree( vBuffers ); // remove useless latches Vec_PtrForEachEntry( vBoxes, pObj, i ) { @@ -626,6 +532,7 @@ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, i Vec_PtrFree( vBoxes ); } + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/ret/retCore.c b/src/opt/ret/retCore.c index 8ef4e79b..a0e66c92 100644 --- a/src/opt/ret/retCore.c +++ b/src/opt/ret/retCore.c @@ -44,11 +44,21 @@ int timeRetime = 0; int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fVerbose ) { int nLatches = Abc_NtkLatchNum(pNtk); - int nLevels = Abc_NtkGetLevelNum(pNtk); + int nLevels = Abc_NtkLevel(pNtk); int RetValue = 0, clkTotal = clock(); - assert( Mode > 0 && Mode < 6 ); + int nNodesOld, nLatchesOld; + assert( Mode > 0 && Mode < 7 ); assert( !fForwardOnly || !fBackwardOnly ); - // perform forward retiming + + // cleanup the network + nNodesOld = Abc_NtkNodeNum(pNtk); + nLatchesOld = Abc_NtkLatchNum(pNtk); + Abc_NtkCleanupSeq(pNtk, 0, 0, 0); + if ( nNodesOld > Abc_NtkNodeNum(pNtk) || nLatchesOld > Abc_NtkLatchNum(pNtk) ) + printf( "Cleanup before retiming removed %d dangling nodes and %d dangling latches.\n", + nNodesOld - Abc_NtkNodeNum(pNtk), nLatchesOld - Abc_NtkLatchNum(pNtk) ); + + // perform retiming switch ( Mode ) { case 1: // forward @@ -73,6 +83,9 @@ int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOn if ( !fForwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, fVerbose ); break; + case 6: // Pan's algorithm + RetValue = Abc_NtkRetimeLValue( pNtk, 200, fVerbose ); + break; default: printf( "Unknown retiming option.\n" ); break; @@ -80,7 +93,7 @@ int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOn if ( fVerbose ) { printf( "Reduction in area = %3d. Reduction in delay = %3d. ", - nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkGetLevelNum(pNtk) ); + nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkLevel(pNtk) ); PRT( "Total runtime", clock() - clkTotal ); } timeRetime = clock() - clkTotal; @@ -104,8 +117,11 @@ int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk ) Abc_Ntk_t * pNtkRet; assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkLogicToSop( pNtk, 0 ); +// if ( !Abc_NtkCheck( pNtk ) ) +// fprintf( stdout, "Abc_NtkRetimeDebug(): Network check has failed.\n" ); +// Io_WriteBlifLogic( pNtk, "debug_temp.blif", 1 ); pNtkRet = Abc_NtkDup( pNtk ); - Abc_NtkRetime( pNtkRet, 3, 0, 1, 0 ); + Abc_NtkRetime( pNtkRet, 3, 0, 1, 0 ); // debugging backward flow return !Abc_NtkSecFraig( pNtk, pNtkRet, 10000, 3, 0 ); } diff --git a/src/opt/ret/retDelay.c b/src/opt/ret/retDelay.c index d2d87447..80c75729 100644 --- a/src/opt/ret/retDelay.c +++ b/src/opt/ret/retDelay.c @@ -76,7 +76,7 @@ int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int Vec_Ptr_t * vCritical; Vec_Int_t * vValues; Abc_Obj_t * pObj; - int i, k, IterBest, DelayCur, DelayBest, DelayStart; + int i, k, IterBest, DelayCur, DelayBest, DelayStart, LatchesBest; // transfer intitial values if ( fInitial ) { @@ -90,8 +90,15 @@ int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk ); } } +if ( fVerbose ) +{ + if ( !fInitial ) + printf( "Performing analysis:\n" ); + else + printf( "Moving latches to the best position:\n" ); +} // find the best iteration - DelayBest = ABC_INFINITY; IterBest = 0; + DelayBest = ABC_INFINITY; IterBest = 0; LatchesBest = Abc_NtkLatchNum(pNtk); vCritical = Vec_PtrAlloc( 100 ); for ( i = 0; ; i++ ) { @@ -102,16 +109,29 @@ int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int // record this position if it has the best delay if ( DelayBest > DelayCur ) { +if ( fVerbose ) + printf( "%s Iter = %3d. Delay = %3d. Latches = %5d. Delta = %6.2f. Ratio = %4.2f %%\n", + fForward ? "Fwd": "Bwd", i, DelayCur, Abc_NtkLatchNum(pNtk), + 1.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/(DelayBest-DelayCur), + 100.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/Abc_NtkLatchNum(pNtk)/(DelayBest-DelayCur) ); + DelayBest = DelayCur; IterBest = i; + LatchesBest = Abc_NtkLatchNum(pNtk); } // quit after timing analysis if ( i == nIterLimit ) break; + // skip if 10 interations did not give improvement + if ( i - IterBest > 20 ) + break; // try retiming to improve the delay Vec_PtrForEachEntry( vCritical, pObj, k ) if ( Abc_NtkRetimeNodeIsEnabled(pObj, fForward) ) Abc_NtkRetimeNode( pObj, fForward, fInitial ); + // share latches + if ( !fForward ) + Abc_NtkRetimeShareLatches( pNtk, fInitial ); } Vec_PtrFree( vCritical ); // transfer the initial state back to the latches diff --git a/src/opt/ret/retFlow.c b/src/opt/ret/retFlow.c index 642a1f69..24d7bf57 100644 --- a/src/opt/ret/retFlow.c +++ b/src/opt/ret/retFlow.c @@ -46,14 +46,40 @@ static inline Abc_Obj_t * Abc_ObjGetFaninPath( Abc_Obj_t * pObj ) return pFanin; return NULL; } +static inline Abc_Obj_t * Abc_ObjGetPredecessorBwd( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; + int i; + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( Abc_ObjGetPath(pNext) == pObj ) + return pNext; + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( Abc_ObjGetPath(pNext) == pObj ) + return pNext; + return NULL; +} +static inline Abc_Obj_t * Abc_ObjGetPredecessorFwd( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; + int i; + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( Abc_ObjGetPath(pNext) == pObj ) + return pNext; + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( Abc_ObjGetPath(pNext) == pObj ) + return pNext; + return NULL; +} -static int Abc_NtkMaxFlowPath( Abc_Ntk_t * pNtk, int * pStart, int fForward ); static int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ); static int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ); -static Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk ); +static int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj ); +static int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj ); +static Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward ); +static void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); static int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); +static void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); static void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward ); -static void Abc_NtkMaxFlowPrintCut( Vec_Ptr_t * vMinCut ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -93,6 +119,7 @@ void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ) vMinCut = Abc_NtkMaxFlow( pNtk, 0, 1 ); Vec_PtrFree( vMinCut ); Abc_NtkCleanMarkA( pNtk ); + } /**Function************************************************************* @@ -109,37 +136,102 @@ void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ) Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) { Vec_Ptr_t * vMinCut; - int Flow, RetValue; + Abc_Obj_t * pLatch; + int Flow, FlowCur, RetValue, i; int clk = clock(); - int Start = 0; + int fUseDirectedFlow = 1; // find the max-flow Abc_NtkCleanCopy( pNtk ); - for ( Flow = 0; Abc_NtkMaxFlowPath( pNtk, &Start, fForward ); Flow++ ); + Flow = 0; + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( fForward ) + { +// assert( !Abc_ObjFanout0(pLatch)->fMarkA ); + FlowCur = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); + Flow += FlowCur; + } + else + { + assert( !Abc_ObjFanin0(pLatch)->fMarkA ); + FlowCur = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); + Flow += FlowCur; + } + if ( FlowCur ) + Abc_NtkIncrementTravId(pNtk); + } + + if ( !fUseDirectedFlow ) + { + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( fForward ) + { + // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); + FlowCur = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); + Flow += FlowCur; + } + else + { + assert( !Abc_ObjFanin0(pLatch)->fMarkA ); + FlowCur = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); + Flow += FlowCur; + } + if ( FlowCur ) + Abc_NtkIncrementTravId(pNtk); + } + } // Abc_NtkMaxFlowPrintFlow( pNtk, fForward ); + // mark the nodes reachable from the latches + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( fForward ) + { +// assert( !Abc_ObjFanout0(pLatch)->fMarkA ); + if ( fUseDirectedFlow ) + RetValue = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); + else + RetValue = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); + } + else + { + assert( !Abc_ObjFanin0(pLatch)->fMarkA ); + if ( fUseDirectedFlow ) + RetValue = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); + else + RetValue = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); + } + assert( RetValue == 0 ); + } + // find the min-cut with the smallest volume - RetValue = Abc_NtkMaxFlowPath( pNtk, NULL, fForward ); - assert( RetValue == 0 ); - vMinCut = Abc_NtkMaxFlowMinCut( pNtk ); + vMinCut = Abc_NtkMaxFlowMinCut( pNtk, fForward ); + // verify the cut if ( !Abc_NtkMaxFlowVerifyCut(pNtk, vMinCut, fForward) ) printf( "Abc_NtkMaxFlow() error! The computed min-cut is not a cut!\n" ); + // make the cut retimable + Abc_NtkMaxFlowMinCutUpdate( pNtk, vMinCut, fForward ); // report the results if ( fVerbose ) { - printf( "Latches = %6d. %s max-flow = %6d. Min-cut = %6d. ", + printf( "L = %6d. %s max-flow = %6d. Min-cut = %6d. ", Abc_NtkLatchNum(pNtk), fForward? "Forward " : "Backward", Flow, Vec_PtrSize(vMinCut) ); PRT( "Time", clock() - clk ); } -// Abc_NtkMaxFlowPrintCut( vMinCut ); +// Abc_NtkMaxFlowPrintCut( pNtk, vMinCut ); return vMinCut; } /**Function************************************************************* - Synopsis [Finds and augments one path.] + Synopsis [Tries to find an augmenting path originating in this node.] Description [] @@ -148,35 +240,44 @@ PRT( "Time", clock() - clk ); SeeAlso [] ***********************************************************************/ -int Abc_NtkMaxFlowPath( Abc_Ntk_t * pNtk, int * pStart, int fForward ) +int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ) { - Abc_Obj_t * pLatch; - int i, LatchStart = pStart? *pStart : 0; - Abc_NtkIncrementTravId(pNtk); - Vec_PtrForEachEntryStart( pNtk->vBoxes, pLatch, i, LatchStart ) + Abc_Obj_t * pNext, * pPred; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // get the predecessor + pPred = Abc_ObjGetPredecessorBwd( pObj ); + // process node without flow + if ( !Abc_ObjGetPath(pObj) ) { - if ( !Abc_ObjIsLatch(pLatch) ) - continue; - if ( fForward ) - { - assert( !Abc_ObjFanout0(pLatch)->fMarkA ); - if ( Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ) ) - { - if ( pStart ) *pStart = i + 1; - return 1; - } - } - else - { - assert( !Abc_ObjFanin0(pLatch)->fMarkA ); - if ( Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ) ) - { - if ( pStart ) *pStart = i + 1; - return 1; - } - } + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Abc_ObjSetPath( pObj, (void *)1 ); + // explore the fanins + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) ) + return Abc_ObjSetPath( pObj, pNext ); + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) ) + return Abc_ObjSetPath( pObj, pNext ); + return 0; } - if ( pStart ) *pStart = 0; + // pObj has flow - find the fanout with flow + if ( pPred == NULL ) + return 0; + // go through the successors of the predecessor + Abc_ObjForEachFanin( pPred, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) ) + return Abc_ObjSetPath( pPred, pNext ); + Abc_ObjForEachFanout( pPred, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) ) + return Abc_ObjSetPath( pPred, pNext ); + // try the fanout + if ( Abc_NtkMaxFlowBwdPath_rec( pPred ) ) + return Abc_ObjSetPath( pPred, NULL ); return 0; } @@ -191,7 +292,59 @@ int Abc_NtkMaxFlowPath( Abc_Ntk_t * pNtk, int * pStart, int fForward ) SeeAlso [] ***********************************************************************/ -int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ) +int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext, * pPred; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // get the predecessor + pPred = Abc_ObjGetPredecessorFwd( pObj ); + // process node without flow + if ( !Abc_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Abc_ObjSetPath( pObj, (void *)1 ); + // explore the fanins + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) ) + return Abc_ObjSetPath( pObj, pNext ); + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) ) + return Abc_ObjSetPath( pObj, pNext ); + return 0; + } + // pObj has flow - find the fanout with flow + if ( pPred == NULL ) + return 0; + // go through the successors of the predecessor + Abc_ObjForEachFanout( pPred, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) ) + return Abc_ObjSetPath( pPred, pNext ); + Abc_ObjForEachFanin( pPred, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) ) + return Abc_ObjSetPath( pPred, pNext ); + // try the fanout + if ( Abc_NtkMaxFlowFwdPath_rec( pPred ) ) + return Abc_ObjSetPath( pPred, NULL ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this node.] + + Description [This procedure works for directed graphs only!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout, * pFanin; int i; @@ -207,7 +360,7 @@ int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ) return Abc_ObjSetPath( pObj, (void *)1 ); // explore the fanins Abc_ObjForEachFanin( pObj, pFanin, i ) - if ( Abc_NtkMaxFlowBwdPath_rec(pFanin) ) + if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) return Abc_ObjSetPath( pObj, pFanin ); return 0; } @@ -217,10 +370,10 @@ int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ) return 0; // go through the fanins of the fanout with flow Abc_ObjForEachFanin( pFanout, pFanin, i ) - if ( pFanin != pObj && Abc_NtkMaxFlowBwdPath_rec( pFanin ) ) + if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) ) return Abc_ObjSetPath( pFanout, pFanin ); // try the fanout - if ( Abc_NtkMaxFlowBwdPath_rec( pFanout ) ) + if ( Abc_NtkMaxFlowBwdPath2_rec( pFanout ) ) return Abc_ObjSetPath( pFanout, NULL ); return 0; } @@ -229,14 +382,14 @@ int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ) Synopsis [Tries to find an augmenting path originating in this node.] - Description [] + Description [This procedure works for directed graphs only!] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ) +int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout, * pFanin; int i; @@ -252,7 +405,7 @@ int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ) return Abc_ObjSetPath( pObj, (void *)1 ); // explore the fanins Abc_ObjForEachFanout( pObj, pFanout, i ) - if ( Abc_NtkMaxFlowFwdPath_rec(pFanout) ) + if ( Abc_NtkMaxFlowFwdPath2_rec(pFanout) ) return Abc_ObjSetPath( pObj, pFanout ); return 0; } @@ -262,18 +415,17 @@ int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ) return 0; // go through the fanins of the fanout with flow Abc_ObjForEachFanout( pFanin, pFanout, i ) - if ( pFanout != pObj && Abc_NtkMaxFlowFwdPath_rec( pFanout ) ) + if ( Abc_NtkMaxFlowFwdPath2_rec( pFanout ) ) return Abc_ObjSetPath( pFanin, pFanout ); // try the fanout - if ( Abc_NtkMaxFlowFwdPath_rec( pFanin ) ) + if ( Abc_NtkMaxFlowFwdPath2_rec( pFanin ) ) return Abc_ObjSetPath( pFanin, NULL ); return 0; } - /**Function************************************************************* - Synopsis [Find one minumum cut.] + Synopsis [Find minimum-volume minumum cut.] Description [] @@ -282,7 +434,7 @@ int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk ) +Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward ) { Vec_Ptr_t * vMinCut; Abc_Obj_t * pObj; @@ -304,6 +456,113 @@ Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk ) return vMinCut; } +/**Function************************************************************* + + Synopsis [Marks the TFI cone with MarkA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowMarkCut_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; + int i; + if ( pObj->fMarkA ) + return; + pObj->fMarkA = 1; + Abc_ObjForEachFanin( pObj, pNext, i ) + Abc_NtkMaxFlowMarkCut_rec( pNext ); +} + +/**Function************************************************************* + + Synopsis [Visits the TFI up to marked nodes and collects marked nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowCollectCut_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pNext; + int i; + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent(pObj); + if ( pObj->fMarkA ) + { + Vec_PtrPush( vNodes, pObj ); + return; + } + Abc_ObjForEachFanin( pObj, pNext, i ) + Abc_NtkMaxFlowCollectCut_rec( pNext, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Updates the minimum cut to be retimable.] + + Description [This procedure also labels the nodes reachable from + the latches to the cut with fMarkA.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k; + // clean marks + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = 0; + // set latch outputs + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjFanout0(pObj)->fMarkA = 1; + // traverse from cut nodes + Vec_PtrForEachEntry( vMinCut, pObj, i ) + Abc_NtkMaxFlowMarkCut_rec( pObj ); + if ( fForward ) + { + // change mincut to be nodes with unmarked fanouts + Vec_PtrClear( vMinCut ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( !pObj->fMarkA ) + continue; + Abc_ObjForEachFanout( pObj, pNext, k ) + { + if ( pNext->fMarkA ) + continue; + Vec_PtrPush( vMinCut, pObj ); + break; + } + } + } + else + { + // change mincut to be marked fanins of the unmarked nodes + Vec_PtrClear( vMinCut ); + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NtkMaxFlowCollectCut_rec( Abc_ObjFanin0(pObj), vMinCut ); + // transfer the attribute + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = Abc_NodeIsTravIdCurrent(pObj); + // unmark the cut nodes + Vec_PtrForEachEntry( vMinCut, pObj, i ) + pObj->fMarkA = 0; + } +} + /**Function************************************************************* Synopsis [Verifies the min-cut is indeed a cut.] @@ -369,13 +628,11 @@ int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward { if ( fForward ) { - assert( !Abc_ObjFanout0(pObj)->fMarkA ); if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanout0(pObj), fForward ) ) return 0; } else { - assert( !Abc_ObjFanin0(pObj)->fMarkA ); if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanin0(pObj), fForward ) ) return 0; } @@ -456,13 +713,18 @@ void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward ) SeeAlso [] ***********************************************************************/ -void Abc_NtkMaxFlowPrintCut( Vec_Ptr_t * vMinCut ) +void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) { Abc_Obj_t * pObj; int i; printf( "Min-cut: " ); Vec_PtrForEachEntry( vMinCut, pObj, i ) - printf( "%d ", pObj->Id ); + printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id ); + printf( "\n" ); + printf( "Marked nodes: " ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->fMarkA ) + printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id ); printf( "\n" ); } diff --git a/src/opt/ret/retIncrem.c b/src/opt/ret/retIncrem.c index d2ad6a72..93305a8e 100644 --- a/src/opt/ret/retIncrem.c +++ b/src/opt/ret/retIncrem.c @@ -24,8 +24,6 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ); -static int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart ); static int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); //////////////////////////////////////////////////////////////////////// @@ -57,13 +55,15 @@ int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int Abc_NtkOrderCisCos( pNtk ); if ( fMinDelay ) { - nIterLimit = 2 * Abc_NtkGetLevelNum(pNtk); + nIterLimit = 2 * Abc_NtkLevel(pNtk); pNtkCopy = Abc_NtkDup( pNtk ); tLatches = Abc_NtkRetimePrepareLatches( pNtkCopy ); st_free_table( tLatches ); } // collect latches and remove CIs/COs tLatches = Abc_NtkRetimePrepareLatches( pNtk ); + // share the latches + Abc_NtkRetimeShareLatches( pNtk, 0 ); // save boxes vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; // perform the retiming @@ -74,7 +74,7 @@ int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int if ( fMinDelay ) Abc_NtkDelete( pNtkCopy ); // share the latches - Abc_NtkRetimeShareLatches( pNtk ); + Abc_NtkRetimeShareLatches( pNtk, 0 ); // restore boxes pNtk->vBoxes = vBoxes; // finalize the latches @@ -83,7 +83,7 @@ int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int if ( RetValue == 0 ) return 0; // fix the COs - Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); +// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); // check for correctness if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkRetimeForward(): Network check has failed.\n" ); @@ -121,7 +121,8 @@ st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ) // disconnect LO pLatchOut = Abc_ObjFanout0(pLatch); pFanin = Abc_ObjFanin0(pLatchOut); - Abc_ObjTransferFanout( pLatchOut, pFanin ); + if ( Abc_ObjFanoutNum(pLatchOut) > 0 ) + Abc_ObjTransferFanout( pLatchOut, pFanin ); Abc_ObjDeleteFanin( pLatchOut, pFanin ); } return tLatches; @@ -164,8 +165,8 @@ int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nId // this is a new latch pLatchIn = Abc_NtkCreateBi(pNtk); pLatchOut = Abc_NtkCreateBo(pNtk); - Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatchIn), NULL ); - Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatchOut), NULL ); + Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" ); + Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" ); } else { @@ -184,7 +185,8 @@ int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nId // connect Abc_ObjAddFanin( pLatchIn, Abc_ObjFanin0(pLatch) ); Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(pLatch), pLatchIn ); - Abc_ObjTransferFanout( pLatch, pLatchOut ); + if ( Abc_ObjFanoutNum(pLatch) > 0 ) + Abc_ObjTransferFanout( pLatch, pLatchOut ); Abc_ObjAddFanin( pLatchOut, pLatch ); // add to the arrays Vec_PtrPush( vCisNew, pLatchOut ); @@ -221,7 +223,7 @@ int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) Abc_Ntk_t * pNtkNew; Vec_Int_t * vValues; Abc_Obj_t * pObj; - int i, fChanges, nTotalMoves = 0, nTotalMovesLimit = 5000; + int i, fChanges, nTotalMoves = 0, nTotalMovesLimit = 10000; if ( fForward ) Abc_NtkRetimeTranferToCopy( pNtk ); else @@ -330,7 +332,8 @@ void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial ) } // add a new latch on top pNext = Abc_NtkCreateLatch(pObj->pNtk); - Abc_ObjTransferFanout( pObj, pNext ); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Abc_ObjTransferFanout( pObj, pNext ); Abc_ObjAddFanin( pNext, pObj ); // set the initial value if ( fInitial ) @@ -416,35 +419,36 @@ int Abc_NtkRetimeCheckCompatibleLatchFanouts( Abc_Obj_t * pObj ) SeeAlso [] ***********************************************************************/ -void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk ) +void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial ) { Vec_Ptr_t * vNodes; - Abc_Obj_t * pFanin, * pLatch, * pLatchTop, * pLatchCur; + Abc_Obj_t * pFanin, * pLatchTop, * pLatchCur; int i, k; vNodes = Vec_PtrAlloc( 10 ); // consider latch fanins - Abc_NtkForEachObj( pNtk, pLatch, i ) + Abc_NtkForEachObj( pNtk, pFanin, i ) { - if ( !Abc_ObjIsLatch(pLatch) ) - continue; - pFanin = Abc_ObjFanin0(pLatch); if ( Abc_NtkRetimeCheckCompatibleLatchFanouts(pFanin) <= 1 ) continue; // get the first latch + pLatchTop = NULL; Abc_ObjForEachFanout( pFanin, pLatchTop, k ) if ( Abc_ObjIsLatch(pLatchTop) ) break; - assert( Abc_ObjIsLatch(pLatchTop) ); + assert( pLatchTop && Abc_ObjIsLatch(pLatchTop) ); // redirect compatible fanout latches to the first latch Abc_NodeCollectFanouts( pFanin, vNodes ); Vec_PtrForEachEntry( vNodes, pLatchCur, k ) { - if ( pLatchCur == pLatchTop ) - continue; if ( !Abc_ObjIsLatch(pLatchCur) ) continue; + if ( pLatchCur == pLatchTop ) + continue; if ( pLatchCur->pData != pLatchTop->pData ) continue; + // connect the initial state + if ( fInitial ) + Abc_ObjAddFanin( pLatchCur->pCopy, pLatchTop->pCopy ); // redirect the fanouts Abc_ObjTransferFanout( pLatchCur, pLatchTop ); Abc_NtkDeleteObj(pLatchCur); diff --git a/src/opt/ret/retInit.c b/src/opt/ret/retInit.c index 3eb80da1..b53ceeae 100644 --- a/src/opt/ret/retInit.c +++ b/src/opt/ret/retInit.c @@ -281,7 +281,6 @@ void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) Abc_ObjAddFanin( pObj->pCopy, Abc_NtkCreatePi(pNtkNew) ); - pObj = Abc_NtkPo(pNtkNew, 0); // assign dummy node names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); diff --git a/src/opt/ret/retInt.h b/src/opt/ret/retInt.h index 9b3aa00a..28529cdc 100644 --- a/src/opt/ret/retInt.h +++ b/src/opt/ret/retInt.h @@ -51,9 +51,11 @@ extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, extern int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose ); /*=== retDirect.c ========================================================*/ extern int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fVerbose ); -extern void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk ); +extern void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial ); extern int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward ); extern void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial ); +extern st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ); +extern int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart ); /*=== retFlow.c ========================================================*/ extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ); extern Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); @@ -66,6 +68,8 @@ extern Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk ); extern void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); extern Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk ); extern void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose ); +/*=== retLvalue.c ========================================================*/ +extern int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ); #endif diff --git a/src/opt/ret/retLvalue.c b/src/opt/ret/retLvalue.c new file mode 100644 index 00000000..ebb42808 --- /dev/null +++ b/src/opt/ret/retLvalue.c @@ -0,0 +1,419 @@ +/**CFile**************************************************************** + + FileName [retLvalue.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [Implementation of Pan's retiming algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retLvalue.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// node status after updating its arrival time +enum { ABC_RET_UPDATE_FAIL, ABC_RET_UPDATE_NO, ABC_RET_UPDATE_YES }; + +// the internal procedures +static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ); +static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose ); +static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, int FiMin, int FiMax, int nMaxIters, int fVerbose ); +static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, int Fi, int nMaxIters, int fVerbose ); +static int Abc_NtkRetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi ); +static Vec_Ptr_t * Abc_NtkRetimeCollect( Abc_Ntk_t * pNtk ); + +static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); } +static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)pNode->pCopy; } +static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (void *)Value; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Implements Pan's retiming algorithm.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ) +{ + Vec_Int_t * vLags; + int nLatches = Abc_NtkLatchNum(pNtk); + assert( Abc_NtkIsLogic( pNtk ) ); + // get the lags + vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose ); + // compute the retiming +// Abc_NtkRetimeUsingLags( pNtk, vLags, fVerbose ); + Vec_IntFree( vLags ); + // fix the COs +// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + // check for correctness + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" ); + // return the number of latches saved + return nLatches - Abc_NtkLatchNum(pNtk); +} + +/**Function************************************************************* + + Synopsis [Computes the retiming lags.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ) +{ + Vec_Int_t * vLags; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i, FiMax, FiBest, RetValue, clk, clkIter; + char NodeLag; + + // get the upper bound on the clock period + FiMax = 10 + Abc_NtkLevel(pNtk); + + // make sure this clock period is feasible + vNodes = Abc_NtkRetimeCollect(pNtk); + if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, FiMax, nIterLimit, fVerbose ) ) + { + Vec_PtrFree( vNodes ); + printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" ); + return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); + } + + // search for the optimal clock period between 0 and nLevelMax +clk = clock(); + FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, 0, FiMax, nIterLimit, fVerbose ); +clkIter = clock() - clk; + + // recompute the best l-values + RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, FiBest, nIterLimit, fVerbose ); + assert( RetValue ); + Vec_PtrFree( vNodes ); + + // fix the problem with non-converged delays + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 ) + Abc_NodeSetLValue( pNode, 0 ); + + // write the retiming lags + vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest ); + Vec_IntWriteEntry( vLags, pNode->Id, NodeLag ); + } + + // print the result +// if ( fVerbose ) + printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest ); +/* + // print the statistic into a file + { + FILE * pTable; + pTable = fopen( "a/ret__stats.txt", "a+" ); + fprintf( pTable, "%d ", FiBest ); + fclose( pTable ); + } +*/ + +/* + printf( "lvalues and lags : " ); + Abc_NtkForEachNode( pNtk, pNode, i ) + printf( "%d=%d(%d) ", pNode->Id, Abc_NodeGetLValue(pNode), Abc_NodeGetLag(pNode) ); + printf( "\n" ); +*/ +/* + { + FILE * pTable; + pTable = fopen( "a/ret_stats_pan.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pName ); + fprintf( pTable, "%d ", FiBest ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + return vLags; +} + +/**Function************************************************************* + + Synopsis [Performs binary search for the optimal clock period.] + + Description [Assumes that FiMin is infeasible while FiMax is feasible.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, int FiMin, int FiMax, int nMaxIters, int fVerbose ) +{ + int Median; + assert( FiMin < FiMax ); + if ( FiMin + 1 == FiMax ) + return FiMax; + Median = FiMin + (FiMax - FiMin)/2; + if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, Median, nMaxIters, fVerbose ) ) + return Abc_NtkRetimeSearch_rec( pNtk, vNodes, FiMin, Median, nMaxIters, fVerbose ); // Median is feasible + else + return Abc_NtkRetimeSearch_rec( pNtk, vNodes, Median, FiMax, nMaxIters, fVerbose ); // Median is infeasible +} + +/**Function************************************************************* + + Synopsis [Returns 1 if retiming with this clock period is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, int Fi, int nMaxIters, int fVerbose ) +{ + Abc_Obj_t * pObj; + int i, c, fContained, fChange, RetValue, Counter; + char * pReason = ""; + + // set l-values of all nodes to be minus infinity, except PIs and constants + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) == 0 ) + Abc_NodeSetLValue( pObj, 0 ); + else + Abc_NodeSetLValue( pObj, -ABC_INFINITY ); + + // update all values iteratively + Counter = 0; + fContained = 1; + fChange = 1; + for ( c = 0; fContained && fChange && c < nMaxIters; c++ ) + { + // go through the nodes and detect change + fChange = 0; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + RetValue = Abc_NtkRetimeNodeUpdateLValue( pObj, Fi ); + if ( RetValue == ABC_RET_UPDATE_FAIL ) + { + fContained = 0; + break; + } + if ( RetValue == ABC_RET_UPDATE_NO ) + continue; + // updating happened + fChange = 1; + Counter++; + } + } + if ( c == nMaxIters ) + { + fContained = 0; + pReason = "(timeout)"; + } + else + c++; + // report the results + if ( fVerbose ) + { + if ( !fContained ) + printf( "Period = %3d. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason ); + else + printf( "Period = %3d. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter ); + } +/* + // check if any AND gates have infinite delay + Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + Counter += (Abc_NodeGetLValue(pObj) < -ABC_INFINITY/2); + if ( Counter > 0 ) + printf( "Warning: %d internal nodes have wrong l-values!\n", Counter ); +*/ + return fContained; +} + +/**Function************************************************************* + + Synopsis [Computes the l-value of the node.] + + Description [The node can be internal or a PO.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi ) +{ + Abc_Obj_t * pFanin; + int lValueNew, i; + // terminals + if ( Abc_ObjFaninNum(pObj) == 0 ) + return ABC_RET_UPDATE_NO; + // primary outputs + if ( Abc_ObjIsPo(pObj) ) + return (Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi)? ABC_RET_UPDATE_FAIL : ABC_RET_UPDATE_NO; + // other types of objects + if ( Abc_ObjIsBi(pObj) || Abc_ObjIsBo(pObj) ) + lValueNew = Abc_NodeGetLValue(Abc_ObjFanin0(pObj)); + else if ( Abc_ObjIsLatch(pObj) ) + lValueNew = Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi; + else + { + assert( Abc_ObjIsNode(pObj) ); + lValueNew = -ABC_INFINITY; + Abc_ObjForEachFanin( pObj, pFanin, i ) + if ( lValueNew < Abc_NodeGetLValue(pFanin) ) + lValueNew = Abc_NodeGetLValue(pFanin); + lValueNew++; + } + // check if it needs to be updated + if ( lValueNew <= Abc_NodeGetLValue(pObj) ) + return ABC_RET_UPDATE_NO; + // update if needed + Abc_NodeSetLValue( pObj, lValueNew ); + return ABC_RET_UPDATE_YES; +} + +/**Function************************************************************* + + Synopsis [Implements the retiming given as a set of retiming lags.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose ) +{ + Abc_Obj_t * pObj; + int fChanges, fForward, nTotalMoves, Lag, Counter, i; + // iterate over the nodes + nTotalMoves = 0; + do { + fChanges = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Lag = Vec_IntEntry( vLags, pObj->Id ); + if ( !Lag ) + continue; + fForward = (Lag < 0); + if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) ) + { + Abc_NtkRetimeNode( pObj, fForward, 0 ); + fChanges = 1; + nTotalMoves++; + Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 ); + } + } + } while ( fChanges ); + if ( fVerbose ) + printf( "Total latch moves = %d.\n", nTotalMoves ); + // check if there are remaining lags + Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0); + if ( Counter ) + printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Collect objects in the topological order from the latch inputs.] + + Description [If flag fOnlyMarked is set, collects only marked nodes. + Otherwise, collects only unmarked nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeCollect_rec( Abc_Obj_t * pObj, int fOnlyMarked, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // skip collected nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent(pObj); + // collect recursively + if ( fOnlyMarked ^ pObj->fMarkA ) + return; + // visit the fanins + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkRetimeCollect_rec( pFanin, fOnlyMarked, vNodes ); + // collect non-trivial objects + if ( Abc_ObjFaninNum(pObj) > 0 ) + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collect objects in the topological order using LIs as a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkRetimeCollect( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin; + int i, k; + vNodes = Vec_PtrAlloc( 100 ); + // mark the latch inputs + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjFanin0(pObj)->fMarkA = 1; + // collect nodes in the DFS order from the marked nodes + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkRetimeCollect_rec( pObj, 0, vNodes ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjForEachFanin( Abc_ObjFanin0(pObj), pFanin, k ) + Abc_NtkRetimeCollect_rec( pFanin, 0, vNodes ); + // collect marked nodes + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NtkRetimeCollect_rec( Abc_ObjFanin0(pObj), 1, vNodes ); + // clean the marks + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjFanin0(pObj)->fMarkA = 0; + return vNodes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c index a84c82ef..2a6c17bf 100644 --- a/src/sat/bsat/satSolver.c +++ b/src/sat/bsat/satSolver.c @@ -1132,9 +1132,9 @@ int sat_solver_solve(sat_solver* s, lit* begin, lit* end, sint64 nConfLimit, sin s->nConfLimit = s->stats.conflicts + nConfLimit; if ( nInsLimit ) s->nInsLimit = s->stats.inspects + nInsLimit; - if ( nConfLimitGlobal && s->nConfLimit > nConfLimitGlobal ) + if ( nConfLimitGlobal && (s->nConfLimit == 0 || s->nConfLimit > nConfLimitGlobal) ) s->nConfLimit = nConfLimitGlobal; - if ( nInsLimitGlobal && s->nInsLimit > nInsLimitGlobal ) + if ( nInsLimitGlobal && (s->nInsLimit == 0 || s->nInsLimit > nInsLimitGlobal) ) s->nInsLimit = nInsLimitGlobal; //printf("solve: "); printlits(begin, end); printf("\n"); diff --git a/src/sat/fraig/fraigMan.c b/src/sat/fraig/fraigMan.c index b43f1093..4e188cf0 100644 --- a/src/sat/fraig/fraigMan.c +++ b/src/sat/fraig/fraigMan.c @@ -68,6 +68,7 @@ void Prove_ParamsSetDefault( Prove_Params_t * pParams ) // global SAT solver limits pParams->nTotalBacktrackLimit = 0; // global limit on the number of backtracks pParams->nTotalInspectLimit = 0; // global limit on the number of clause inspects +// pParams->nTotalInspectLimit = 100000000; // global limit on the number of clause inspects } /**Function************************************************************* diff --git a/src/temp/aig/aig.h b/src/temp/aig/aig.h deleted file mode 100644 index 0dfc3f11..00000000 --- a/src/temp/aig/aig.h +++ /dev/null @@ -1,321 +0,0 @@ -/**CFile**************************************************************** - - FileName [aig.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __AIG_H__ -#define __AIG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Aig_Man_t_ Aig_Man_t; -typedef struct Aig_Obj_t_ Aig_Obj_t; -typedef int Aig_Edge_t; - -// object types -typedef enum { - AIG_NONE, // 0: non-existent object - AIG_CONST1, // 1: constant 1 - AIG_PI, // 2: primary input - AIG_PO, // 3: primary output - AIG_AND, // 4: AND node - AIG_EXOR, // 5: EXOR node - AIG_VOID // 6: unused object -} Aig_Type_t; - -// the AIG node -struct Aig_Obj_t_ // 4 words -{ - void * pData; // misc - Aig_Obj_t * pFanin0; // fanin - Aig_Obj_t * pFanin1; // fanin - unsigned long Type : 3; // object type - unsigned long fPhase : 1; // value under 000...0 pattern - unsigned long fMarkA : 1; // multipurpose mask - unsigned long fMarkB : 1; // multipurpose mask - unsigned long nRefs : 26; // reference count (level) -}; - -// the AIG manager -struct Aig_Man_t_ -{ - // AIG nodes - Vec_Ptr_t * vPis; // the array of PIs - Vec_Ptr_t * vPos; // the array of POs - Aig_Obj_t * pConst1; // the constant 1 node - Aig_Obj_t Ghost; // the ghost node - // AIG node counters - int nObjs[AIG_VOID];// the number of objects by type - int nCreated; // the number of created objects - int nDeleted; // the number of deleted objects - // stuctural hash table - Aig_Obj_t ** pTable; // structural hash table - int nTableSize; // structural hash table size - // various data members - void * pData; // the temporary data - int nTravIds; // the current traversal ID - int fRefCount; // enables reference counting - int fCatchExor; // enables EXOR nodes - // memory management - Vec_Ptr_t * vChunks; // allocated memory pieces - Vec_Ptr_t * vPages; // memory pages used by nodes - Aig_Obj_t * pListFree; // the list of free nodes - // timing statistics - int time1; - int time2; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define AIG_MIN(a,b) (((a) < (b))? (a) : (b)) -#define AIG_MAX(a,b) (((a) > (b))? (a) : (b)) - -#ifndef PRT -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) -#endif - -static inline int Aig_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -static inline int Aig_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline int Aig_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } -static inline void Aig_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } -static inline void Aig_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } - -static inline Aig_Obj_t * Aig_Regular( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) & ~01); } -static inline Aig_Obj_t * Aig_Not( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) ^ 01); } -static inline Aig_Obj_t * Aig_NotCond( Aig_Obj_t * p, int c ) { return (Aig_Obj_t *)((unsigned long)(p) ^ (c)); } -static inline int Aig_IsComplement( Aig_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } - -static inline Aig_Obj_t * Aig_ManConst0( Aig_Man_t * p ) { return Aig_Not(p->pConst1); } -static inline Aig_Obj_t * Aig_ManConst1( Aig_Man_t * p ) { return p->pConst1; } -static inline Aig_Obj_t * Aig_ManGhost( Aig_Man_t * p ) { return &p->Ghost; } -static inline Aig_Obj_t * Aig_ManPi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPis, i); } - -static inline Aig_Edge_t Aig_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } -static inline int Aig_EdgeId( Aig_Edge_t Edge ) { return Edge >> 1; } -static inline int Aig_EdgeIsComplement( Aig_Edge_t Edge ) { return Edge & 1; } -static inline Aig_Edge_t Aig_EdgeRegular( Aig_Edge_t Edge ) { return (Edge >> 1) << 1; } -static inline Aig_Edge_t Aig_EdgeNot( Aig_Edge_t Edge ) { return Edge ^ 1; } -static inline Aig_Edge_t Aig_EdgeNotCond( Aig_Edge_t Edge, int fCond ) { return Edge ^ fCond; } - -static inline int Aig_ManPiNum( Aig_Man_t * p ) { return p->nObjs[AIG_PI]; } -static inline int Aig_ManPoNum( Aig_Man_t * p ) { return p->nObjs[AIG_PO]; } -static inline int Aig_ManAndNum( Aig_Man_t * p ) { return p->nObjs[AIG_AND]; } -static inline int Aig_ManExorNum( Aig_Man_t * p ) { return p->nObjs[AIG_EXOR]; } -static inline int Aig_ManNodeNum( Aig_Man_t * p ) { return p->nObjs[AIG_AND]+p->nObjs[AIG_EXOR];} -static inline int Aig_ManGetCost( Aig_Man_t * p ) { return p->nObjs[AIG_AND]+3*p->nObjs[AIG_EXOR]; } -static inline int Aig_ManObjNum( Aig_Man_t * p ) { return p->nCreated - p->nDeleted; } - -static inline Aig_Type_t Aig_ObjType( Aig_Obj_t * pObj ) { return pObj->Type; } -static inline int Aig_ObjIsNone( Aig_Obj_t * pObj ) { return pObj->Type == AIG_NONE; } -static inline int Aig_ObjIsConst1( Aig_Obj_t * pObj ) { assert(!Aig_IsComplement(pObj)); return pObj->Type == AIG_CONST1; } -static inline int Aig_ObjIsPi( Aig_Obj_t * pObj ) { return pObj->Type == AIG_PI; } -static inline int Aig_ObjIsPo( Aig_Obj_t * pObj ) { return pObj->Type == AIG_PO; } -static inline int Aig_ObjIsAnd( Aig_Obj_t * pObj ) { return pObj->Type == AIG_AND; } -static inline int Aig_ObjIsExor( Aig_Obj_t * pObj ) { return pObj->Type == AIG_EXOR; } -static inline int Aig_ObjIsNode( Aig_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } -static inline int Aig_ObjIsTerm( Aig_Obj_t * pObj ) { return pObj->Type == AIG_PI || pObj->Type == AIG_PO || pObj->Type == AIG_CONST1; } -static inline int Aig_ObjIsHash( Aig_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } - -static inline int Aig_ObjIsMarkA( Aig_Obj_t * pObj ) { return pObj->fMarkA; } -static inline void Aig_ObjSetMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; } -static inline void Aig_ObjClearMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; } - -static inline void Aig_ObjSetTravId( Aig_Obj_t * pObj, int TravId ) { pObj->pData = (void *)TravId; } -static inline void Aig_ObjSetTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->pData = (void *)p->nTravIds; } -static inline void Aig_ObjSetTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->pData = (void *)(p->nTravIds - 1); } -static inline int Aig_ObjIsTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds); } -static inline int Aig_ObjIsTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds - 1); } - -static inline int Aig_ObjTravId( Aig_Obj_t * pObj ) { return (int)pObj->pData; } -static inline int Aig_ObjPhase( Aig_Obj_t * pObj ) { return pObj->fPhase; } -static inline int Aig_ObjRefs( Aig_Obj_t * pObj ) { return pObj->nRefs; } -static inline void Aig_ObjRef( Aig_Obj_t * pObj ) { pObj->nRefs++; } -static inline void Aig_ObjDeref( Aig_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } -static inline void Aig_ObjClearRef( Aig_Obj_t * pObj ) { pObj->nRefs = 0; } -static inline int Aig_ObjFaninC0( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin0); } -static inline int Aig_ObjFaninC1( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin1); } -static inline Aig_Obj_t * Aig_ObjFanin0( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin0); } -static inline Aig_Obj_t * Aig_ObjFanin1( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin1); } -static inline Aig_Obj_t * Aig_ObjChild0( Aig_Obj_t * pObj ) { return pObj->pFanin0; } -static inline Aig_Obj_t * Aig_ObjChild1( Aig_Obj_t * pObj ) { return pObj->pFanin1; } -static inline Aig_Obj_t * Aig_ObjChild0Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Aig_ObjChild1Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; } -static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { return pObj->nRefs; } -static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { return 1 + Aig_ObjIsExor(pObj) + AIG_MAX(Aig_ObjFanin0(pObj)->nRefs, Aig_ObjFanin1(pObj)->nRefs); } -static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); } -static inline int Aig_ObjWhatFanin( Aig_Obj_t * pObj, Aig_Obj_t * pFanin ) -{ - if ( Aig_ObjFanin0(pObj) == pFanin ) return 0; - if ( Aig_ObjFanin1(pObj) == pFanin ) return 1; - assert(0); return -1; -} -static inline int Aig_ObjFanoutC( Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) -{ - if ( Aig_ObjFanin0(pFanout) == pObj ) return Aig_ObjFaninC0(pObj); - if ( Aig_ObjFanin1(pFanout) == pObj ) return Aig_ObjFaninC1(pObj); - assert(0); return -1; -} - -// create the ghost of the new node -static inline Aig_Obj_t * Aig_ObjCreateGhost( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) -{ - Aig_Obj_t * pGhost; - assert( Type != AIG_AND || !Aig_ObjIsConst1(Aig_Regular(p0)) ); - assert( p1 == NULL || !Aig_ObjIsConst1(Aig_Regular(p1)) ); - assert( Type == AIG_PI || Aig_Regular(p0) != Aig_Regular(p1) ); - pGhost = Aig_ManGhost(p); - pGhost->Type = Type; - pGhost->pFanin0 = p0 < p1? p0 : p1; - pGhost->pFanin1 = p0 < p1? p1 : p0; - return pGhost; -} - -// internal memory manager -static inline Aig_Obj_t * Aig_ManFetchMemory( Aig_Man_t * p ) -{ - extern void Aig_ManAddMemory( Aig_Man_t * p ); - Aig_Obj_t * pTemp; - if ( p->pListFree == NULL ) - Aig_ManAddMemory( p ); - pTemp = p->pListFree; - p->pListFree = *((Aig_Obj_t **)pTemp); - memset( pTemp, 0, sizeof(Aig_Obj_t) ); - return pTemp; -} -static inline void Aig_ManRecycleMemory( Aig_Man_t * p, Aig_Obj_t * pEntry ) -{ - pEntry->Type = AIG_NONE; // distinquishes dead node from live node - *((Aig_Obj_t **)pEntry) = p->pListFree; - p->pListFree = pEntry; -} - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over the primary inputs -#define Aig_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPis, pObj, i ) -// iterator over the primary outputs -#define Aig_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPos, pObj, i ) -// iterator over all objects, including those currently not used -#define Aig_ManForEachNode( p, pObj, i ) \ - for ( i = 0; i < p->nTableSize; i++ ) \ - if ( ((pObj) = p->pTable[i]) == NULL ) {} else - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== aigBalance.c ========================================================*/ -extern Aig_Man_t * Aig_ManBalance( Aig_Man_t * p, int fUpdateLevel ); -extern Aig_Obj_t * Aig_NodeBalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ); -/*=== aigCheck.c ========================================================*/ -extern int Aig_ManCheck( Aig_Man_t * p ); -/*=== aigDfs.c ==========================================================*/ -extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ); -extern Vec_Ptr_t * Aig_ManDfsNode( Aig_Man_t * p, Aig_Obj_t * pNode ); -extern int Aig_ManCountLevels( Aig_Man_t * p ); -extern void Aig_ManCreateRefs( Aig_Man_t * p ); -extern int Aig_DagSize( Aig_Obj_t * pObj ); -extern void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ); -extern Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pObj, int nVars ); -extern Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ); -/*=== aigMan.c ==========================================================*/ -extern Aig_Man_t * Aig_ManStart(); -extern Aig_Man_t * Aig_ManDup( Aig_Man_t * p ); -extern void Aig_ManStop( Aig_Man_t * p ); -extern int Aig_ManCleanup( Aig_Man_t * p ); -extern void Aig_ManPrintStats( Aig_Man_t * p ); -/*=== aigMem.c ==========================================================*/ -extern void Aig_ManStartMemory( Aig_Man_t * p ); -extern void Aig_ManStopMemory( Aig_Man_t * p ); -/*=== aigObj.c ==========================================================*/ -extern Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p ); -extern Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver ); -extern Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ); -extern void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ); -extern void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj ); -/*=== aigOper.c =========================================================*/ -extern Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ); -extern Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ); -extern Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ); -extern Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ); -extern Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ); -extern Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ); -extern Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ); -extern Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ); -/*=== aigTable.c ========================================================*/ -extern Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ); -extern void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern int Aig_TableCountEntries( Aig_Man_t * p ); -extern void Aig_TableProfile( Aig_Man_t * p ); -/*=== aigUtil.c =========================================================*/ -extern void Aig_ManIncrementTravId( Aig_Man_t * p ); -extern void Aig_ManCleanData( Aig_Man_t * p ); -extern void Aig_ObjCollectMulti( Aig_Obj_t * pFunc, Vec_Ptr_t * vSuper ); -extern int Aig_ObjIsMuxType( Aig_Obj_t * pObj ); -extern int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ); -extern Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pObj, Aig_Obj_t ** ppObjT, Aig_Obj_t ** ppObjE ); -extern void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); -extern void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ); -extern void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ); -extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/aig/aigBalance.c b/src/temp/aig/aigBalance.c deleted file mode 100644 index 8806b654..00000000 --- a/src/temp/aig/aigBalance.c +++ /dev/null @@ -1,391 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigBalance.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Algebraic AIG balancing.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Aig_Obj_t * Aig_NodeBalance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); -static Vec_Ptr_t * Aig_NodeBalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); -static int Aig_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); -static void Aig_NodeBalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); -static void Aig_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs algebraic balancing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManBalance( Aig_Man_t * p, int fUpdateLevel ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjNew; - Vec_Vec_t * vStore; - int i; - // create the new manager - pNew = Aig_ManStart(); - pNew->fRefCount = 0; - // map the PI nodes - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pNew); - // balance the AIG - vStore = Vec_VecAlloc( 50 ); - Aig_ManForEachPo( p, pObj, i ) - { - pObjNew = Aig_NodeBalance_rec( pNew, Aig_ObjFanin0(pObj), vStore, 0, fUpdateLevel ); - Aig_ObjCreatePo( pNew, Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ) ); - } - Vec_VecFree( vStore ); - // remove dangling nodes -// Aig_ManCreateRefs( pNew ); -// if ( i = Aig_ManCleanup( pNew ) ) -// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); - // check the resulting AIG - if ( !Aig_ManCheck(pNew) ) - printf( "Aig_ManBalance(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns the new node constructed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_NodeBalance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) -{ - Aig_Obj_t * pObjNew; - Vec_Ptr_t * vSuper; - int i; - assert( !Aig_IsComplement(pObjOld) ); - // return if the result is known - if ( pObjOld->pData ) - return pObjOld->pData; - assert( Aig_ObjIsNode(pObjOld) ); - // get the implication supergate - vSuper = Aig_NodeBalanceCone( pObjOld, vStore, Level ); - // check if supergate contains two nodes in the opposite polarity - if ( vSuper->nSize == 0 ) - return pObjOld->pData = Aig_ManConst0(pNew); - if ( Vec_PtrSize(vSuper) < 2 ) - printf( "BUG!\n" ); - // for each old node, derive the new well-balanced node - for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) - { - pObjNew = Aig_NodeBalance_rec( pNew, Aig_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); - vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement(vSuper->pArray[i]) ); - } - // build the supergate - pObjNew = Aig_NodeBalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel ); - // make sure the balanced node is not assigned -// assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level ); - assert( pObjOld->pData == NULL ); - return pObjOld->pData = pObjNew; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeBalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Aig_Regular(pObj)->fMarkB ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pObj ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Aig_Not(pObj) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) ) - { - Vec_PtrPush( vSuper, pObj ); - Aig_Regular(pObj)->fMarkB = 1; - return 0; - } - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // go through the branches - RetValue1 = Aig_NodeBalanceCone_rec( pRoot, Aig_ObjChild0(pObj), vSuper ); - RetValue2 = Aig_NodeBalanceCone_rec( pRoot, Aig_ObjChild1(pObj), vSuper ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_NodeBalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) -{ - Vec_Ptr_t * vNodes; - int RetValue, i; - assert( !Aig_IsComplement(pObj) ); - // extend the storage - if ( Vec_VecSize( vStore ) <= Level ) - Vec_VecPush( vStore, Level, 0 ); - // get the temporary array of nodes - vNodes = Vec_VecEntry( vStore, Level ); - Vec_PtrClear( vNodes ); - // collect the nodes in the implication supergate - RetValue = Aig_NodeBalanceCone_rec( pObj, pObj, vNodes ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_Regular(pObj)->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) -{ - int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2)); - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Builds implication supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_NodeBalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ) -{ - Aig_Obj_t * pObj1, * pObj2; - int LeftBound; - assert( vSuper->nSize > 1 ); - // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, Aig_NodeCompareLevelsDecrease ); - // balance the nodes - while ( vSuper->nSize > 1 ) - { - // find the left bound on the node to be paired - LeftBound = (!fUpdateLevel)? 0 : Aig_NodeBalanceFindLeft( vSuper ); - // find the node that can be shared (if no such node, randomize choice) - Aig_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR ); - // pull out the last two nodes - pObj1 = Vec_PtrPop(vSuper); - pObj2 = Vec_PtrPop(vSuper); - Aig_NodeBalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type) ); - } - return Vec_PtrEntry(vSuper, 0); -} - -/**Function************************************************************* - - Synopsis [Finds the left bound on the next candidate to be paired.] - - Description [The nodes in the array are in the decreasing order of levels. - The last node in the array has the smallest level. By default it would be paired - with the next node on the left. However, it may be possible to pair it with some - other node on the left, in such a way that the new node is shared. This procedure - finds the index of the left-most node, which can be paired with the last node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) -{ - Aig_Obj_t * pObjRight, * pObjLeft; - int Current; - // if two or less nodes, pair with the first - if ( Vec_PtrSize(vSuper) < 3 ) - return 0; - // set the pointer to the one before the last - Current = Vec_PtrSize(vSuper) - 2; - pObjRight = Vec_PtrEntry( vSuper, Current ); - // go through the nodes to the left of this one - for ( Current--; Current >= 0; Current-- ) - { - // get the next node on the left - pObjLeft = Vec_PtrEntry( vSuper, Current ); - // if the level of this node is different, quit the loop - if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) ) - break; - } - Current++; - // get the node, for which the equality holds - pObjLeft = Vec_PtrEntry( vSuper, Current ); - assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_Regular(pObjRight)) ); - return Current; -} - -/**Function************************************************************* - - Synopsis [Moves closer to the end the node that is best for sharing.] - - Description [If there is no node with sharing, randomly chooses one of - the legal nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_NodeBalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) -{ - Aig_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; - int RightBound, i; - // get the right bound - RightBound = Vec_PtrSize(vSuper) - 2; - assert( LeftBound <= RightBound ); - if ( LeftBound == RightBound ) - return; - // get the two last nodes - pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); - pObj2 = Vec_PtrEntry( vSuper, RightBound ); - if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 ) - return; - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - pObj3 = Vec_PtrEntry( vSuper, i ); - if ( Aig_Regular(pObj3) == p->pConst1 ) - { - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND ); - if ( Aig_TableLookup( p, pGhost ) ) - { - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - } -/* - // we did not find the node to share, randomize choice - { - int Choice = rand() % (RightBound - LeftBound + 1); - pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObj1, * pObj2; - int i; - if ( Vec_PtrPushUnique(vStore, pObj) ) - return; - // find the p of the node - for ( i = vStore->nSize-1; i > 0; i-- ) - { - pObj1 = vStore->pArray[i ]; - pObj2 = vStore->pArray[i-1]; - if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) ) - break; - vStore->pArray[i ] = pObj2; - vStore->pArray[i-1] = pObj1; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aigCheck.c b/src/temp/aig/aigCheck.c deleted file mode 100644 index 61e4cf78..00000000 --- a/src/temp/aig/aigCheck.c +++ /dev/null @@ -1,110 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks the consistency of the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCheck( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObj2; - int i; - // check primary inputs - Aig_ManForEachPi( p, pObj, i ) - { - if ( Aig_ObjFanin0(pObj) || Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); - return 0; - } - } - // check primary outputs - Aig_ManForEachPo( p, pObj, i ) - { - if ( !Aig_ObjFanin0(pObj) ) - { - printf( "Aig_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); - return 0; - } - if ( Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); - return 0; - } - } - // check internal nodes - Aig_ManForEachNode( p, pObj, i ) - { - if ( !Aig_ObjFanin0(pObj) || !Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); - return 0; - } - if ( Aig_ObjFanin0(pObj) >= Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); - return 0; - } - pObj2 = Aig_TableLookup( p, pObj ); - if ( pObj2 != pObj ) - { - printf( "Aig_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); - return 0; - } - } - // count the total number of nodes - if ( Aig_ManObjNum(p) != 1 + Aig_ManPiNum(p) + Aig_ManPoNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) ) - { - printf( "Aig_ManCheck: The number of created nodes is wrong.\n" ); - return 0; - } - // count the number of nodes in the table - if ( Aig_TableCountEntries(p) != Aig_ManAndNum(p) + Aig_ManExorNum(p) ) - { - printf( "Aig_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); - return 0; - } -// if ( !Aig_ManIsAcyclic(p) ) -// return 0; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aigDfs.c b/src/temp/aig/aigDfs.c deleted file mode 100644 index c004cab0..00000000 --- a/src/temp/aig/aigDfs.c +++ /dev/null @@ -1,399 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [DFS traversal procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDfs_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_ManDfs_rec( Aig_ObjFanin0(pObj), vNodes ); - Aig_ManDfs_rec( Aig_ObjFanin1(pObj), vNodes ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA(pObj); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); - Aig_ManForEachNode( p, pObj, i ) - Aig_ManDfs_rec( pObj, vNodes ); - Aig_ManForEachNode( p, pObj, i ) - Aig_ObjClearMarkA(pObj); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfsNode( Aig_Man_t * p, Aig_Obj_t * pNode ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - assert( !Aig_IsComplement(pNode) ); - vNodes = Vec_PtrAlloc( 16 ); - Aig_ManDfs_rec( pNode, vNodes ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_ObjClearMarkA(pObj); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the max number of levels in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCountLevels( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i, LevelsMax, Level0, Level1; - // initialize the levels - Aig_ManConst1(p)->pData = NULL; - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = NULL; - // compute levels in a DFS order - vNodes = Aig_ManDfs( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - Level0 = (int)Aig_ObjFanin0(pObj)->pData; - Level1 = (int)Aig_ObjFanin1(pObj)->pData; - pObj->pData = (void *)(1 + Aig_ObjIsExor(pObj) + AIG_MAX(Level0, Level1)); - } - Vec_PtrFree( vNodes ); - // get levels of the POs - LevelsMax = 0; - Aig_ManForEachPo( p, pObj, i ) - LevelsMax = AIG_MAX( LevelsMax, (int)Aig_ObjFanin0(pObj)->pData ); - return LevelsMax; -} - -/**Function************************************************************* - - Synopsis [Creates correct reference counters at each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCreateRefs( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - if ( p->fRefCount ) - return; - p->fRefCount = 1; - // clear refs - Aig_ObjClearRef( Aig_ManConst1(p) ); - Aig_ManForEachPi( p, pObj, i ) - Aig_ObjClearRef( pObj ); - Aig_ManForEachNode( p, pObj, i ) - Aig_ObjClearRef( pObj ); - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjClearRef( pObj ); - // set refs - Aig_ManForEachNode( p, pObj, i ) - { - Aig_ObjRef( Aig_ObjFanin0(pObj) ); - Aig_ObjRef( Aig_ObjFanin1(pObj) ); - } - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjRef( Aig_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeMark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeMark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeCleanAndMark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeCleanAndMark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeCleanAndMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ConeCountAndMark_rec( Aig_Obj_t * pObj ) -{ - int Counter; - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return 0; - Counter = 1 + Aig_ConeCountAndMark_rec( Aig_ObjFanin0(pObj) ) + - Aig_ConeCountAndMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeUnmark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeUnmark_rec( Aig_ObjFanin1(pObj) ); - assert( Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjClearMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_DagSize( Aig_Obj_t * pObj ) -{ - int Counter; - Counter = Aig_ConeCountAndMark_rec( Aig_Regular(pObj) ); - Aig_ConeUnmark_rec( Aig_Regular(pObj) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_Transfer_rec( Aig_Man_t * pDest, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_Transfer_rec( pDest, Aig_ObjFanin0(pObj) ); - Aig_Transfer_rec( pDest, Aig_ObjFanin1(pObj) ); - pObj->pData = Aig_And( pDest, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pRoot, int nVars ) -{ - Aig_Obj_t * pObj; - int i; - // solve simple cases - if ( pSour == pDest ) - return pRoot; - if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) ) - return Aig_NotCond( Aig_ManConst1(pDest), Aig_IsComplement(pRoot) ); - // set the PI mapping - Aig_ManForEachPi( pSour, pObj, i ) - { - if ( i == nVars ) - break; - pObj->pData = Aig_IthVar(pDest, i); - } - // transfer and set markings - Aig_Transfer_rec( pDest, Aig_Regular(pRoot) ); - // clear the markings - Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); - return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); -} - -/**Function************************************************************* - - Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_Compose_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFunc, Aig_Obj_t * pVar ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsMarkA(pObj) ) - return; - if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) ) - { - pObj->pData = pObj == pVar ? pFunc : pObj; - return; - } - Aig_Compose_rec( p, Aig_ObjFanin0(pObj), pFunc, pVar ); - Aig_Compose_rec( p, Aig_ObjFanin1(pObj), pFunc, pVar ); - pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ) -{ - // quit if the PI variable is not defined - if ( iVar >= Aig_ManPiNum(p) ) - { - printf( "Aig_Compose(): The PI variable %d is not defined.\n", iVar ); - return NULL; - } - // recursively perform composition - Aig_Compose_rec( p, Aig_Regular(pRoot), pFunc, Aig_ManPi(p, iVar) ); - // clear the markings - Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); - return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aigMan.c b/src/temp/aig/aigMan.c deleted file mode 100644 index bb39712f..00000000 --- a/src/temp/aig/aigMan.c +++ /dev/null @@ -1,162 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aig_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManStart() -{ - Aig_Man_t * p; - // start the manager - p = ALLOC( Aig_Man_t, 1 ); - memset( p, 0, sizeof(Aig_Man_t) ); - // perform initializations - p->nTravIds = 1; - p->fRefCount = 1; - p->fCatchExor = 0; - // allocate arrays for nodes - p->vPis = Vec_PtrAlloc( 100 ); - p->vPos = Vec_PtrAlloc( 100 ); - // prepare the internal memory manager - Aig_ManStartMemory( p ); - // create the constant node - p->pConst1 = Aig_ManFetchMemory( p ); - p->pConst1->Type = AIG_CONST1; - p->pConst1->fPhase = 1; - p->nCreated = 1; - // start the table - p->nTableSize = 10007; - p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStop( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - // make sure the nodes have clean marks - pObj = Aig_ManConst1(p); - assert( !pObj->fMarkA && !pObj->fMarkB ); - Aig_ManForEachPi( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - Aig_ManForEachPo( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - Aig_ManForEachNode( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - // print time - if ( p->time1 ) { PRT( "time1", p->time1 ); } - if ( p->time2 ) { PRT( "time2", p->time2 ); } -// Aig_TableProfile( p ); - if ( p->vChunks ) Aig_ManStopMemory( p ); - if ( p->vPis ) Vec_PtrFree( p->vPis ); - if ( p->vPos ) Vec_PtrFree( p->vPos ); - free( p->pTable ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCleanup( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pNode; - int i, nNodesOld; - assert( p->fRefCount ); - nNodesOld = Aig_ManNodeNum(p); - // collect roots of dangling nodes - vNodes = Vec_PtrAlloc( 100 ); - Aig_ManForEachNode( p, pNode, i ) - if ( Aig_ObjRefs(pNode) == 0 ) - Vec_PtrPush( vNodes, pNode ); - // recursively remove dangling nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - Aig_ObjDelete_rec( p, pNode ); - Vec_PtrFree( vNodes ); - return nNodesOld - Aig_ManNodeNum(p); -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManPrintStats( Aig_Man_t * p ) -{ - printf( "PI/PO = %d/%d. ", Aig_ManPiNum(p), Aig_ManPoNum(p) ); - printf( "A = %7d. ", Aig_ManAndNum(p) ); - printf( "X = %5d. ", Aig_ManExorNum(p) ); - printf( "Cre = %7d. ", p->nCreated ); - printf( "Del = %7d. ", p->nDeleted ); - printf( "Lev = %3d. ", Aig_ManCountLevels(p) ); - printf( "\n" ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aigMem.c b/src/temp/aig/aigMem.c deleted file mode 100644 index 1be78a88..00000000 --- a/src/temp/aig/aigMem.c +++ /dev/null @@ -1,115 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigMem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Memory management for the AIG nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// memory management -#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes -#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStartMemory( Aig_Man_t * p ) -{ - p->vChunks = Vec_PtrAlloc( 128 ); - p->vPages = Vec_PtrAlloc( 128 ); -} - -/**Function************************************************************* - - Synopsis [Stops the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStopMemory( Aig_Man_t * p ) -{ - void * pMemory; - int i; - Vec_PtrForEachEntry( p->vChunks, pMemory, i ) - free( pMemory ); - Vec_PtrFree( p->vChunks ); - Vec_PtrFree( p->vPages ); - p->pListFree = NULL; -} - -/**Function************************************************************* - - Synopsis [Allocates additional memory for the nodes.] - - Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. - Records the pointer to the AIG manager in the -1 entry.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManAddMemory( Aig_Man_t * p ) -{ - char * pMemory; - int i, nBytes; - assert( sizeof(Aig_Obj_t) <= 64 ); - assert( p->pListFree == NULL ); -// assert( (Aig_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); - // allocate new memory page - nBytes = sizeof(Aig_Obj_t) * (1<vChunks, pMemory ); - // align memory at the 32-byte boundary - pMemory = pMemory + 64 - (((int)pMemory) & 63); - // remember the manager in the first entry - Vec_PtrPush( p->vPages, pMemory ); - // break the memory down into nodes - p->pListFree = (Aig_Obj_t *)pMemory; - for ( i = 1; i <= IVY_PAGE_MASK; i++ ) - { - *((char **)pMemory) = pMemory + sizeof(Aig_Obj_t); - pMemory += sizeof(Aig_Obj_t); - } - *((char **)pMemory) = NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aigObj.c b/src/temp/aig/aigObj.c deleted file mode 100644 index 51ce6008..00000000 --- a/src/temp/aig/aigObj.c +++ /dev/null @@ -1,228 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigObj.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Adding/removing objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates primary input.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - pObj = Aig_ManFetchMemory( p ); - pObj->Type = AIG_PI; - Vec_PtrPush( p->vPis, pObj ); - p->nObjs[AIG_PI]++; - p->nCreated++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Creates primary output with the given driver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver ) -{ - Aig_Obj_t * pObj; - pObj = Aig_ManFetchMemory( p ); - pObj->Type = AIG_PO; - Vec_PtrPush( p->vPos, pObj ); - // add connections - pObj->pFanin0 = pDriver; - if ( p->fRefCount ) - Aig_ObjRef( Aig_Regular(pDriver) ); - else - pObj->nRefs = Aig_ObjLevel( Aig_Regular(pDriver) ); - // update node counters of the manager - p->nObjs[AIG_PO]++; - p->nCreated++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ) -{ - Aig_Obj_t * pObj; - assert( !Aig_IsComplement(pGhost) ); - assert( Aig_ObjIsNode(pGhost) ); - assert( pGhost == &p->Ghost ); - // get memory for the new object - pObj = Aig_ManFetchMemory( p ); - pObj->Type = pGhost->Type; - // add connections - Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); - // update node counters of the manager - p->nObjs[Aig_ObjType(pObj)]++; - p->nCreated++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // add the first fanin - pObj->pFanin0 = pFan0; - pObj->pFanin1 = pFan1; - // increment references of the fanins and add their fanouts - if ( p->fRefCount ) - { - if ( pFan0 != NULL ) - Aig_ObjRef( Aig_ObjFanin0(pObj) ); - if ( pFan1 != NULL ) - Aig_ObjRef( Aig_ObjFanin1(pObj) ); - } - else - pObj->nRefs = Aig_ObjLevelNew( pObj ); - // add the node to the structural hash table - Aig_TableInsert( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // remove connections - if ( pObj->pFanin0 != NULL ) - Aig_ObjDeref(Aig_ObjFanin0(pObj)); - if ( pObj->pFanin1 != NULL ) - Aig_ObjDeref(Aig_ObjFanin1(pObj)); - // remove the node from the structural hash table - Aig_TableDelete( p, pObj ); - // add the first fanin - pObj->pFanin0 = NULL; - pObj->pFanin1 = NULL; -} - -/**Function************************************************************* - - Synopsis [Deletes the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsTerm(pObj) ); - assert( Aig_ObjRefs(pObj) == 0 ); - // update node counters of the manager - p->nObjs[pObj->Type]--; - p->nDeleted++; - // remove connections - Aig_ObjDisconnect( p, pObj ); - // remove PIs/POs from the arrays - if ( Aig_ObjIsPi(pObj) ) - Vec_PtrRemove( p->vPis, pObj ); - // free the node - Aig_ManRecycleMemory( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Deletes the MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); - Aig_ObjDelete( p, pObj ); - if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 ) - Aig_ObjDelete_rec( p, pFanin0 ); - if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 ) - Aig_ObjDelete_rec( p, pFanin1 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aigOper.c b/src/temp/aig/aigOper.c deleted file mode 100644 index 9985093e..00000000 --- a/src/temp/aig/aigOper.c +++ /dev/null @@ -1,373 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigOper.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// procedure to detect an EXOR gate -static inline int Aig_ObjIsExorType( Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) -{ - if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) - return 0; - p0 = Aig_Regular(p0); - p1 = Aig_Regular(p1); - if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) - return 0; - if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) - return 0; - if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Aig_ObjChild0(p0); - *ppFan1 = Aig_ObjChild1(p0); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns i-th elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ) -{ - int v; - for ( v = Aig_ManPiNum(p); v <= i; v++ ) - Aig_ObjCreatePi( p ); - assert( i < Vec_PtrSize(p->vPis) ); - return Aig_ManPi( p, i ); -} - -/**Function************************************************************* - - Synopsis [Perform one operation.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) -{ - if ( Type == AIG_AND ) - return Aig_And( p, p0, p1 ); - if ( Type == AIG_EXOR ) - return Aig_Exor( p, p0, p1 ); - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ - Aig_Obj_t * pGhost, * pResult; -// Aig_Obj_t * pFan0, * pFan1; - // check trivial cases - if ( p0 == p1 ) - return p0; - if ( p0 == Aig_Not(p1) ) - return Aig_Not(p->pConst1); - if ( Aig_Regular(p0) == p->pConst1 ) - return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1); - if ( Aig_Regular(p1) == p->pConst1 ) - return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1); - // check if it can be an EXOR gate -// if ( Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) -// return Aig_Exor( p, pFan0, pFan1 ); - // check the table - pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_AND ); - if ( pResult = Aig_TableLookup( p, pGhost ) ) - return pResult; - return Aig_ObjCreate( p, pGhost ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ -/* - Aig_Obj_t * pGhost, * pResult; - // check trivial cases - if ( p0 == p1 ) - return Aig_Not(p->pConst1); - if ( p0 == Aig_Not(p1) ) - return p->pConst1; - if ( Aig_Regular(p0) == p->pConst1 ) - return Aig_NotCond( p1, p0 == p->pConst1 ); - if ( Aig_Regular(p1) == p->pConst1 ) - return Aig_NotCond( p0, p1 == p->pConst1 ); - // check the table - pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_EXOR ); - if ( pResult = Aig_TableLookup( p, pGhost ) ) - return pResult; - return Aig_ObjCreate( p, pGhost ); -*/ - return Aig_Or( p, Aig_And(p, p0, Aig_Not(p1)), Aig_And(p, Aig_Not(p0), p1) ); -} - -/**Function************************************************************* - - Synopsis [Implements Boolean OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ - return Aig_Not( Aig_And( p, Aig_Not(p0), Aig_Not(p1) ) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ) -{ -/* - Aig_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; - int Count0, Count1; - // consider trivial cases - if ( p0 == Aig_Not(p1) ) - return Aig_Exor( p, pC, p0 ); - // other cases can be added - // implement the first MUX (F = C * x1 + C' * x0) - - // check for constants here!!! - - pTempA1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, p1, AIG_AND) ); - pTempA2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), p0, AIG_AND) ); - if ( pTempA1 && pTempA2 ) - { - pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempA1), Aig_Not(pTempA2), AIG_AND) ); - if ( pTemp ) return Aig_Not(pTemp); - } - Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); - // implement the second MUX (F' = C * x1' + C' * x0') - pTempB1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, Aig_Not(p1), AIG_AND) ); - pTempB2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), Aig_Not(p0), AIG_AND) ); - if ( pTempB1 && pTempB2 ) - { - pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempB1), Aig_Not(pTempB2), AIG_AND) ); - if ( pTemp ) return pTemp; - } - Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); - // compare and decide which one to implement - if ( Count0 >= Count1 ) - { - pTempA1 = pTempA1? pTempA1 : Aig_And(p, pC, p1); - pTempA2 = pTempA2? pTempA2 : Aig_And(p, Aig_Not(pC), p0); - return Aig_Or( p, pTempA1, pTempA2 ); - } - pTempB1 = pTempB1? pTempB1 : Aig_And(p, pC, Aig_Not(p1)); - pTempB2 = pTempB2? pTempB2 : Aig_And(p, Aig_Not(pC), Aig_Not(p0)); - return Aig_Not( Aig_Or( p, pTempB1, pTempB2 ) ); -*/ - return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ) -{ - return Aig_Or( p, Aig_Or(p, Aig_And(p, pA, pB), Aig_And(p, pA, pC)), Aig_And(p, pB, pC) ); -} - -/**Function************************************************************* - - Synopsis [Constructs the well-balanced tree of gates.] - - Description [Disregards levels and possible logic sharing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Multi_rec( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Aig_Type_t Type ) -{ - Aig_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Aig_Multi_rec( p, ppObjs, nObjs/2, Type ); - pObj2 = Aig_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); - return Aig_Oper( p, pObj1, pObj2, Type ); -} - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type ) -{ - assert( Type == AIG_AND || Type == AIG_EXOR ); - assert( nArgs > 0 ); - return Aig_Multi_rec( p, pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ) -{ - int i; - assert( vPairs->nSize > 0 ); - assert( vPairs->nSize % 2 == 0 ); - // go through the cubes of the node's SOP - for ( i = 0; i < vPairs->nSize; i += 2 ) - vPairs->pArray[i/2] = Aig_Not( Aig_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); - vPairs->nSize = vPairs->nSize/2; - return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_AND ) ); -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst1( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_And( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst0( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_Or( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst0( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_Exor( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aigTable.c b/src/temp/aig/aigTable.c deleted file mode 100644 index 338faa45..00000000 --- a/src/temp/aig/aigTable.c +++ /dev/null @@ -1,266 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Structural hashing table.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006. ] - - Revision [$Id: aigTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing the node -static unsigned long Aig_Hash( Aig_Obj_t * pObj, int TableSize ) -{ - unsigned long Key = Aig_ObjIsExor(pObj) * 1699; - Key ^= (long)Aig_ObjFanin0(pObj) * 7937; - Key ^= (long)Aig_ObjFanin1(pObj) * 2971; - Key ^= Aig_ObjFaninC0(pObj) * 911; - Key ^= Aig_ObjFaninC1(pObj) * 353; - return Key % TableSize; -} - -// returns the place where this node is stored (or should be stored) -static Aig_Obj_t ** Aig_TableFind( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - int i; - assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) ); - assert( Aig_ObjChild0(pObj) < Aig_ObjChild1(pObj) ); - for ( i = Aig_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) - if ( p->pTable[i] == pObj ) - break; - return p->pTable + i; -} - -static void Aig_TableResize( Aig_Man_t * p ); -static unsigned int Cudd_PrimeAig( unsigned int p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks if node with the given attributes is in the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ) -{ - int i; - assert( !Aig_IsComplement(pGhost) ); - assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) ); - assert( Aig_ObjChild0(pGhost) < Aig_ObjChild1(pGhost) ); - if ( p->fRefCount && (!Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost))) ) - return NULL; - for ( i = Aig_Hash(pGhost, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) - { - if ( Aig_ObjChild0(p->pTable[i]) == Aig_ObjChild0(pGhost) && - Aig_ObjChild1(p->pTable[i]) == Aig_ObjChild1(pGhost) && - Aig_ObjType(p->pTable[i]) == Aig_ObjType(pGhost) ) - return p->pTable[i]; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Adds the new node to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t ** ppPlace; - assert( !Aig_IsComplement(pObj) ); - assert( Aig_TableLookup(p, pObj) == NULL ); - if ( p->nTableSize < 2 * Aig_ManNodeNum(p) ) - Aig_TableResize( p ); - ppPlace = Aig_TableFind( p, pObj ); - assert( *ppPlace == NULL ); - *ppPlace = pObj; -} - -/**Function************************************************************* - - Synopsis [Deletes the node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pEntry, ** ppPlace; - int i; - assert( !Aig_IsComplement(pObj) ); - ppPlace = Aig_TableFind( p, pObj ); - assert( *ppPlace == pObj ); // node should be in the table - *ppPlace = NULL; - // rehash the adjacent entries - i = ppPlace - p->pTable; - for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) - { - pEntry = p->pTable[i]; - p->pTable[i] = 0; - Aig_TableInsert( p, pEntry ); - } -} - -/**Function************************************************************* - - Synopsis [Count the number of nodes in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_TableCountEntries( Aig_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - Counter += (p->pTable[i] != NULL); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [Typically this procedure should not be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableResize( Aig_Man_t * p ) -{ - Aig_Obj_t ** pTableOld, ** ppPlace; - int nTableSizeOld, Counter, nEntries, e, clk; -clk = clock(); - // save the old table - pTableOld = p->pTable; - nTableSizeOld = p->nTableSize; - // get the new table - p->nTableSize = Cudd_PrimeAig( 5 * Aig_ManNodeNum(p) ); - p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); - // rehash the entries from the old table - Counter = 0; - for ( e = 0; e < nTableSizeOld; e++ ) - { - if ( pTableOld[e] == 0 ) - continue; - Counter++; - // get the place where this entry goes in the table table - ppPlace = Aig_TableFind( p, pTableOld[e] ); - assert( *ppPlace == NULL ); // should not be in the table - *ppPlace = pTableOld[e]; - } - nEntries = Aig_ManNodeNum(p); -// assert( Counter == nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( pTableOld ); -} - -/**Function******************************************************************** - - Synopsis [Profiles the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Aig_TableProfile( Aig_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - { - if ( p->pTable[i] ) - Counter++; - else if ( Counter ) - { - printf( "%d ", Counter ); - Counter = 0; - } - } -} - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Cudd_PrimeAig( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aigUtil.c b/src/temp/aig/aigUtil.c deleted file mode 100644 index 6534a460..00000000 --- a/src/temp/aig/aigUtil.c +++ /dev/null @@ -1,502 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Various procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Increments the current traversal ID of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManIncrementTravId( Aig_Man_t * p ) -{ - if ( p->nTravIds >= (1<<30)-1 ) - Aig_ManCleanData( p ); - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Sets the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCleanData( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - p->nTravIds = 1; - Aig_ManConst1(p)->pData = NULL; - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = NULL; - Aig_ManForEachPo( p, pObj, i ) - pObj->pData = NULL; - Aig_ManForEachNode( p, pObj, i ) - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCollectMulti_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - if ( pRoot != pObj && (Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || Aig_ObjType(pRoot) != Aig_ObjType(pObj)) ) - { - Vec_PtrPushUnique(vSuper, pObj); - return; - } - Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild0(pObj), vSuper ); - Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild1(pObj), vSuper ); -} - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCollectMulti( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper ) -{ - assert( !Aig_IsComplement(pRoot) ); - Vec_PtrClear( vSuper ); - Aig_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjIsMuxType( Aig_Obj_t * pNode ) -{ - Aig_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Aig_IsComplement(pNode) ); - // if the node is not AND, this is not MUX - if ( !Aig_ObjIsAnd(pNode) ) - return 0; - // if the children are not complemented, this is not MUX - if ( !Aig_ObjFaninC0(pNode) || !Aig_ObjFaninC1(pNode) ) - return 0; - // get children - pNode0 = Aig_ObjFanin0(pNode); - pNode1 = Aig_ObjFanin1(pNode); - // if the children are not ANDs, this is not MUX - if ( !Aig_ObjIsAnd(pNode0) || !Aig_ObjIsAnd(pNode1) ) - return 0; - // otherwise the node is MUX iff it has a pair of equal grandchildren - return (Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1))) || - (Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1))) || - (Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1))) || - (Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1))); -} - - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are inputs of the EXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) -{ - Aig_Obj_t * p0, * p1; - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) ) - return 0; - if ( Aig_ObjIsExor(pObj) ) - { - *ppFan0 = Aig_ObjChild0(pObj); - *ppFan1 = Aig_ObjChild1(pObj); - return 1; - } - assert( Aig_ObjIsAnd(pObj) ); - p0 = Aig_ObjChild0(pObj); - p1 = Aig_ObjChild1(pObj); - if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) - return 0; - p0 = Aig_Regular(p0); - p1 = Aig_Regular(p1); - if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) - return 0; - if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) - return 0; - if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Aig_ObjChild0(p0); - *ppFan1 = Aig_ObjChild1(p0); - return 1; -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pNode, Aig_Obj_t ** ppNodeT, Aig_Obj_t ** ppNodeE ) -{ - Aig_Obj_t * pNode0, * pNode1; - assert( !Aig_IsComplement(pNode) ); - assert( Aig_ObjIsMuxType(pNode) ); - // get children - pNode0 = Aig_ObjFanin0(pNode); - pNode1 = Aig_ObjFanin1(pNode); - - // find the control variable - if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Aig_ObjFaninC1(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - return Aig_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - return Aig_ObjChild1(pNode0);//pNode1->p2; - } - } - else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Aig_ObjFaninC0(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - return Aig_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - return Aig_ObjChild0(pNode0);//pNode1->p1; - } - } - else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Aig_ObjFaninC0(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - return Aig_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - return Aig_ObjChild0(pNode0);//pNode1->p1; - } - } - else if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Aig_ObjFaninC1(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - return Aig_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - return Aig_ObjChild1(pNode0);//pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - - -/**Function************************************************************* - - Synopsis [Prints Verilog formula for the AIG rooted at this node.] - - Description [The formula is in terms of PIs, which should have - their names assigned in pObj->pData fields.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) -{ - Vec_Ptr_t * vSuper; - Aig_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; - int fCompl, i; - // store the complemented attribute - fCompl = Aig_IsComplement(pObj); - pObj = Aig_Regular(pObj); - // constant case - if ( Aig_ObjIsConst1(pObj) ) - { - fprintf( pFile, "%d", !fCompl ); - return; - } - // PI case - if ( Aig_ObjIsPi(pObj) ) - { - fprintf( pFile, "%s%s", fCompl? "~" : "", pObj->pData ); - return; - } - // EXOR case - if ( Aig_ObjIsExor(pObj) ) - { - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry( vLevels, Level ); - Aig_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " ^ " ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; - } - // MUX case - if ( Aig_ObjIsMuxType(pObj) ) - { - if ( Aig_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) - { - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); - fprintf( pFile, " ^ " ); - Aig_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); - fprintf( pFile, "%s", (Level==0? "" : ")") ); - } - else - { - pFaninC = Aig_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Aig_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); - fprintf( pFile, " ? " ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin1, fCompl), vLevels, Level+1 ); - fprintf( pFile, " : " ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); - fprintf( pFile, "%s", (Level==0? "" : ")") ); - } - return; - } - // AND case - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry(vLevels, Level); - Aig_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " %s ", fCompl? "|" : "&" ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; -} - - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ) -{ - assert( !Aig_IsComplement(pObj) ); - printf( "Node %p : ", pObj ); - if ( Aig_ObjIsConst1(pObj) ) - printf( "constant 1" ); - else if ( Aig_ObjIsPi(pObj) ) - printf( "PI" ); - else - printf( "AND( %p%s, %p%s )", - Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " "), - Aig_ObjFanin1(pObj), (Aig_ObjFaninC1(pObj)? "\'" : " ") ); - printf( " (refs = %3d)", Aig_ObjRefs(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - printf( "PIs: " ); - Aig_ManForEachPi( p, pObj, i ) - printf( " %p", pObj ); - printf( "\n" ); - vNodes = Aig_ManDfs( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the AIG into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj, * pConst1 = NULL; - int i, nDigits, Counter = 0; - if ( Aig_ManPoNum(p) == 0 ) - { - printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); - return; - } - // collect nodes in the DFS order - vNodes = Aig_ManDfs( p ); - // assign IDs to objects - Aig_ManConst1(p)->pData = (void *)Counter++; - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = (void *)Counter++; - Aig_ManForEachPo( p, pObj, i ) - pObj->pData = (void *)Counter++; - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pData = (void *)Counter++; - nDigits = Extra_Base10Log( Counter ); - // write the file - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif() in ABC\n" ); - fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); - fprintf( pFile, ".model test\n" ); - // write PIs - fprintf( pFile, ".inputs" ); - Aig_ManForEachPi( p, pObj, i ) - fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); - fprintf( pFile, "\n" ); - // write POs - fprintf( pFile, ".outputs" ); - Aig_ManForEachPo( p, pObj, i ) - fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); - fprintf( pFile, "\n" ); - // write nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", - nDigits, (int)Aig_ObjFanin0(pObj)->pData, - nDigits, (int)Aig_ObjFanin1(pObj)->pData, - nDigits, (int)pObj->pData ); - fprintf( pFile, "%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) ); - } - // write POs - Aig_ManForEachPo( p, pObj, i ) - { - fprintf( pFile, ".names n%0*d n%0*d\n", - nDigits, (int)Aig_ObjFanin0(pObj)->pData, - nDigits, (int)pObj->pData ); - fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) ); - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) - pConst1 = Aig_ManConst1(p); - } - if ( pConst1 ) - fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)pConst1->pData ); - fprintf( pFile, ".end\n\n" ); - fclose( pFile ); - Vec_PtrFree( vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/aig_.c b/src/temp/aig/aig_.c deleted file mode 100644 index 468413fa..00000000 --- a/src/temp/aig/aig_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivy_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/cudd2.c b/src/temp/aig/cudd2.c deleted file mode 100644 index 3cc38260..00000000 --- a/src/temp/aig/cudd2.c +++ /dev/null @@ -1,355 +0,0 @@ -/**CFile**************************************************************** - - FileName [cudd2.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Recording AIGs for the BDD operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 3, 2006.] - - Revision [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" -#include "st.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Aig_CuddMan_t_ Aig_CuddMan_t; -struct Aig_CuddMan_t_ -{ - Aig_Man_t * pAig; // internal AIG package - st_table * pTable; // hash table mapping BDD nodes into AIG nodes -}; - -// static Cudd AIG manager used in this experiment -static Aig_CuddMan_t * s_pCuddMan = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start AIG recording.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ) -{ - int v; - // start the BDD-to-AIG manager when the first BDD manager is allocated - if ( s_pCuddMan != NULL ) - return; - s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 ); - s_pCuddMan->pAig = Aig_ManStart(); - s_pCuddMan->pTable = st_init_table( st_ptrcmp, st_ptrhash ); - for ( v = 0; v < (int)numVars; v++ ) - Aig_ObjCreatePi( s_pCuddMan->pAig ); -} - -/**Function************************************************************* - - Synopsis [Stops AIG recording.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_Quit( void * pCudd ) -{ - assert( s_pCuddMan != NULL ); - Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif" ); - Aig_ManStop( s_pCuddMan->pAig ); - st_free_table( s_pCuddMan->pTable ); - free( s_pCuddMan ); - s_pCuddMan = NULL; -} - -/**Function************************************************************* - - Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Aig_Obj_t * Cudd2_GetArg( void * pArg ) -{ - Aig_Obj_t * pNode; - assert( s_pCuddMan != NULL ); - if ( !st_lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) ) - { - printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" ); - return NULL; - } - return Aig_NotCond( pNode, Aig_IsComplement(pArg) ); -} - -/**Function************************************************************* - - Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult ) -{ - assert( s_pCuddMan != NULL ); - if ( st_is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) ) - return; - pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) ); - st_insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode ); -} - -/**Function************************************************************* - - Synopsis [Registers constant 1 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddOne( void * pCudd, void * pResult ) -{ - Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult ); -} - -/**Function************************************************************* - - Synopsis [Adds elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult ) -{ - int v; - assert( s_pCuddMan != NULL ); - for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ ) - Aig_ObjCreatePi( s_pCuddMan->pAig ); - Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode2 = Cudd2_GetArg( pArg2 ); - pNode = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Should be called after each containment check.] - - Description [Result should be 1 if Cudd2_bddLeq returned 1.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) ); - Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); -} - -/**Function************************************************************* - - Synopsis [Should be called after each equality check.] - - Description [Result should be 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); - Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig/cudd2.h b/src/temp/aig/cudd2.h deleted file mode 100644 index 69711c11..00000000 --- a/src/temp/aig/cudd2.h +++ /dev/null @@ -1,82 +0,0 @@ -/**CFile**************************************************************** - - FileName [cudd2.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 3, 2006.] - - Revision [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CUDD2_H__ -#define __CUDD2_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -// HA: Added for printing messages -#ifndef MSG -#define MSG(msg) (printf("%s = \n",(msg))); -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern void Cudd2_Init ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ); -extern void Cudd2_Quit ( void * pCudd ); -extern void Cudd2_bddOne ( void * pCudd, void * pResult ); -extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult ); -extern void Cudd2_bddAnd ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddOr ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddNand ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddNor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddXor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddXnor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddIte ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ); -extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ); -extern void Cudd2_bddLeq ( void * pCudd, void * pArg0, void * pArg1, int Result ); -extern void Cudd2_bddEqual ( void * pCudd, void * pArg0, void * pArg1, int Result ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/aig/module.make b/src/temp/aig/module.make deleted file mode 100644 index ef9b587c..00000000 --- a/src/temp/aig/module.make +++ /dev/null @@ -1,9 +0,0 @@ -SRC += src/temp/aig/aigBalance.c \ - src/temp/aig/aigCheck.c \ - src/temp/aig/aigDfs.c \ - src/temp/aig/aigMan.c \ - src/temp/aig/aigMem.c \ - src/temp/aig/aigObj.c \ - src/temp/aig/aigOper.c \ - src/temp/aig/aigTable.c \ - src/temp/aig/aigUtil.c diff --git a/src/temp/aig_free/aig.h b/src/temp/aig_free/aig.h deleted file mode 100644 index 0dfc3f11..00000000 --- a/src/temp/aig_free/aig.h +++ /dev/null @@ -1,321 +0,0 @@ -/**CFile**************************************************************** - - FileName [aig.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __AIG_H__ -#define __AIG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Aig_Man_t_ Aig_Man_t; -typedef struct Aig_Obj_t_ Aig_Obj_t; -typedef int Aig_Edge_t; - -// object types -typedef enum { - AIG_NONE, // 0: non-existent object - AIG_CONST1, // 1: constant 1 - AIG_PI, // 2: primary input - AIG_PO, // 3: primary output - AIG_AND, // 4: AND node - AIG_EXOR, // 5: EXOR node - AIG_VOID // 6: unused object -} Aig_Type_t; - -// the AIG node -struct Aig_Obj_t_ // 4 words -{ - void * pData; // misc - Aig_Obj_t * pFanin0; // fanin - Aig_Obj_t * pFanin1; // fanin - unsigned long Type : 3; // object type - unsigned long fPhase : 1; // value under 000...0 pattern - unsigned long fMarkA : 1; // multipurpose mask - unsigned long fMarkB : 1; // multipurpose mask - unsigned long nRefs : 26; // reference count (level) -}; - -// the AIG manager -struct Aig_Man_t_ -{ - // AIG nodes - Vec_Ptr_t * vPis; // the array of PIs - Vec_Ptr_t * vPos; // the array of POs - Aig_Obj_t * pConst1; // the constant 1 node - Aig_Obj_t Ghost; // the ghost node - // AIG node counters - int nObjs[AIG_VOID];// the number of objects by type - int nCreated; // the number of created objects - int nDeleted; // the number of deleted objects - // stuctural hash table - Aig_Obj_t ** pTable; // structural hash table - int nTableSize; // structural hash table size - // various data members - void * pData; // the temporary data - int nTravIds; // the current traversal ID - int fRefCount; // enables reference counting - int fCatchExor; // enables EXOR nodes - // memory management - Vec_Ptr_t * vChunks; // allocated memory pieces - Vec_Ptr_t * vPages; // memory pages used by nodes - Aig_Obj_t * pListFree; // the list of free nodes - // timing statistics - int time1; - int time2; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define AIG_MIN(a,b) (((a) < (b))? (a) : (b)) -#define AIG_MAX(a,b) (((a) > (b))? (a) : (b)) - -#ifndef PRT -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) -#endif - -static inline int Aig_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -static inline int Aig_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline int Aig_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } -static inline void Aig_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } -static inline void Aig_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } - -static inline Aig_Obj_t * Aig_Regular( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) & ~01); } -static inline Aig_Obj_t * Aig_Not( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) ^ 01); } -static inline Aig_Obj_t * Aig_NotCond( Aig_Obj_t * p, int c ) { return (Aig_Obj_t *)((unsigned long)(p) ^ (c)); } -static inline int Aig_IsComplement( Aig_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } - -static inline Aig_Obj_t * Aig_ManConst0( Aig_Man_t * p ) { return Aig_Not(p->pConst1); } -static inline Aig_Obj_t * Aig_ManConst1( Aig_Man_t * p ) { return p->pConst1; } -static inline Aig_Obj_t * Aig_ManGhost( Aig_Man_t * p ) { return &p->Ghost; } -static inline Aig_Obj_t * Aig_ManPi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPis, i); } - -static inline Aig_Edge_t Aig_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } -static inline int Aig_EdgeId( Aig_Edge_t Edge ) { return Edge >> 1; } -static inline int Aig_EdgeIsComplement( Aig_Edge_t Edge ) { return Edge & 1; } -static inline Aig_Edge_t Aig_EdgeRegular( Aig_Edge_t Edge ) { return (Edge >> 1) << 1; } -static inline Aig_Edge_t Aig_EdgeNot( Aig_Edge_t Edge ) { return Edge ^ 1; } -static inline Aig_Edge_t Aig_EdgeNotCond( Aig_Edge_t Edge, int fCond ) { return Edge ^ fCond; } - -static inline int Aig_ManPiNum( Aig_Man_t * p ) { return p->nObjs[AIG_PI]; } -static inline int Aig_ManPoNum( Aig_Man_t * p ) { return p->nObjs[AIG_PO]; } -static inline int Aig_ManAndNum( Aig_Man_t * p ) { return p->nObjs[AIG_AND]; } -static inline int Aig_ManExorNum( Aig_Man_t * p ) { return p->nObjs[AIG_EXOR]; } -static inline int Aig_ManNodeNum( Aig_Man_t * p ) { return p->nObjs[AIG_AND]+p->nObjs[AIG_EXOR];} -static inline int Aig_ManGetCost( Aig_Man_t * p ) { return p->nObjs[AIG_AND]+3*p->nObjs[AIG_EXOR]; } -static inline int Aig_ManObjNum( Aig_Man_t * p ) { return p->nCreated - p->nDeleted; } - -static inline Aig_Type_t Aig_ObjType( Aig_Obj_t * pObj ) { return pObj->Type; } -static inline int Aig_ObjIsNone( Aig_Obj_t * pObj ) { return pObj->Type == AIG_NONE; } -static inline int Aig_ObjIsConst1( Aig_Obj_t * pObj ) { assert(!Aig_IsComplement(pObj)); return pObj->Type == AIG_CONST1; } -static inline int Aig_ObjIsPi( Aig_Obj_t * pObj ) { return pObj->Type == AIG_PI; } -static inline int Aig_ObjIsPo( Aig_Obj_t * pObj ) { return pObj->Type == AIG_PO; } -static inline int Aig_ObjIsAnd( Aig_Obj_t * pObj ) { return pObj->Type == AIG_AND; } -static inline int Aig_ObjIsExor( Aig_Obj_t * pObj ) { return pObj->Type == AIG_EXOR; } -static inline int Aig_ObjIsNode( Aig_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } -static inline int Aig_ObjIsTerm( Aig_Obj_t * pObj ) { return pObj->Type == AIG_PI || pObj->Type == AIG_PO || pObj->Type == AIG_CONST1; } -static inline int Aig_ObjIsHash( Aig_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } - -static inline int Aig_ObjIsMarkA( Aig_Obj_t * pObj ) { return pObj->fMarkA; } -static inline void Aig_ObjSetMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; } -static inline void Aig_ObjClearMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; } - -static inline void Aig_ObjSetTravId( Aig_Obj_t * pObj, int TravId ) { pObj->pData = (void *)TravId; } -static inline void Aig_ObjSetTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->pData = (void *)p->nTravIds; } -static inline void Aig_ObjSetTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->pData = (void *)(p->nTravIds - 1); } -static inline int Aig_ObjIsTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds); } -static inline int Aig_ObjIsTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds - 1); } - -static inline int Aig_ObjTravId( Aig_Obj_t * pObj ) { return (int)pObj->pData; } -static inline int Aig_ObjPhase( Aig_Obj_t * pObj ) { return pObj->fPhase; } -static inline int Aig_ObjRefs( Aig_Obj_t * pObj ) { return pObj->nRefs; } -static inline void Aig_ObjRef( Aig_Obj_t * pObj ) { pObj->nRefs++; } -static inline void Aig_ObjDeref( Aig_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } -static inline void Aig_ObjClearRef( Aig_Obj_t * pObj ) { pObj->nRefs = 0; } -static inline int Aig_ObjFaninC0( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin0); } -static inline int Aig_ObjFaninC1( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin1); } -static inline Aig_Obj_t * Aig_ObjFanin0( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin0); } -static inline Aig_Obj_t * Aig_ObjFanin1( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin1); } -static inline Aig_Obj_t * Aig_ObjChild0( Aig_Obj_t * pObj ) { return pObj->pFanin0; } -static inline Aig_Obj_t * Aig_ObjChild1( Aig_Obj_t * pObj ) { return pObj->pFanin1; } -static inline Aig_Obj_t * Aig_ObjChild0Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Aig_ObjChild1Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; } -static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { return pObj->nRefs; } -static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { return 1 + Aig_ObjIsExor(pObj) + AIG_MAX(Aig_ObjFanin0(pObj)->nRefs, Aig_ObjFanin1(pObj)->nRefs); } -static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); } -static inline int Aig_ObjWhatFanin( Aig_Obj_t * pObj, Aig_Obj_t * pFanin ) -{ - if ( Aig_ObjFanin0(pObj) == pFanin ) return 0; - if ( Aig_ObjFanin1(pObj) == pFanin ) return 1; - assert(0); return -1; -} -static inline int Aig_ObjFanoutC( Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) -{ - if ( Aig_ObjFanin0(pFanout) == pObj ) return Aig_ObjFaninC0(pObj); - if ( Aig_ObjFanin1(pFanout) == pObj ) return Aig_ObjFaninC1(pObj); - assert(0); return -1; -} - -// create the ghost of the new node -static inline Aig_Obj_t * Aig_ObjCreateGhost( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) -{ - Aig_Obj_t * pGhost; - assert( Type != AIG_AND || !Aig_ObjIsConst1(Aig_Regular(p0)) ); - assert( p1 == NULL || !Aig_ObjIsConst1(Aig_Regular(p1)) ); - assert( Type == AIG_PI || Aig_Regular(p0) != Aig_Regular(p1) ); - pGhost = Aig_ManGhost(p); - pGhost->Type = Type; - pGhost->pFanin0 = p0 < p1? p0 : p1; - pGhost->pFanin1 = p0 < p1? p1 : p0; - return pGhost; -} - -// internal memory manager -static inline Aig_Obj_t * Aig_ManFetchMemory( Aig_Man_t * p ) -{ - extern void Aig_ManAddMemory( Aig_Man_t * p ); - Aig_Obj_t * pTemp; - if ( p->pListFree == NULL ) - Aig_ManAddMemory( p ); - pTemp = p->pListFree; - p->pListFree = *((Aig_Obj_t **)pTemp); - memset( pTemp, 0, sizeof(Aig_Obj_t) ); - return pTemp; -} -static inline void Aig_ManRecycleMemory( Aig_Man_t * p, Aig_Obj_t * pEntry ) -{ - pEntry->Type = AIG_NONE; // distinquishes dead node from live node - *((Aig_Obj_t **)pEntry) = p->pListFree; - p->pListFree = pEntry; -} - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over the primary inputs -#define Aig_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPis, pObj, i ) -// iterator over the primary outputs -#define Aig_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPos, pObj, i ) -// iterator over all objects, including those currently not used -#define Aig_ManForEachNode( p, pObj, i ) \ - for ( i = 0; i < p->nTableSize; i++ ) \ - if ( ((pObj) = p->pTable[i]) == NULL ) {} else - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== aigBalance.c ========================================================*/ -extern Aig_Man_t * Aig_ManBalance( Aig_Man_t * p, int fUpdateLevel ); -extern Aig_Obj_t * Aig_NodeBalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ); -/*=== aigCheck.c ========================================================*/ -extern int Aig_ManCheck( Aig_Man_t * p ); -/*=== aigDfs.c ==========================================================*/ -extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ); -extern Vec_Ptr_t * Aig_ManDfsNode( Aig_Man_t * p, Aig_Obj_t * pNode ); -extern int Aig_ManCountLevels( Aig_Man_t * p ); -extern void Aig_ManCreateRefs( Aig_Man_t * p ); -extern int Aig_DagSize( Aig_Obj_t * pObj ); -extern void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ); -extern Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pObj, int nVars ); -extern Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ); -/*=== aigMan.c ==========================================================*/ -extern Aig_Man_t * Aig_ManStart(); -extern Aig_Man_t * Aig_ManDup( Aig_Man_t * p ); -extern void Aig_ManStop( Aig_Man_t * p ); -extern int Aig_ManCleanup( Aig_Man_t * p ); -extern void Aig_ManPrintStats( Aig_Man_t * p ); -/*=== aigMem.c ==========================================================*/ -extern void Aig_ManStartMemory( Aig_Man_t * p ); -extern void Aig_ManStopMemory( Aig_Man_t * p ); -/*=== aigObj.c ==========================================================*/ -extern Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p ); -extern Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver ); -extern Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ); -extern void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ); -extern void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj ); -/*=== aigOper.c =========================================================*/ -extern Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ); -extern Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ); -extern Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ); -extern Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ); -extern Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ); -extern Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ); -extern Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ); -extern Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ); -/*=== aigTable.c ========================================================*/ -extern Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ); -extern void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern int Aig_TableCountEntries( Aig_Man_t * p ); -extern void Aig_TableProfile( Aig_Man_t * p ); -/*=== aigUtil.c =========================================================*/ -extern void Aig_ManIncrementTravId( Aig_Man_t * p ); -extern void Aig_ManCleanData( Aig_Man_t * p ); -extern void Aig_ObjCollectMulti( Aig_Obj_t * pFunc, Vec_Ptr_t * vSuper ); -extern int Aig_ObjIsMuxType( Aig_Obj_t * pObj ); -extern int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ); -extern Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pObj, Aig_Obj_t ** ppObjT, Aig_Obj_t ** ppObjE ); -extern void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); -extern void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ); -extern void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ); -extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/aig_free/aigBalance.c b/src/temp/aig_free/aigBalance.c deleted file mode 100644 index 1abc672d..00000000 --- a/src/temp/aig_free/aigBalance.c +++ /dev/null @@ -1,391 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigBalance.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Algebraic AIG balancing.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Aig_Obj_t * Aig_NodeBalance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); -static Vec_Ptr_t * Aig_NodeBalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); -static int Aig_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); -static void Aig_NodeBalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); -static void Aig_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs algebraic balancing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManBalance( Aig_Man_t * p, int fUpdateLevel ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjNew; - Vec_Vec_t * vStore; - int i; - // create the new manager - pNew = Aig_ManStart(); - pNew->fRefCount = 0; - // map the PI nodes - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pNew); - // balance the AIG - vStore = Vec_VecAlloc( 50 ); - Aig_ManForEachPo( p, pObj, i ) - { - pObjNew = Aig_NodeBalance_rec( pNew, Aig_ObjFanin0(pObj), vStore, 0, fUpdateLevel ); - Aig_ObjCreatePo( pNew, Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ) ); - } - Vec_VecFree( vStore ); - // remove dangling nodes -// Aig_ManCreateRefs( pNew ); -// if ( i = Aig_ManCleanup( pNew ) ) -// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); - // check the resulting AIG - if ( !Aig_ManCheck(pNew) ) - printf( "Aig_ManBalance(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns the new node constructed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_NodeBalance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) -{ - Aig_Obj_t * pObjNew; - Vec_Ptr_t * vSuper; - int i; - assert( !Aig_IsComplement(pObjOld) ); - // return if the result is known - if ( pObjOld->pData ) - return pObjOld->pData; - assert( Aig_ObjIsNode(pObjOld) ); - // get the implication supergate - vSuper = Aig_NodeBalanceCone( pObjOld, vStore, Level ); - // check if supergate contains two nodes in the opposite polarity - if ( vSuper->nSize == 0 ) - return pObjOld->pData = Aig_ManConst0(pNew); - if ( Vec_PtrSize(vSuper) < 2 ) - printf( "BUG!\n" ); - // for each old node, derive the new well-balanced node - for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) - { - pObjNew = Aig_NodeBalance_rec( pNew, Aig_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); - vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement(vSuper->pArray[i]) ); - } - // build the supergate - pObjNew = Aig_NodeBalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel ); - // make sure the balanced node is not assigned -// assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level ); - assert( pObjOld->pData == NULL ); - return pObjOld->pData = pObjNew; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeBalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Aig_Regular(pObj)->fMarkB ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pObj ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Aig_Not(pObj) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) ) - { - Vec_PtrPush( vSuper, pObj ); - Aig_Regular(pObj)->fMarkB = 1; - return 0; - } - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // go through the branches - RetValue1 = Aig_NodeBalanceCone_rec( pRoot, Aig_ObjChild0(pObj), vSuper ); - RetValue2 = Aig_NodeBalanceCone_rec( pRoot, Aig_ObjChild1(pObj), vSuper ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_NodeBalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) -{ - Vec_Ptr_t * vNodes; - int RetValue, i; - assert( !Aig_IsComplement(pObj) ); - // extend the storage - if ( Vec_VecSize( vStore ) <= Level ) - Vec_VecPush( vStore, Level, 0 ); - // get the temporary array of nodes - vNodes = Vec_VecEntry( vStore, Level ); - Vec_PtrClear( vNodes ); - // collect the nodes in the implication supergate - RetValue = Aig_NodeBalanceCone_rec( pObj, pObj, vNodes ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_Regular(pObj)->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) -{ - int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2)); - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Builds implication supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_NodeBalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ) -{ - Aig_Obj_t * pObj1, * pObj2; - int LeftBound; - assert( vSuper->nSize > 1 ); - // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, Aig_NodeCompareLevelsDecrease ); - // balance the nodes - while ( vSuper->nSize > 1 ) - { - // find the left bound on the node to be paired - LeftBound = (!fUpdateLevel)? 0 : Aig_NodeBalanceFindLeft( vSuper ); - // find the node that can be shared (if no such node, randomize choice) - Aig_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR ); - // pull out the last two nodes - pObj1 = Vec_PtrPop(vSuper); - pObj2 = Vec_PtrPop(vSuper); - Aig_NodeBalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type) ); - } - return Vec_PtrEntry(vSuper, 0); -} - -/**Function************************************************************* - - Synopsis [Finds the left bound on the next candidate to be paired.] - - Description [The nodes in the array are in the decreasing order of levels. - The last node in the array has the smallest level. By default it would be paired - with the next node on the left. However, it may be possible to pair it with some - other node on the left, in such a way that the new node is shared. This procedure - finds the index of the left-most node, which can be paired with the last node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) -{ - Aig_Obj_t * pObjRight, * pObjLeft; - int Current; - // if two or less nodes, pair with the first - if ( Vec_PtrSize(vSuper) < 3 ) - return 0; - // set the pointer to the one before the last - Current = Vec_PtrSize(vSuper) - 2; - pObjRight = Vec_PtrEntry( vSuper, Current ); - // go through the nodes to the left of this one - for ( Current--; Current >= 0; Current-- ) - { - // get the next node on the left - pObjLeft = Vec_PtrEntry( vSuper, Current ); - // if the level of this node is different, quit the loop - if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) ) - break; - } - Current++; - // get the node, for which the equality holds - pObjLeft = Vec_PtrEntry( vSuper, Current ); - assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_Regular(pObjRight)) ); - return Current; -} - -/**Function************************************************************* - - Synopsis [Moves closer to the end the node that is best for sharing.] - - Description [If there is no node with sharing, randomly chooses one of - the legal nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_NodeBalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) -{ - Aig_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; - int RightBound, i; - // get the right bound - RightBound = Vec_PtrSize(vSuper) - 2; - assert( LeftBound <= RightBound ); - if ( LeftBound == RightBound ) - return; - // get the two last nodes - pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); - pObj2 = Vec_PtrEntry( vSuper, RightBound ); - if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 ) - return; - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - pObj3 = Vec_PtrEntry( vSuper, i ); - if ( Aig_Regular(pObj3) == p->pConst1 ) - { - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND ); - if ( Aig_TableLookup( p, pGhost ) ) - { - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - } -/* - // we did not find the node to share, randomize choice - { - int Choice = rand() % (RightBound - LeftBound + 1); - pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObj1, * pObj2; - int i; - if ( Vec_PtrPushUnique(vStore, pObj) ) - return; - // find the p of the node - for ( i = vStore->nSize-1; i > 0; i-- ) - { - pObj1 = vStore->pArray[i ]; - pObj2 = vStore->pArray[i-1]; - if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) ) - break; - vStore->pArray[i ] = pObj2; - vStore->pArray[i-1] = pObj1; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/aigCheck.c b/src/temp/aig_free/aigCheck.c deleted file mode 100644 index 61e4cf78..00000000 --- a/src/temp/aig_free/aigCheck.c +++ /dev/null @@ -1,110 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks the consistency of the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCheck( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObj2; - int i; - // check primary inputs - Aig_ManForEachPi( p, pObj, i ) - { - if ( Aig_ObjFanin0(pObj) || Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); - return 0; - } - } - // check primary outputs - Aig_ManForEachPo( p, pObj, i ) - { - if ( !Aig_ObjFanin0(pObj) ) - { - printf( "Aig_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); - return 0; - } - if ( Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); - return 0; - } - } - // check internal nodes - Aig_ManForEachNode( p, pObj, i ) - { - if ( !Aig_ObjFanin0(pObj) || !Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); - return 0; - } - if ( Aig_ObjFanin0(pObj) >= Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); - return 0; - } - pObj2 = Aig_TableLookup( p, pObj ); - if ( pObj2 != pObj ) - { - printf( "Aig_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); - return 0; - } - } - // count the total number of nodes - if ( Aig_ManObjNum(p) != 1 + Aig_ManPiNum(p) + Aig_ManPoNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) ) - { - printf( "Aig_ManCheck: The number of created nodes is wrong.\n" ); - return 0; - } - // count the number of nodes in the table - if ( Aig_TableCountEntries(p) != Aig_ManAndNum(p) + Aig_ManExorNum(p) ) - { - printf( "Aig_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); - return 0; - } -// if ( !Aig_ManIsAcyclic(p) ) -// return 0; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/aigDfs.c b/src/temp/aig_free/aigDfs.c deleted file mode 100644 index c004cab0..00000000 --- a/src/temp/aig_free/aigDfs.c +++ /dev/null @@ -1,399 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [DFS traversal procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDfs_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_ManDfs_rec( Aig_ObjFanin0(pObj), vNodes ); - Aig_ManDfs_rec( Aig_ObjFanin1(pObj), vNodes ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA(pObj); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); - Aig_ManForEachNode( p, pObj, i ) - Aig_ManDfs_rec( pObj, vNodes ); - Aig_ManForEachNode( p, pObj, i ) - Aig_ObjClearMarkA(pObj); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfsNode( Aig_Man_t * p, Aig_Obj_t * pNode ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - assert( !Aig_IsComplement(pNode) ); - vNodes = Vec_PtrAlloc( 16 ); - Aig_ManDfs_rec( pNode, vNodes ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_ObjClearMarkA(pObj); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the max number of levels in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCountLevels( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i, LevelsMax, Level0, Level1; - // initialize the levels - Aig_ManConst1(p)->pData = NULL; - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = NULL; - // compute levels in a DFS order - vNodes = Aig_ManDfs( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - Level0 = (int)Aig_ObjFanin0(pObj)->pData; - Level1 = (int)Aig_ObjFanin1(pObj)->pData; - pObj->pData = (void *)(1 + Aig_ObjIsExor(pObj) + AIG_MAX(Level0, Level1)); - } - Vec_PtrFree( vNodes ); - // get levels of the POs - LevelsMax = 0; - Aig_ManForEachPo( p, pObj, i ) - LevelsMax = AIG_MAX( LevelsMax, (int)Aig_ObjFanin0(pObj)->pData ); - return LevelsMax; -} - -/**Function************************************************************* - - Synopsis [Creates correct reference counters at each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCreateRefs( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - if ( p->fRefCount ) - return; - p->fRefCount = 1; - // clear refs - Aig_ObjClearRef( Aig_ManConst1(p) ); - Aig_ManForEachPi( p, pObj, i ) - Aig_ObjClearRef( pObj ); - Aig_ManForEachNode( p, pObj, i ) - Aig_ObjClearRef( pObj ); - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjClearRef( pObj ); - // set refs - Aig_ManForEachNode( p, pObj, i ) - { - Aig_ObjRef( Aig_ObjFanin0(pObj) ); - Aig_ObjRef( Aig_ObjFanin1(pObj) ); - } - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjRef( Aig_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeMark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeMark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeCleanAndMark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeCleanAndMark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeCleanAndMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ConeCountAndMark_rec( Aig_Obj_t * pObj ) -{ - int Counter; - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return 0; - Counter = 1 + Aig_ConeCountAndMark_rec( Aig_ObjFanin0(pObj) ) + - Aig_ConeCountAndMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeUnmark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeUnmark_rec( Aig_ObjFanin1(pObj) ); - assert( Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjClearMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_DagSize( Aig_Obj_t * pObj ) -{ - int Counter; - Counter = Aig_ConeCountAndMark_rec( Aig_Regular(pObj) ); - Aig_ConeUnmark_rec( Aig_Regular(pObj) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_Transfer_rec( Aig_Man_t * pDest, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_Transfer_rec( pDest, Aig_ObjFanin0(pObj) ); - Aig_Transfer_rec( pDest, Aig_ObjFanin1(pObj) ); - pObj->pData = Aig_And( pDest, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pRoot, int nVars ) -{ - Aig_Obj_t * pObj; - int i; - // solve simple cases - if ( pSour == pDest ) - return pRoot; - if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) ) - return Aig_NotCond( Aig_ManConst1(pDest), Aig_IsComplement(pRoot) ); - // set the PI mapping - Aig_ManForEachPi( pSour, pObj, i ) - { - if ( i == nVars ) - break; - pObj->pData = Aig_IthVar(pDest, i); - } - // transfer and set markings - Aig_Transfer_rec( pDest, Aig_Regular(pRoot) ); - // clear the markings - Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); - return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); -} - -/**Function************************************************************* - - Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_Compose_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFunc, Aig_Obj_t * pVar ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsMarkA(pObj) ) - return; - if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) ) - { - pObj->pData = pObj == pVar ? pFunc : pObj; - return; - } - Aig_Compose_rec( p, Aig_ObjFanin0(pObj), pFunc, pVar ); - Aig_Compose_rec( p, Aig_ObjFanin1(pObj), pFunc, pVar ); - pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ) -{ - // quit if the PI variable is not defined - if ( iVar >= Aig_ManPiNum(p) ) - { - printf( "Aig_Compose(): The PI variable %d is not defined.\n", iVar ); - return NULL; - } - // recursively perform composition - Aig_Compose_rec( p, Aig_Regular(pRoot), pFunc, Aig_ManPi(p, iVar) ); - // clear the markings - Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); - return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/aigMan.c b/src/temp/aig_free/aigMan.c deleted file mode 100644 index bb39712f..00000000 --- a/src/temp/aig_free/aigMan.c +++ /dev/null @@ -1,162 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aig_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManStart() -{ - Aig_Man_t * p; - // start the manager - p = ALLOC( Aig_Man_t, 1 ); - memset( p, 0, sizeof(Aig_Man_t) ); - // perform initializations - p->nTravIds = 1; - p->fRefCount = 1; - p->fCatchExor = 0; - // allocate arrays for nodes - p->vPis = Vec_PtrAlloc( 100 ); - p->vPos = Vec_PtrAlloc( 100 ); - // prepare the internal memory manager - Aig_ManStartMemory( p ); - // create the constant node - p->pConst1 = Aig_ManFetchMemory( p ); - p->pConst1->Type = AIG_CONST1; - p->pConst1->fPhase = 1; - p->nCreated = 1; - // start the table - p->nTableSize = 10007; - p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStop( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - // make sure the nodes have clean marks - pObj = Aig_ManConst1(p); - assert( !pObj->fMarkA && !pObj->fMarkB ); - Aig_ManForEachPi( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - Aig_ManForEachPo( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - Aig_ManForEachNode( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - // print time - if ( p->time1 ) { PRT( "time1", p->time1 ); } - if ( p->time2 ) { PRT( "time2", p->time2 ); } -// Aig_TableProfile( p ); - if ( p->vChunks ) Aig_ManStopMemory( p ); - if ( p->vPis ) Vec_PtrFree( p->vPis ); - if ( p->vPos ) Vec_PtrFree( p->vPos ); - free( p->pTable ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCleanup( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pNode; - int i, nNodesOld; - assert( p->fRefCount ); - nNodesOld = Aig_ManNodeNum(p); - // collect roots of dangling nodes - vNodes = Vec_PtrAlloc( 100 ); - Aig_ManForEachNode( p, pNode, i ) - if ( Aig_ObjRefs(pNode) == 0 ) - Vec_PtrPush( vNodes, pNode ); - // recursively remove dangling nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - Aig_ObjDelete_rec( p, pNode ); - Vec_PtrFree( vNodes ); - return nNodesOld - Aig_ManNodeNum(p); -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManPrintStats( Aig_Man_t * p ) -{ - printf( "PI/PO = %d/%d. ", Aig_ManPiNum(p), Aig_ManPoNum(p) ); - printf( "A = %7d. ", Aig_ManAndNum(p) ); - printf( "X = %5d. ", Aig_ManExorNum(p) ); - printf( "Cre = %7d. ", p->nCreated ); - printf( "Del = %7d. ", p->nDeleted ); - printf( "Lev = %3d. ", Aig_ManCountLevels(p) ); - printf( "\n" ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/aigMem.c b/src/temp/aig_free/aigMem.c deleted file mode 100644 index 1be78a88..00000000 --- a/src/temp/aig_free/aigMem.c +++ /dev/null @@ -1,115 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigMem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Memory management for the AIG nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// memory management -#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes -#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStartMemory( Aig_Man_t * p ) -{ - p->vChunks = Vec_PtrAlloc( 128 ); - p->vPages = Vec_PtrAlloc( 128 ); -} - -/**Function************************************************************* - - Synopsis [Stops the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStopMemory( Aig_Man_t * p ) -{ - void * pMemory; - int i; - Vec_PtrForEachEntry( p->vChunks, pMemory, i ) - free( pMemory ); - Vec_PtrFree( p->vChunks ); - Vec_PtrFree( p->vPages ); - p->pListFree = NULL; -} - -/**Function************************************************************* - - Synopsis [Allocates additional memory for the nodes.] - - Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. - Records the pointer to the AIG manager in the -1 entry.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManAddMemory( Aig_Man_t * p ) -{ - char * pMemory; - int i, nBytes; - assert( sizeof(Aig_Obj_t) <= 64 ); - assert( p->pListFree == NULL ); -// assert( (Aig_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); - // allocate new memory page - nBytes = sizeof(Aig_Obj_t) * (1<vChunks, pMemory ); - // align memory at the 32-byte boundary - pMemory = pMemory + 64 - (((int)pMemory) & 63); - // remember the manager in the first entry - Vec_PtrPush( p->vPages, pMemory ); - // break the memory down into nodes - p->pListFree = (Aig_Obj_t *)pMemory; - for ( i = 1; i <= IVY_PAGE_MASK; i++ ) - { - *((char **)pMemory) = pMemory + sizeof(Aig_Obj_t); - pMemory += sizeof(Aig_Obj_t); - } - *((char **)pMemory) = NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/aigObj.c b/src/temp/aig_free/aigObj.c deleted file mode 100644 index 51ce6008..00000000 --- a/src/temp/aig_free/aigObj.c +++ /dev/null @@ -1,228 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigObj.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Adding/removing objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates primary input.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - pObj = Aig_ManFetchMemory( p ); - pObj->Type = AIG_PI; - Vec_PtrPush( p->vPis, pObj ); - p->nObjs[AIG_PI]++; - p->nCreated++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Creates primary output with the given driver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver ) -{ - Aig_Obj_t * pObj; - pObj = Aig_ManFetchMemory( p ); - pObj->Type = AIG_PO; - Vec_PtrPush( p->vPos, pObj ); - // add connections - pObj->pFanin0 = pDriver; - if ( p->fRefCount ) - Aig_ObjRef( Aig_Regular(pDriver) ); - else - pObj->nRefs = Aig_ObjLevel( Aig_Regular(pDriver) ); - // update node counters of the manager - p->nObjs[AIG_PO]++; - p->nCreated++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ) -{ - Aig_Obj_t * pObj; - assert( !Aig_IsComplement(pGhost) ); - assert( Aig_ObjIsNode(pGhost) ); - assert( pGhost == &p->Ghost ); - // get memory for the new object - pObj = Aig_ManFetchMemory( p ); - pObj->Type = pGhost->Type; - // add connections - Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); - // update node counters of the manager - p->nObjs[Aig_ObjType(pObj)]++; - p->nCreated++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // add the first fanin - pObj->pFanin0 = pFan0; - pObj->pFanin1 = pFan1; - // increment references of the fanins and add their fanouts - if ( p->fRefCount ) - { - if ( pFan0 != NULL ) - Aig_ObjRef( Aig_ObjFanin0(pObj) ); - if ( pFan1 != NULL ) - Aig_ObjRef( Aig_ObjFanin1(pObj) ); - } - else - pObj->nRefs = Aig_ObjLevelNew( pObj ); - // add the node to the structural hash table - Aig_TableInsert( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // remove connections - if ( pObj->pFanin0 != NULL ) - Aig_ObjDeref(Aig_ObjFanin0(pObj)); - if ( pObj->pFanin1 != NULL ) - Aig_ObjDeref(Aig_ObjFanin1(pObj)); - // remove the node from the structural hash table - Aig_TableDelete( p, pObj ); - // add the first fanin - pObj->pFanin0 = NULL; - pObj->pFanin1 = NULL; -} - -/**Function************************************************************* - - Synopsis [Deletes the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsTerm(pObj) ); - assert( Aig_ObjRefs(pObj) == 0 ); - // update node counters of the manager - p->nObjs[pObj->Type]--; - p->nDeleted++; - // remove connections - Aig_ObjDisconnect( p, pObj ); - // remove PIs/POs from the arrays - if ( Aig_ObjIsPi(pObj) ) - Vec_PtrRemove( p->vPis, pObj ); - // free the node - Aig_ManRecycleMemory( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Deletes the MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); - Aig_ObjDelete( p, pObj ); - if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 ) - Aig_ObjDelete_rec( p, pFanin0 ); - if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 ) - Aig_ObjDelete_rec( p, pFanin1 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/aigOper.c b/src/temp/aig_free/aigOper.c deleted file mode 100644 index 9985093e..00000000 --- a/src/temp/aig_free/aigOper.c +++ /dev/null @@ -1,373 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigOper.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// procedure to detect an EXOR gate -static inline int Aig_ObjIsExorType( Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) -{ - if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) - return 0; - p0 = Aig_Regular(p0); - p1 = Aig_Regular(p1); - if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) - return 0; - if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) - return 0; - if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Aig_ObjChild0(p0); - *ppFan1 = Aig_ObjChild1(p0); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns i-th elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ) -{ - int v; - for ( v = Aig_ManPiNum(p); v <= i; v++ ) - Aig_ObjCreatePi( p ); - assert( i < Vec_PtrSize(p->vPis) ); - return Aig_ManPi( p, i ); -} - -/**Function************************************************************* - - Synopsis [Perform one operation.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) -{ - if ( Type == AIG_AND ) - return Aig_And( p, p0, p1 ); - if ( Type == AIG_EXOR ) - return Aig_Exor( p, p0, p1 ); - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ - Aig_Obj_t * pGhost, * pResult; -// Aig_Obj_t * pFan0, * pFan1; - // check trivial cases - if ( p0 == p1 ) - return p0; - if ( p0 == Aig_Not(p1) ) - return Aig_Not(p->pConst1); - if ( Aig_Regular(p0) == p->pConst1 ) - return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1); - if ( Aig_Regular(p1) == p->pConst1 ) - return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1); - // check if it can be an EXOR gate -// if ( Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) -// return Aig_Exor( p, pFan0, pFan1 ); - // check the table - pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_AND ); - if ( pResult = Aig_TableLookup( p, pGhost ) ) - return pResult; - return Aig_ObjCreate( p, pGhost ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ -/* - Aig_Obj_t * pGhost, * pResult; - // check trivial cases - if ( p0 == p1 ) - return Aig_Not(p->pConst1); - if ( p0 == Aig_Not(p1) ) - return p->pConst1; - if ( Aig_Regular(p0) == p->pConst1 ) - return Aig_NotCond( p1, p0 == p->pConst1 ); - if ( Aig_Regular(p1) == p->pConst1 ) - return Aig_NotCond( p0, p1 == p->pConst1 ); - // check the table - pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_EXOR ); - if ( pResult = Aig_TableLookup( p, pGhost ) ) - return pResult; - return Aig_ObjCreate( p, pGhost ); -*/ - return Aig_Or( p, Aig_And(p, p0, Aig_Not(p1)), Aig_And(p, Aig_Not(p0), p1) ); -} - -/**Function************************************************************* - - Synopsis [Implements Boolean OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ - return Aig_Not( Aig_And( p, Aig_Not(p0), Aig_Not(p1) ) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ) -{ -/* - Aig_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; - int Count0, Count1; - // consider trivial cases - if ( p0 == Aig_Not(p1) ) - return Aig_Exor( p, pC, p0 ); - // other cases can be added - // implement the first MUX (F = C * x1 + C' * x0) - - // check for constants here!!! - - pTempA1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, p1, AIG_AND) ); - pTempA2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), p0, AIG_AND) ); - if ( pTempA1 && pTempA2 ) - { - pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempA1), Aig_Not(pTempA2), AIG_AND) ); - if ( pTemp ) return Aig_Not(pTemp); - } - Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); - // implement the second MUX (F' = C * x1' + C' * x0') - pTempB1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, Aig_Not(p1), AIG_AND) ); - pTempB2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), Aig_Not(p0), AIG_AND) ); - if ( pTempB1 && pTempB2 ) - { - pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempB1), Aig_Not(pTempB2), AIG_AND) ); - if ( pTemp ) return pTemp; - } - Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); - // compare and decide which one to implement - if ( Count0 >= Count1 ) - { - pTempA1 = pTempA1? pTempA1 : Aig_And(p, pC, p1); - pTempA2 = pTempA2? pTempA2 : Aig_And(p, Aig_Not(pC), p0); - return Aig_Or( p, pTempA1, pTempA2 ); - } - pTempB1 = pTempB1? pTempB1 : Aig_And(p, pC, Aig_Not(p1)); - pTempB2 = pTempB2? pTempB2 : Aig_And(p, Aig_Not(pC), Aig_Not(p0)); - return Aig_Not( Aig_Or( p, pTempB1, pTempB2 ) ); -*/ - return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ) -{ - return Aig_Or( p, Aig_Or(p, Aig_And(p, pA, pB), Aig_And(p, pA, pC)), Aig_And(p, pB, pC) ); -} - -/**Function************************************************************* - - Synopsis [Constructs the well-balanced tree of gates.] - - Description [Disregards levels and possible logic sharing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Multi_rec( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Aig_Type_t Type ) -{ - Aig_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Aig_Multi_rec( p, ppObjs, nObjs/2, Type ); - pObj2 = Aig_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); - return Aig_Oper( p, pObj1, pObj2, Type ); -} - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type ) -{ - assert( Type == AIG_AND || Type == AIG_EXOR ); - assert( nArgs > 0 ); - return Aig_Multi_rec( p, pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ) -{ - int i; - assert( vPairs->nSize > 0 ); - assert( vPairs->nSize % 2 == 0 ); - // go through the cubes of the node's SOP - for ( i = 0; i < vPairs->nSize; i += 2 ) - vPairs->pArray[i/2] = Aig_Not( Aig_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); - vPairs->nSize = vPairs->nSize/2; - return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_AND ) ); -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst1( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_And( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst0( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_Or( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst0( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_Exor( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/aigTable.c b/src/temp/aig_free/aigTable.c deleted file mode 100644 index 338faa45..00000000 --- a/src/temp/aig_free/aigTable.c +++ /dev/null @@ -1,266 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Structural hashing table.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006. ] - - Revision [$Id: aigTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing the node -static unsigned long Aig_Hash( Aig_Obj_t * pObj, int TableSize ) -{ - unsigned long Key = Aig_ObjIsExor(pObj) * 1699; - Key ^= (long)Aig_ObjFanin0(pObj) * 7937; - Key ^= (long)Aig_ObjFanin1(pObj) * 2971; - Key ^= Aig_ObjFaninC0(pObj) * 911; - Key ^= Aig_ObjFaninC1(pObj) * 353; - return Key % TableSize; -} - -// returns the place where this node is stored (or should be stored) -static Aig_Obj_t ** Aig_TableFind( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - int i; - assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) ); - assert( Aig_ObjChild0(pObj) < Aig_ObjChild1(pObj) ); - for ( i = Aig_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) - if ( p->pTable[i] == pObj ) - break; - return p->pTable + i; -} - -static void Aig_TableResize( Aig_Man_t * p ); -static unsigned int Cudd_PrimeAig( unsigned int p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks if node with the given attributes is in the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ) -{ - int i; - assert( !Aig_IsComplement(pGhost) ); - assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) ); - assert( Aig_ObjChild0(pGhost) < Aig_ObjChild1(pGhost) ); - if ( p->fRefCount && (!Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost))) ) - return NULL; - for ( i = Aig_Hash(pGhost, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) - { - if ( Aig_ObjChild0(p->pTable[i]) == Aig_ObjChild0(pGhost) && - Aig_ObjChild1(p->pTable[i]) == Aig_ObjChild1(pGhost) && - Aig_ObjType(p->pTable[i]) == Aig_ObjType(pGhost) ) - return p->pTable[i]; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Adds the new node to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t ** ppPlace; - assert( !Aig_IsComplement(pObj) ); - assert( Aig_TableLookup(p, pObj) == NULL ); - if ( p->nTableSize < 2 * Aig_ManNodeNum(p) ) - Aig_TableResize( p ); - ppPlace = Aig_TableFind( p, pObj ); - assert( *ppPlace == NULL ); - *ppPlace = pObj; -} - -/**Function************************************************************* - - Synopsis [Deletes the node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pEntry, ** ppPlace; - int i; - assert( !Aig_IsComplement(pObj) ); - ppPlace = Aig_TableFind( p, pObj ); - assert( *ppPlace == pObj ); // node should be in the table - *ppPlace = NULL; - // rehash the adjacent entries - i = ppPlace - p->pTable; - for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) - { - pEntry = p->pTable[i]; - p->pTable[i] = 0; - Aig_TableInsert( p, pEntry ); - } -} - -/**Function************************************************************* - - Synopsis [Count the number of nodes in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_TableCountEntries( Aig_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - Counter += (p->pTable[i] != NULL); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [Typically this procedure should not be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableResize( Aig_Man_t * p ) -{ - Aig_Obj_t ** pTableOld, ** ppPlace; - int nTableSizeOld, Counter, nEntries, e, clk; -clk = clock(); - // save the old table - pTableOld = p->pTable; - nTableSizeOld = p->nTableSize; - // get the new table - p->nTableSize = Cudd_PrimeAig( 5 * Aig_ManNodeNum(p) ); - p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); - // rehash the entries from the old table - Counter = 0; - for ( e = 0; e < nTableSizeOld; e++ ) - { - if ( pTableOld[e] == 0 ) - continue; - Counter++; - // get the place where this entry goes in the table table - ppPlace = Aig_TableFind( p, pTableOld[e] ); - assert( *ppPlace == NULL ); // should not be in the table - *ppPlace = pTableOld[e]; - } - nEntries = Aig_ManNodeNum(p); -// assert( Counter == nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( pTableOld ); -} - -/**Function******************************************************************** - - Synopsis [Profiles the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Aig_TableProfile( Aig_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - { - if ( p->pTable[i] ) - Counter++; - else if ( Counter ) - { - printf( "%d ", Counter ); - Counter = 0; - } - } -} - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Cudd_PrimeAig( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/aigUtil.c b/src/temp/aig_free/aigUtil.c deleted file mode 100644 index 623de32b..00000000 --- a/src/temp/aig_free/aigUtil.c +++ /dev/null @@ -1,513 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Various procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: aigUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -int Extra_Base10Log( unsigned Num ) -{ - int Res; - assert( Num >= 0 ); - if ( Num == 0 ) return 0; - if ( Num == 1 ) return 1; - for ( Res = 0, Num--; Num; Num /= 10, Res++ ); - return Res; -} /* end of Extra_Base2Log */ - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Increments the current traversal ID of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManIncrementTravId( Aig_Man_t * p ) -{ - if ( p->nTravIds >= (1<<30)-1 ) - Aig_ManCleanData( p ); - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Sets the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCleanData( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - p->nTravIds = 1; - Aig_ManConst1(p)->pData = NULL; - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = NULL; - Aig_ManForEachPo( p, pObj, i ) - pObj->pData = NULL; - Aig_ManForEachNode( p, pObj, i ) - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCollectMulti_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - if ( pRoot != pObj && (Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || Aig_ObjType(pRoot) != Aig_ObjType(pObj)) ) - { - Vec_PtrPushUnique(vSuper, pObj); - return; - } - Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild0(pObj), vSuper ); - Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild1(pObj), vSuper ); -} - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCollectMulti( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper ) -{ - assert( !Aig_IsComplement(pRoot) ); - Vec_PtrClear( vSuper ); - Aig_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjIsMuxType( Aig_Obj_t * pNode ) -{ - Aig_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Aig_IsComplement(pNode) ); - // if the node is not AND, this is not MUX - if ( !Aig_ObjIsAnd(pNode) ) - return 0; - // if the children are not complemented, this is not MUX - if ( !Aig_ObjFaninC0(pNode) || !Aig_ObjFaninC1(pNode) ) - return 0; - // get children - pNode0 = Aig_ObjFanin0(pNode); - pNode1 = Aig_ObjFanin1(pNode); - // if the children are not ANDs, this is not MUX - if ( !Aig_ObjIsAnd(pNode0) || !Aig_ObjIsAnd(pNode1) ) - return 0; - // otherwise the node is MUX iff it has a pair of equal grandchildren - return (Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1))) || - (Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1))) || - (Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1))) || - (Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1))); -} - - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are inputs of the EXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) -{ - Aig_Obj_t * p0, * p1; - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) ) - return 0; - if ( Aig_ObjIsExor(pObj) ) - { - *ppFan0 = Aig_ObjChild0(pObj); - *ppFan1 = Aig_ObjChild1(pObj); - return 1; - } - assert( Aig_ObjIsAnd(pObj) ); - p0 = Aig_ObjChild0(pObj); - p1 = Aig_ObjChild1(pObj); - if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) - return 0; - p0 = Aig_Regular(p0); - p1 = Aig_Regular(p1); - if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) - return 0; - if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) - return 0; - if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Aig_ObjChild0(p0); - *ppFan1 = Aig_ObjChild1(p0); - return 1; -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pNode, Aig_Obj_t ** ppNodeT, Aig_Obj_t ** ppNodeE ) -{ - Aig_Obj_t * pNode0, * pNode1; - assert( !Aig_IsComplement(pNode) ); - assert( Aig_ObjIsMuxType(pNode) ); - // get children - pNode0 = Aig_ObjFanin0(pNode); - pNode1 = Aig_ObjFanin1(pNode); - - // find the control variable - if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Aig_ObjFaninC1(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - return Aig_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - return Aig_ObjChild1(pNode0);//pNode1->p2; - } - } - else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Aig_ObjFaninC0(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - return Aig_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - return Aig_ObjChild0(pNode0);//pNode1->p1; - } - } - else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Aig_ObjFaninC0(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - return Aig_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - return Aig_ObjChild0(pNode0);//pNode1->p1; - } - } - else if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Aig_ObjFaninC1(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - return Aig_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - return Aig_ObjChild1(pNode0);//pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - - -/**Function************************************************************* - - Synopsis [Prints Verilog formula for the AIG rooted at this node.] - - Description [The formula is in terms of PIs, which should have - their names assigned in pObj->pData fields.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) -{ - Vec_Ptr_t * vSuper; - Aig_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; - int fCompl, i; - // store the complemented attribute - fCompl = Aig_IsComplement(pObj); - pObj = Aig_Regular(pObj); - // constant case - if ( Aig_ObjIsConst1(pObj) ) - { - fprintf( pFile, "%d", !fCompl ); - return; - } - // PI case - if ( Aig_ObjIsPi(pObj) ) - { - fprintf( pFile, "%s%s", fCompl? "~" : "", pObj->pData ); - return; - } - // EXOR case - if ( Aig_ObjIsExor(pObj) ) - { - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry( vLevels, Level ); - Aig_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " ^ " ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; - } - // MUX case - if ( Aig_ObjIsMuxType(pObj) ) - { - if ( Aig_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) - { - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); - fprintf( pFile, " ^ " ); - Aig_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); - fprintf( pFile, "%s", (Level==0? "" : ")") ); - } - else - { - pFaninC = Aig_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Aig_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); - fprintf( pFile, " ? " ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin1, fCompl), vLevels, Level+1 ); - fprintf( pFile, " : " ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); - fprintf( pFile, "%s", (Level==0? "" : ")") ); - } - return; - } - // AND case - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry(vLevels, Level); - Aig_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " %s ", fCompl? "|" : "&" ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; -} - - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ) -{ - assert( !Aig_IsComplement(pObj) ); - printf( "Node %p : ", pObj ); - if ( Aig_ObjIsConst1(pObj) ) - printf( "constant 1" ); - else if ( Aig_ObjIsPi(pObj) ) - printf( "PI" ); - else - printf( "AND( %p%s, %p%s )", - Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " "), - Aig_ObjFanin1(pObj), (Aig_ObjFaninC1(pObj)? "\'" : " ") ); - printf( " (refs = %3d)", Aig_ObjRefs(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - printf( "PIs: " ); - Aig_ManForEachPi( p, pObj, i ) - printf( " %p", pObj ); - printf( "\n" ); - vNodes = Aig_ManDfs( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the AIG into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj, * pConst1 = NULL; - int i, nDigits, Counter = 0; - if ( Aig_ManPoNum(p) == 0 ) - { - printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); - return; - } - // collect nodes in the DFS order - vNodes = Aig_ManDfs( p ); - // assign IDs to objects - Aig_ManConst1(p)->pData = (void *)Counter++; - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = (void *)Counter++; - Aig_ManForEachPo( p, pObj, i ) - pObj->pData = (void *)Counter++; - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pData = (void *)Counter++; - nDigits = Extra_Base10Log( Counter ); - // write the file - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif() in ABC\n" ); - fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); - fprintf( pFile, ".model test\n" ); - // write PIs - fprintf( pFile, ".inputs" ); - Aig_ManForEachPi( p, pObj, i ) - fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); - fprintf( pFile, "\n" ); - // write POs - fprintf( pFile, ".outputs" ); - Aig_ManForEachPo( p, pObj, i ) - fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); - fprintf( pFile, "\n" ); - // write nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", - nDigits, (int)Aig_ObjFanin0(pObj)->pData, - nDigits, (int)Aig_ObjFanin1(pObj)->pData, - nDigits, (int)pObj->pData ); - fprintf( pFile, "%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) ); - } - // write POs - Aig_ManForEachPo( p, pObj, i ) - { - fprintf( pFile, ".names n%0*d n%0*d\n", - nDigits, (int)Aig_ObjFanin0(pObj)->pData, - nDigits, (int)pObj->pData ); - fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) ); - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) - pConst1 = Aig_ManConst1(p); - } - if ( pConst1 ) - fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)pConst1->pData ); - fprintf( pFile, ".end\n\n" ); - fclose( pFile ); - Vec_PtrFree( vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/cudd2.c b/src/temp/aig_free/cudd2.c deleted file mode 100644 index f95d3fd0..00000000 --- a/src/temp/aig_free/cudd2.c +++ /dev/null @@ -1,375 +0,0 @@ -/**CFile**************************************************************** - - FileName [cudd2.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Recording AIGs for the BDD operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 3, 2006.] - - Revision [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" -#include "st.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Aig_CuddMan_t_ Aig_CuddMan_t; -struct Aig_CuddMan_t_ -{ - Aig_Man_t * pAig; // internal AIG package - st_table * pTable; // hash table mapping BDD nodes into AIG nodes -}; - -// static Cudd AIG manager used in this experiment -static Aig_CuddMan_t * s_pCuddMan = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start AIG recording.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ) -{ - int v; - assert( s_pCuddMan == NULL ); - s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 ); - s_pCuddMan->pAig = Aig_ManStart(); - s_pCuddMan->pTable = st_init_table( st_ptrcmp, st_ptrhash ); - for ( v = 0; v < (int)numVars; v++ ) - Aig_ObjCreatePi( s_pCuddMan->pAig ); -} - -/**Function************************************************************* - - Synopsis [Stops AIG recording.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_Quit( void * pCudd ) -{ - assert( s_pCuddMan != NULL ); - Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif" ); - Aig_ManStop( s_pCuddMan->pAig ); - st_free_table( s_pCuddMan->pTable ); - free( s_pCuddMan ); - s_pCuddMan = NULL; -} - -/**Function************************************************************* - - Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Aig_Obj_t * Cudd2_GetArg( void * pArg ) -{ - Aig_Obj_t * pNode; - assert( s_pCuddMan != NULL ); - if ( !st_lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) ) - { - printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" ); - return NULL; - } - return Aig_NotCond( pNode, Aig_IsComplement(pArg) ); -} - -/**Function************************************************************* - - Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult ) -{ - assert( s_pCuddMan != NULL ); - if ( st_is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) ) - return; - pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) ); - st_insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode ); -} - - -/**Function************************************************************* - - Synopsis [Creates equivalent of BDD.ONE and BDD.ReadZero.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -void Cudd2_bddOne( void * pCudd, void * pResult ) -{ - Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult ); -} - - -/**Function************************************************************* - - Synopsis [Adds elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult ) -{ - int v; - assert( s_pCuddMan != NULL ); - for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ ) - Aig_ObjCreatePi( s_pCuddMan->pAig ); - Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode2 = Cudd2_GetArg( pArg2 ); - pNode = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Should be called after each containment check.] - - Description [Result should be 1 if Cudd2_bddLeq returned 1.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) ); - Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); -} - -/**Function************************************************************* - - Synopsis [Should be called after each equality check.] - - Description [Result should be 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); - Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); -} - -/**Function************************************************************* - - Synopsis [Should be called each time a BDD node is dereferenced.] - - Description [Removes mapping of a BDD node into an AIG node when the BDD - node is dereferenced.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_RecursiveDeref( void * pCudd, void * pArg ) -{ - assert( s_pCuddMan != NULL ); - assert( st_is_member(s_pCuddMan->pTable, (char *)Aig_Regular(pArg)) ); - st_delete( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), NULL ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/aig_free/cudd2.h b/src/temp/aig_free/cudd2.h deleted file mode 100644 index c80ec5ed..00000000 --- a/src/temp/aig_free/cudd2.h +++ /dev/null @@ -1,83 +0,0 @@ -/**CFile**************************************************************** - - FileName [cudd2.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 3, 2006.] - - Revision [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CUDD2_H__ -#define __CUDD2_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -// HA: Added for printing messages -#ifndef MSG -#define MSG(msg) (printf("%s = \n",(msg))); -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - - extern void Cudd2_Init ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ); - extern void Cudd2_Quit ( void * pCudd ); - extern void Cudd2_bddOne ( void * pCudd, void * pResult ); - - extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult ); - extern void Cudd2_bddAnd ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); - extern void Cudd2_bddOr ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); - extern void Cudd2_bddNand ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); - extern void Cudd2_bddNor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); - extern void Cudd2_bddXor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); - extern void Cudd2_bddXnor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); - extern void Cudd2_bddIte ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ); - extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ); - extern void Cudd2_bddLeq ( void * pCudd, void * pArg0, void * pArg1, int Result ); - extern void Cudd2_bddEqual ( void * pCudd, void * pArg0, void * pArg1, int Result ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/aig_free/st.c b/src/temp/aig_free/st.c deleted file mode 100644 index 5024e08d..00000000 --- a/src/temp/aig_free/st.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/st/st.c,v - * serdar - * 1.1 - * 1993/07/29 01:00:13 - * - */ -#include - -#include -//#include "extra.h" -#include "st.h" - -#ifndef ABS -# define ABS(a) ((a) < 0 ? -(a) : (a)) -#endif - -#ifndef ALLOC -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef FREE -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#endif - -#ifndef REALLOC -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) -#endif - -#define ST_NUMCMP(x,y) ((x) != (y)) -#define ST_NUMHASH(x,size) (ABS((long)x)%(size)) -#define ST_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) -#define EQUAL(func, x, y) \ - ((((func) == st_numcmp) || ((func) == st_ptrcmp)) ?\ - (ST_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0)) - - -#define do_hash(key, table)\ - ((table->hash == st_ptrhash) ? ST_PTRHASH((key),(table)->num_bins) :\ - (table->hash == st_numhash) ? ST_NUMHASH((key), (table)->num_bins) :\ - (*table->hash)((key), (table)->num_bins)) - -static int rehash(); -int st_numhash(), st_ptrhash(), st_numcmp(), st_ptrcmp(); - -st_table * -st_init_table_with_params(compare, hash, size, density, grow_factor, - reorder_flag) -int (*compare)(); -int (*hash)(); -int size; -int density; -double grow_factor; -int reorder_flag; -{ - int i; - st_table *new; - - new = ALLOC(st_table, 1); - if (new == NULL) { - return NULL; - } - new->compare = compare; - new->hash = hash; - new->num_entries = 0; - new->max_density = density; - new->grow_factor = grow_factor; - new->reorder_flag = reorder_flag; - if (size <= 0) { - size = 1; - } - new->num_bins = size; - new->bins = ALLOC(st_table_entry *, size); - if (new->bins == NULL) { - FREE(new); - return NULL; - } - for(i = 0; i < size; i++) { - new->bins[i] = 0; - } - return new; -} - -st_table * -st_init_table(compare, hash) -int (*compare)(); -int (*hash)(); -{ - return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE, - ST_DEFAULT_MAX_DENSITY, - ST_DEFAULT_GROW_FACTOR, - ST_DEFAULT_REORDER_FLAG); -} - -void -st_free_table(table) -st_table *table; -{ - register st_table_entry *ptr, *next; - int i; - - for(i = 0; i < table->num_bins ; i++) { - ptr = table->bins[i]; - while (ptr != NULL) { - next = ptr->next; - FREE(ptr); - ptr = next; - } - } - FREE(table->bins); - FREE(table); -} - -#define PTR_NOT_EQUAL(table, ptr, user_key)\ -(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) - -#define FIND_ENTRY(table, hash_val, key, ptr, last) \ - (last) = &(table)->bins[hash_val];\ - (ptr) = *(last);\ - while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ - (last) = &(ptr)->next; (ptr) = *(last);\ - }\ - if ((ptr) != NULL && (table)->reorder_flag) {\ - *(last) = (ptr)->next;\ - (ptr)->next = (table)->bins[hash_val];\ - (table)->bins[hash_val] = (ptr);\ - } - -int -st_lookup(table, key, value) -st_table *table; -register char *key; -char **value; -{ - int hash_val; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } else { - if (value != NULL) { - *value = ptr->record; - } - return 1; - } -} - -int -st_lookup_int(table, key, value) -st_table *table; -register char *key; -int *value; -{ - int hash_val; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } else { - if (value != 0) { - *value = (long) ptr->record; - } - return 1; - } -} - -/* This macro does not check if memory allocation fails. Use at you own risk */ -#define ADD_DIRECT(table, key, value, hash_val, new)\ -{\ - if (table->num_entries/table->num_bins >= table->max_density) {\ - rehash(table);\ - hash_val = do_hash(key,table);\ - }\ - \ - new = ALLOC(st_table_entry, 1);\ - \ - new->key = key;\ - new->record = value;\ - new->next = table->bins[hash_val];\ - table->bins[hash_val] = new;\ - table->num_entries++;\ -} - -int -st_insert(table, key, value) -register st_table *table; -register char *key; -char *value; -{ - int hash_val; - st_table_entry *new; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - if (table->num_entries/table->num_bins >= table->max_density) { - if (rehash(table) == ST_OUT_OF_MEM) { - return ST_OUT_OF_MEM; - } - hash_val = do_hash(key, table); - } - new = ALLOC(st_table_entry, 1); - if (new == NULL) { - return ST_OUT_OF_MEM; - } - new->key = key; - new->record = value; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - return 0; - } else { - ptr->record = value; - return 1; - } -} - -int -st_add_direct(table, key, value) -st_table *table; -char *key; -char *value; -{ - int hash_val; - st_table_entry *new; - - hash_val = do_hash(key, table); - if (table->num_entries / table->num_bins >= table->max_density) { - if (rehash(table) == ST_OUT_OF_MEM) { - return ST_OUT_OF_MEM; - } - } - hash_val = do_hash(key, table); - new = ALLOC(st_table_entry, 1); - if (new == NULL) { - return ST_OUT_OF_MEM; - } - new->key = key; - new->record = value; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - return 1; -} - -int -st_find_or_add(table, key, slot) -st_table *table; -char *key; -char ***slot; -{ - int hash_val; - st_table_entry *new, *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - if (table->num_entries / table->num_bins >= table->max_density) { - if (rehash(table) == ST_OUT_OF_MEM) { - return ST_OUT_OF_MEM; - } - hash_val = do_hash(key, table); - } - new = ALLOC(st_table_entry, 1); - if (new == NULL) { - return ST_OUT_OF_MEM; - } - new->key = key; - new->record = (char *) 0; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - if (slot != NULL) *slot = &new->record; - return 0; - } else { - if (slot != NULL) *slot = &ptr->record; - return 1; - } -} - -int -st_find(table, key, slot) -st_table *table; -char *key; -char ***slot; -{ - int hash_val; - st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } else { - if (slot != NULL) { - *slot = &ptr->record; - } - return 1; - } -} - -static int -rehash(table) -register st_table *table; -{ - register st_table_entry *ptr, *next, **old_bins; - int i, old_num_bins, hash_val, old_num_entries; - - /* save old values */ - old_bins = table->bins; - old_num_bins = table->num_bins; - old_num_entries = table->num_entries; - - /* rehash */ - table->num_bins = (int)(table->grow_factor * old_num_bins); - if (table->num_bins % 2 == 0) { - table->num_bins += 1; - } - table->num_entries = 0; - table->bins = ALLOC(st_table_entry *, table->num_bins); - if (table->bins == NULL) { - table->bins = old_bins; - table->num_bins = old_num_bins; - table->num_entries = old_num_entries; - return ST_OUT_OF_MEM; - } - /* initialize */ - for (i = 0; i < table->num_bins; i++) { - table->bins[i] = 0; - } - - /* copy data over */ - for (i = 0; i < old_num_bins; i++) { - ptr = old_bins[i]; - while (ptr != NULL) { - next = ptr->next; - hash_val = do_hash(ptr->key, table); - ptr->next = table->bins[hash_val]; - table->bins[hash_val] = ptr; - table->num_entries++; - ptr = next; - } - } - FREE(old_bins); - - return 1; -} - -st_table * -st_copy(old_table) -st_table *old_table; -{ - st_table *new_table; - st_table_entry *ptr, *newptr, *next, *new; - int i, j, num_bins = old_table->num_bins; - - new_table = ALLOC(st_table, 1); - if (new_table == NULL) { - return NULL; - } - - *new_table = *old_table; - new_table->bins = ALLOC(st_table_entry *, num_bins); - if (new_table->bins == NULL) { - FREE(new_table); - return NULL; - } - for(i = 0; i < num_bins ; i++) { - new_table->bins[i] = NULL; - ptr = old_table->bins[i]; - while (ptr != NULL) { - new = ALLOC(st_table_entry, 1); - if (new == NULL) { - for (j = 0; j <= i; j++) { - newptr = new_table->bins[j]; - while (newptr != NULL) { - next = newptr->next; - FREE(newptr); - newptr = next; - } - } - FREE(new_table->bins); - FREE(new_table); - return NULL; - } - *new = *ptr; - new->next = new_table->bins[i]; - new_table->bins[i] = new; - ptr = ptr->next; - } - } - return new_table; -} - -int -st_delete(table, keyp, value) -register st_table *table; -register char **keyp; -char **value; -{ - int hash_val; - char *key = *keyp; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr ,last); - - if (ptr == NULL) { - return 0; - } - - *last = ptr->next; - if (value != NULL) *value = ptr->record; - *keyp = ptr->key; - FREE(ptr); - table->num_entries--; - return 1; -} - -int -st_delete_int(table, keyp, value) -register st_table *table; -register long *keyp; -char **value; -{ - int hash_val; - char *key = (char *) *keyp; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr ,last); - - if (ptr == NULL) { - return 0; - } - - *last = ptr->next; - if (value != NULL) *value = ptr->record; - *keyp = (long) ptr->key; - FREE(ptr); - table->num_entries--; - return 1; -} - -int -st_foreach(table, func, arg) -st_table *table; -enum st_retval (*func)(); -char *arg; -{ - st_table_entry *ptr, **last; - enum st_retval retval; - int i; - - for(i = 0; i < table->num_bins; i++) { - last = &table->bins[i]; ptr = *last; - while (ptr != NULL) { - retval = (*func)(ptr->key, ptr->record, arg); - switch (retval) { - case ST_CONTINUE: - last = &ptr->next; ptr = *last; - break; - case ST_STOP: - return 0; - case ST_DELETE: - *last = ptr->next; - table->num_entries--; /* cstevens@ic */ - FREE(ptr); - ptr = *last; - } - } - } - return 1; -} - -int -st_strhash(string, modulus) -register char *string; -int modulus; -{ - register int val = 0; - register int c; - - while ((c = *string++) != '\0') { - val = val*997 + c; - } - - return ((val < 0) ? -val : val)%modulus; -} - -int -st_numhash(x, size) -char *x; -int size; -{ - return ST_NUMHASH(x, size); -} - -int -st_ptrhash(x, size) -char *x; -int size; -{ - return ST_PTRHASH(x, size); -} - -int -st_numcmp(x, y) -char *x; -char *y; -{ - return ST_NUMCMP(x, y); -} - -int -st_ptrcmp(x, y) -char *x; -char *y; -{ - return ST_NUMCMP(x, y); -} - -st_generator * -st_init_gen(table) -st_table *table; -{ - st_generator *gen; - - gen = ALLOC(st_generator, 1); - if (gen == NULL) { - return NULL; - } - gen->table = table; - gen->entry = NULL; - gen->index = 0; - return gen; -} - - -int -st_gen(gen, key_p, value_p) -st_generator *gen; -char **key_p; -char **value_p; -{ - register int i; - - if (gen->entry == NULL) { - /* try to find next entry */ - for(i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { - gen->index = i+1; - gen->entry = gen->table->bins[i]; - break; - } - } - if (gen->entry == NULL) { - return 0; /* that's all folks ! */ - } - } - *key_p = gen->entry->key; - if (value_p != 0) { - *value_p = gen->entry->record; - } - gen->entry = gen->entry->next; - return 1; -} - - -int -st_gen_int(gen, key_p, value_p) -st_generator *gen; -char **key_p; -long *value_p; -{ - register int i; - - if (gen->entry == NULL) { - /* try to find next entry */ - for(i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { - gen->index = i+1; - gen->entry = gen->table->bins[i]; - break; - } - } - if (gen->entry == NULL) { - return 0; /* that's all folks ! */ - } - } - *key_p = gen->entry->key; - if (value_p != 0) { - *value_p = (long) gen->entry->record; - } - gen->entry = gen->entry->next; - return 1; -} - - -void -st_free_gen(gen) -st_generator *gen; -{ - FREE(gen); -} diff --git a/src/temp/aig_free/st.h b/src/temp/aig_free/st.h deleted file mode 100644 index b15f3c83..00000000 --- a/src/temp/aig_free/st.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/st/st.h,v - * serdar - * 1.1 - * 1993/07/29 01:00:21 - * - */ -/* LINTLIBRARY */ - -/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ - -#ifndef ST_INCLUDED -#define ST_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct st_table_entry st_table_entry; -struct st_table_entry { - char *key; - char *record; - st_table_entry *next; -}; - -typedef struct st_table st_table; -struct st_table { - int (*compare)(); - int (*hash)(); - int num_bins; - int num_entries; - int max_density; - int reorder_flag; - double grow_factor; - st_table_entry **bins; -}; - -typedef struct st_generator st_generator; -struct st_generator { - st_table *table; - st_table_entry *entry; - int index; -}; - -#define st_is_member(table,key) st_lookup(table,key,(char **) 0) -#define st_count(table) ((table)->num_entries) - -enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE}; - -typedef enum st_retval (*ST_PFSR)(); -typedef int (*ST_PFI)(); - -extern st_table *st_init_table_with_params (ST_PFI, ST_PFI, int, int, double, int); -extern st_table *st_init_table (ST_PFI, ST_PFI); -extern void st_free_table (st_table *); -extern int st_lookup (st_table *, char *, char **); -extern int st_lookup_int (st_table *, char *, int *); -extern int st_insert (st_table *, char *, char *); -extern int st_add_direct (st_table *, char *, char *); -extern int st_find_or_add (st_table *, char *, char ***); -extern int st_find (st_table *, char *, char ***); -extern st_table *st_copy (st_table *); -extern int st_delete (st_table *, char **, char **); -extern int st_delete_int (st_table *, long *, char **); -extern int st_foreach (st_table *, ST_PFSR, char *); -extern int st_strhash (char *, int); -extern int st_numhash (char *, int); -extern int st_ptrhash (char *, int); -extern int st_numcmp (char *, char *); -extern int st_ptrcmp (char *, char *); -extern st_generator *st_init_gen (st_table *); -extern int st_gen (st_generator *, char **, char **); -extern int st_gen_int (st_generator *, char **, long *); -extern void st_free_gen (st_generator *); - - -#define ST_DEFAULT_MAX_DENSITY 5 -#define ST_DEFAULT_INIT_TABLE_SIZE 11 -#define ST_DEFAULT_GROW_FACTOR 2.0 -#define ST_DEFAULT_REORDER_FLAG 0 - -#define st_foreach_item(table, gen, key, value) \ - for(gen=st_init_gen(table); st_gen(gen,key,value) || (st_free_gen(gen),0);) - -#define st_foreach_item_int(table, gen, key, value) \ - for(gen=st_init_gen(table); st_gen_int(gen,key,value) || (st_free_gen(gen),0);) - -#define ST_OUT_OF_MEM -10000 - -#ifdef __cplusplus -} -#endif - -#endif /* ST_INCLUDED */ diff --git a/src/temp/aig_free/subdir.mk b/src/temp/aig_free/subdir.mk deleted file mode 100644 index 1867f777..00000000 --- a/src/temp/aig_free/subdir.mk +++ /dev/null @@ -1,87 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -INCPATHS = -I$(ROOT)/aig-alan - -# Add inputs and outputs from these tool invocations to the build variables -PURE_C_SRCS += \ -${addprefix $(ROOT)/aig-alan/, \ -aigBalance.c \ -aigCheck.c \ -aigDfs.c \ -aigMan.c \ -aigMem.c \ -aigObj.c \ -aigOper.c \ -aigTable.c \ -aigUtil.c \ -cudd2.c \ -st.c \ -} - -C_SRCS += $(PURE_C_SRCS) - - -PURE_C_OBJS += \ -${addprefix $(ROOT)/obj/aig-alan/, \ -aigBalance.o \ -aigCheck.o \ -aigDfs.o \ -aigMan.o \ -aigMem.o \ -aigObj.o \ -aigOper.o \ -aigTable.o \ -aigUtil.o \ -cudd2.o \ -st.o \ -} - -OBJS += $(PURE_C_OBJS) - -PURE_C_DEPS += \ -${addprefix $(ROOT)/obj/aig-alan, \ -aigBalance.d \ -aigCheck.d \ -aigDfs.d \ -aigMan.d \ -aigMem.d \ -aigObj.d \ -aigOper.d \ -aigTable.d \ -aigUtil.d \ -cudd2.d \ -st.d \ -} - -DEPS += $(PURE_C_DEPS) - - -OCAML_OBJS += - - -DEPEND_SRCS += - -# Each subdirectory must supply rules for building sources it contributes -$(ROOT)/obj/aig-alan/%.o: $(ROOT)/aig-alan/%.c - @echo 'Building file: $<' - @echo 'Invoking: GCC C Compiler: $(CC)' - @echo $(CC) $(GPCC_OPTS) $(INCPATHS) -O3 -g3 -Wall -c -fmessage-length=0 -o$@ $< - @$(CC) $(GPCC_OPTS) $(INCPATHS) -O3 -g3 -Wall -c -fmessage-length=0 -o$@ $< && \ - echo -n $(@:%.o=%.d) $(dir $@) > $(@:%.o=%.d) && \ - $(CC) -MM -MG -P -w $(GPCC_OPTS) $(INCPATHS) -O3 -g3 -Wall -c -fmessage-length=0 $< >> $(@:%.o=%.d) - @echo 'Finished building: $<' - @echo ' ' - -$(ROOT)/obj/aig-alan/%.o: $(ROOT)/aig-alan/%.cpp - @echo 'Building file: $<' - @echo 'Invoking: G++ C Compiler: $(GPCC)' - @echo $(GPPCC) $(GPCC_OPTS) $(INCPATHS) -O3 -g3 -Wall -c -fmessage-length=0 -o$@ $< - @$(GPPCC) $(GPCC_OPTS) $(INCPATHS) -O3 -g3 -Wall -c -fmessage-length=0 -o$@ $< && \ - echo -n $(@:%.o=%.d) $(dir $@) > $(@:%.o=%.d) && \ - $(GPPCC) -MM -MG -P -w $(GPCC_OPTS) $(INCPATHS) -O3 -g3 -Wall -c -fmessage-length=0 $< >> $(@:%.o=%.d) - @echo 'Finished building: $<' - @echo ' ' - - diff --git a/src/temp/aig_free/vec.h b/src/temp/aig_free/vec.h deleted file mode 100644 index 61737d3a..00000000 --- a/src/temp/aig_free/vec.h +++ /dev/null @@ -1,82 +0,0 @@ -/**CFile**************************************************************** - - FileName [vec.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_H__ -#define __VEC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -#ifndef ALLOC -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef FREE -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#endif - -#ifndef REALLOC -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) -#endif - - -#include "vecInt.h" -#include "vecFlt.h" -#include "vecStr.h" -#include "vecPtr.h" -#include "vecVec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/aig_free/vecFlt.h b/src/temp/aig_free/vecFlt.h deleted file mode 100644 index 6d92d824..00000000 --- a/src/temp/aig_free/vecFlt.h +++ /dev/null @@ -1,667 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecFlt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable arrays of floats.] - - Author [Aaron P. Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_FLT_H__ -#define __VEC_FLT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -//#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Flt_t_ Vec_Flt_t; -struct Vec_Flt_t_ -{ - int nCap; - int nSize; - float * pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Vec_FltForEachEntry( vVec, Entry, i ) \ - for ( i = 0; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) -#define Vec_FltForEachEntryStart( vVec, Entry, i, Start ) \ - for ( i = Start; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) -#define Vec_FltForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ - for ( i = Start; (i < Stop) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) -#define Vec_FltForEachEntryReverse( vVec, pEntry, i ) \ - for ( i = Vec_FltSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_FltEntry(vVec, i)), 1); i-- ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltAlloc( int nCap ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( float, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltStart( int nSize ) -{ - Vec_Flt_t * p; - p = Vec_FltAlloc( nSize ); - p->nSize = nSize; - memset( p->pArray, 0, sizeof(float) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from a float array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltAllocArray( float * pArray, int nSize ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from a float array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltAllocArrayCopy( float * pArray, int nSize ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( float, nSize ); - memcpy( p->pArray, pArray, sizeof(float) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the float array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltDup( Vec_Flt_t * pVec ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( float, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(float) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltDupArray( Vec_Flt_t * pVec ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltFree( Vec_Flt_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float * Vec_FltReleaseArray( Vec_Flt_t * p ) -{ - float * pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float * Vec_FltArray( Vec_Flt_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltSize( Vec_Flt_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Vec_FltEntry( Vec_Flt_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltWriteEntry( Vec_Flt_t * p, int i, float Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltAddToEntry( Vec_Flt_t * p, int i, float Addition ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] += Addition; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Vec_FltEntryLast( Vec_Flt_t * p ) -{ - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltGrow( Vec_Flt_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( float, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltFill( Vec_Flt_t * p, int nSize, float Entry ) -{ - int i; - Vec_FltGrow( p, nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltFillExtra( Vec_Flt_t * p, int nSize, float Entry ) -{ - int i; - if ( p->nSize >= nSize ) - return; - Vec_FltGrow( p, nSize ); - for ( i = p->nSize; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltShrink( Vec_Flt_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltClear( Vec_Flt_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltPush( Vec_Flt_t * p, float Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_FltGrow( p, 16 ); - else - Vec_FltGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -// HA: Commented as proposed by Alan M. -// static inline void Vec_FltPushMem( Extra_MmStep_t * pMemMan, Vec_Flt_t * p, float Entry ) -// { -// if ( p->nSize == p->nCap ) -// { -// float * pArray; -// int i; - -// if ( p->nSize == 0 ) -// p->nCap = 1; -// pArray = (float *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 ); -// // pArray = ALLOC( float, p->nCap * 2 ); -// if ( p->pArray ) -// { -// for ( i = 0; i < p->nSize; i++ ) -// pArray[i] = p->pArray[i]; -// Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 ); -// // free( p->pArray ); -// } -// p->nCap *= 2; -// p->pArray = pArray; -// } -// p->pArray[p->nSize++] = Entry; -// } - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltPushOrder( Vec_Flt_t * p, float Entry ) -{ - int i; - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_FltGrow( p, 16 ); - else - Vec_FltGrow( p, 2 * p->nCap ); - } - p->nSize++; - for ( i = p->nSize-2; i >= 0; i-- ) - if ( p->pArray[i] > Entry ) - p->pArray[i+1] = p->pArray[i]; - else - break; - p->pArray[i+1] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltPushUnique( Vec_Flt_t * p, float Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Vec_FltPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Vec_FltPop( Vec_Flt_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Find entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltFind( Vec_Flt_t * p, float Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltRemove( Vec_Flt_t * p, float Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - if ( i == p->nSize ) - return 0; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; - return 1; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two floats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltSortCompare1( float * pp1, float * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two floats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltSortCompare2( float * pp1, float * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 > *pp2 ) - return -1; - if ( *pp1 < *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltSort( Vec_Flt_t * p, int fReverse ) -{ - if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(float), - (int (*)(const void *, const void *)) Vec_FltSortCompare2 ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(float), - (int (*)(const void *, const void *)) Vec_FltSortCompare1 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif - diff --git a/src/temp/aig_free/vecInt.h b/src/temp/aig_free/vecInt.h deleted file mode 100644 index 77bf5849..00000000 --- a/src/temp/aig_free/vecInt.h +++ /dev/null @@ -1,781 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable arrays of integers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_INT_H__ -#define __VEC_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//HA: Commented as advised by Alan -//#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Int_t_ Vec_Int_t; -struct Vec_Int_t_ -{ - int nCap; - int nSize; - int * pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Vec_IntForEachEntry( vVec, Entry, i ) \ - for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) -#define Vec_IntForEachEntryStart( vVec, Entry, i, Start ) \ - for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) -#define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ - for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) -#define Vec_IntForEachEntryReverse( vVec, pEntry, i ) \ - for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntAlloc( int nCap ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntStart( int nSize ) -{ - Vec_Int_t * p; - p = Vec_IntAlloc( nSize ); - p->nSize = nSize; - memset( p->pArray, 0, sizeof(int) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntAllocArrayCopy( int * pArray, int nSize ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( int, nSize ); - memcpy( p->pArray, pArray, sizeof(int) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntDupArray( Vec_Int_t * pVec ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntFree( Vec_Int_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int * Vec_IntReleaseArray( Vec_Int_t * p ) -{ - int * pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int * Vec_IntArray( Vec_Int_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntSize( Vec_Int_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntEntry( Vec_Int_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] += Addition; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntEntryLast( Vec_Int_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( int, p->pArray, nCapMin ); - assert( p->pArray ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Entry ) -{ - int i; - Vec_IntGrow( p, nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Entry ) -{ - int i; - if ( p->nSize >= nSize ) - return; - Vec_IntGrow( p, nSize ); - for ( i = p->nSize; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntClear( Vec_Int_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_IntGrow( p, 16 ); - else - Vec_IntGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry ) -{ - int i; - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_IntGrow( p, 16 ); - else - Vec_IntGrow( p, 2 * p->nCap ); - } - p->nSize++; - for ( i = p->nSize - 1; i >= 1; i-- ) - p->pArray[i] = p->pArray[i-1]; - p->pArray[0] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -// HA: Commented as advised by Alan M. -// static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int Entry ) -// { -// if ( p->nSize == p->nCap ) -// { -// int * pArray; -// int i; - -// if ( p->nSize == 0 ) -// p->nCap = 1; -// if ( pMemMan ) -// pArray = (int *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 ); -// else -// pArray = ALLOC( int, p->nCap * 2 ); -// if ( p->pArray ) -// { -// for ( i = 0; i < p->nSize; i++ ) -// pArray[i] = p->pArray[i]; -// if ( pMemMan ) -// Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 ); -// else -// free( p->pArray ); -// } -// p->nCap *= 2; -// p->pArray = pArray; -// } -// p->pArray[p->nSize++] = Entry; -//} - -/**Function************************************************************* - - Synopsis [Inserts the entry while preserving the increasing order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry ) -{ - int i; - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_IntGrow( p, 16 ); - else - Vec_IntGrow( p, 2 * p->nCap ); - } - p->nSize++; - for ( i = p->nSize-2; i >= 0; i-- ) - if ( p->pArray[i] > Entry ) - p->pArray[i+1] = p->pArray[i]; - else - break; - p->pArray[i+1] = Entry; -} - -/**Function************************************************************* - - Synopsis [Inserts the entry while preserving the increasing order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Vec_IntPushOrder( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Vec_IntPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the next nWords entries in the vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned * Vec_IntFetch( Vec_Int_t * p, int nWords ) -{ - p->nSize += nWords; - if ( p->nSize > p->nCap ) - { -// Vec_IntGrow( p, 2 * p->nSize ); - return NULL; - } - return ((unsigned *)p->pArray) + p->nSize - nWords; -} - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntPop( Vec_Int_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Find entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntFind( Vec_Int_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntRemove( Vec_Int_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - if ( i == p->nSize ) - return 0; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; - return 1; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two integers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntSortCompare1( int * pp1, int * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two integers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntSortCompare2( int * pp1, int * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 > *pp2 ) - return -1; - if ( *pp1 < *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntSort( Vec_Int_t * p, int fReverse ) -{ - if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(int), - (int (*)(const void *, const void *)) Vec_IntSortCompare2 ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(int), - (int (*)(const void *, const void *)) Vec_IntSortCompare1 ); -} - - -/**Function************************************************************* - - Synopsis [Comparison procedure for two integers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntSortCompareUnsigned( unsigned * pp1, unsigned * pp2 ) -{ - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntSortUnsigned( Vec_Int_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(int), - (int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned ); -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/aig_free/vecPtr.h b/src/temp/aig_free/vecPtr.h deleted file mode 100644 index 72678ed6..00000000 --- a/src/temp/aig_free/vecPtr.h +++ /dev/null @@ -1,587 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecPtr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable arrays of generic pointers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecPtr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_PTR_H__ -#define __VEC_PTR_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -//#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Ptr_t_ Vec_Ptr_t; -struct Vec_Ptr_t_ -{ - int nCap; - int nSize; - void ** pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// iterators through entries -#define Vec_PtrForEachEntry( vVec, pEntry, i ) \ - for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) -#define Vec_PtrForEachEntryStart( vVec, pEntry, i, Start ) \ - for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) -#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \ - for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) -#define Vec_PtrForEachEntryStartStop( vVec, pEntry, i, Start, Stop ) \ - for ( i = Start; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) -#define Vec_PtrForEachEntryReverse( vVec, pEntry, i ) \ - for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i-- ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrAlloc( int nCap ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - if ( nCap > 0 && nCap < 8 ) - nCap = 8; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrStart( int nSize ) -{ - Vec_Ptr_t * p; - p = Vec_PtrAlloc( nSize ); - p->nSize = nSize; - memset( p->pArray, 0, sizeof(void *) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrAllocArray( void ** pArray, int nSize ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrAllocArrayCopy( void ** pArray, int nSize ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( void *, nSize ); - memcpy( p->pArray, pArray, sizeof(void *) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrDup( Vec_Ptr_t * pVec ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(void *) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrDupArray( Vec_Ptr_t * pVec ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrFree( Vec_Ptr_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void ** Vec_PtrReleaseArray( Vec_Ptr_t * p ) -{ - void ** pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void ** Vec_PtrArray( Vec_Ptr_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_PtrSize( Vec_Ptr_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void ** Vec_PtrEntryP( Vec_Ptr_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray + i; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrGrow( Vec_Ptr_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( void *, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrFill( Vec_Ptr_t * p, int nSize, void * Entry ) -{ - int i; - Vec_PtrGrow( p, nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Entry ) -{ - int i; - if ( p->nSize >= nSize ) - return; - if ( p->nSize < 2 * nSize ) - Vec_PtrGrow( p, 2 * nSize ); - else - Vec_PtrGrow( p, p->nSize ); - for ( i = p->nSize; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrShrink( Vec_Ptr_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrClear( Vec_Ptr_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrPush( Vec_Ptr_t * p, void * Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_PtrGrow( p, 16 ); - else - Vec_PtrGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_PtrPushUnique( Vec_Ptr_t * p, void * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Vec_PtrPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_PtrPop( Vec_Ptr_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Find entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry ) -{ - int i; - // delete assuming that it is closer to the end - for ( i = p->nSize - 1; i >= 0; i-- ) - if ( p->pArray[i] == Entry ) - break; - assert( i >= 0 ); -/* - // delete assuming that it is closer to the beginning - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - assert( i < p->nSize ); -*/ - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; -} - -/**Function************************************************************* - - Synopsis [Moves the first nItems to the end.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems ) -{ - assert( nItems < p->nSize ); - Vec_PtrGrow( p, nItems + p->nSize ); - memmove( (char **)p->pArray + p->nSize, p->pArray, nItems * sizeof(void*) ); - memmove( p->pArray, (char **)p->pArray + nItems, p->nSize * sizeof(void*) ); -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(void *), - (int (*)(const void *, const void *)) Vec_PtrSortCompare ); -} - -#endif - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/aig_free/vecStr.h b/src/temp/aig_free/vecStr.h deleted file mode 100644 index a36734f6..00000000 --- a/src/temp/aig_free/vecStr.h +++ /dev/null @@ -1,510 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecStr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable arrays of characters.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecStr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_STR_H__ -#define __VEC_STR_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -//#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Str_t_ Vec_Str_t; -struct Vec_Str_t_ -{ - int nCap; - int nSize; - char * pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Vec_StrForEachEntry( vVec, Entry, i ) \ - for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrAlloc( int nCap ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrStart( int nSize ) -{ - Vec_Str_t * p; - p = Vec_StrAlloc( nSize ); - p->nSize = nSize; - memset( p->pArray, 0, sizeof(char) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrAllocArrayCopy( char * pArray, int nSize ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( char, nSize ); - memcpy( p->pArray, pArray, sizeof(char) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrDup( Vec_Str_t * pVec ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(char) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrDupArray( Vec_Str_t * pVec ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrFree( Vec_Str_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char * Vec_StrReleaseArray( Vec_Str_t * p ) -{ - char * pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char * Vec_StrArray( Vec_Str_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_StrSize( Vec_Str_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char Vec_StrEntry( Vec_Str_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char Vec_StrEntryLast( Vec_Str_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrGrow( Vec_Str_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( char, p->pArray, 2 * nCapMin ); - p->nCap = 2 * nCapMin; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrFill( Vec_Str_t * p, int nSize, char Entry ) -{ - int i; - Vec_StrGrow( p, nSize ); - p->nSize = nSize; - for ( i = 0; i < p->nSize; i++ ) - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrShrink( Vec_Str_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrClear( Vec_Str_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrPush( Vec_Str_t * p, char Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_StrGrow( p, 16 ); - else - Vec_StrGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [Appends the string to the char vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrAppend( Vec_Str_t * p, char * pString ) -{ - int i, nLength = strlen(pString); - Vec_StrGrow( p, p->nSize + nLength ); - for ( i = 0; i < nLength; i++ ) - p->pArray[p->nSize + i] = pString[i]; - p->nSize += nLength; -} - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char Vec_StrPop( Vec_Str_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_StrSortCompare1( char * pp1, char * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_StrSortCompare2( char * pp1, char * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 > *pp2 ) - return -1; - if ( *pp1 < *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrSort( Vec_Str_t * p, int fReverse ) -{ - if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(char), - (int (*)(const void *, const void *)) Vec_StrSortCompare2 ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(char), - (int (*)(const void *, const void *)) Vec_StrSortCompare1 ); -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/aig_free/vecVec.h b/src/temp/aig_free/vecVec.h deleted file mode 100644 index 2de38619..00000000 --- a/src/temp/aig_free/vecVec.h +++ /dev/null @@ -1,289 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecVec.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable vector of resizable vectors.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_VEC_H__ -#define __VEC_VEC_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -//#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Vec_t_ Vec_Vec_t; -struct Vec_Vec_t_ -{ - int nCap; - int nSize; - void ** pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// iterators through levels -#define Vec_VecForEachLevel( vGlob, vVec, i ) \ - for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) -#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \ - for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) -#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ - for ( i = LevelStart; (i <= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) -#define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \ - for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- ) - -// iteratores through entries -#define Vec_VecForEachEntry( vGlob, pEntry, i, k ) \ - for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ - Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryStart( vGlob, pEntry, i, k, LevelStart ) \ - for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \ - Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryStartStop( vGlob, pEntry, i, k, LevelStart, LevelStop ) \ - for ( i = LevelStart; i <= LevelStop; i++ ) \ - Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryReverse( vGlob, pEntry, i, k ) \ - for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ - Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryReverseReverse( vGlob, pEntry, i, k ) \ - for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \ - Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Vec_t * Vec_VecAlloc( int nCap ) -{ - Vec_Vec_t * p; - p = ALLOC( Vec_Vec_t, 1 ); - if ( nCap > 0 && nCap < 8 ) - nCap = 8; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Vec_t * Vec_VecStart( int nSize ) -{ - Vec_Vec_t * p; - int i; - p = Vec_VecAlloc( nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Vec_PtrAlloc( 0 ); - p->nSize = nSize; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecExpand( Vec_Vec_t * p, int Level ) -{ - int i; - if ( p->nSize >= Level + 1 ) - return; - Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); - for ( i = p->nSize; i <= Level; i++ ) - p->pArray[i] = Vec_PtrAlloc( 0 ); - p->nSize = Level + 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_VecSize( Vec_Vec_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_VecEntry( Vec_Vec_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Frees the vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecFree( Vec_Vec_t * p ) -{ - Vec_Ptr_t * vVec; - int i; - Vec_VecForEachLevel( p, vVec, i ) - Vec_PtrFree( vVec ); - Vec_PtrFree( (Vec_Ptr_t *)p ); -} - -/**Function************************************************************* - - Synopsis [Frees the vector of vectors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_VecSizeSize( Vec_Vec_t * p ) -{ - Vec_Ptr_t * vVec; - int i, Counter = 0; - Vec_VecForEachLevel( p, vVec, i ) - Counter += vVec->nSize; - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecClear( Vec_Vec_t * p ) -{ - Vec_Ptr_t * vVec; - int i; - Vec_VecForEachLevel( p, vVec, i ) - Vec_PtrClear( vVec ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry ) -{ - if ( p->nSize < Level + 1 ) - { - int i; - Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); - for ( i = p->nSize; i < Level + 1; i++ ) - p->pArray[i] = Vec_PtrAlloc( 0 ); - p->nSize = Level + 1; - } - Vec_PtrPush( (Vec_Ptr_t*)p->pArray[Level], Entry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry ) -{ - if ( p->nSize < Level + 1 ) - Vec_VecPush( p, Level, Entry ); - else - Vec_PtrPushUnique( (Vec_Ptr_t*)p->pArray[Level], Entry ); -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/deco/deco.h b/src/temp/deco/deco.h deleted file mode 100644 index 67126902..00000000 --- a/src/temp/deco/deco.h +++ /dev/null @@ -1,703 +0,0 @@ -/**CFile**************************************************************** - - FileName [deco.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [A simple decomposition tree/node data structure and its APIs.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DEC_H__ -#define __DEC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dec_Edge_t_ Dec_Edge_t; -struct Dec_Edge_t_ -{ - unsigned fCompl : 1; // the complemented bit - unsigned Node : 30; // the decomposition node pointed by the edge -}; - -typedef struct Dec_Node_t_ Dec_Node_t; -struct Dec_Node_t_ -{ - Dec_Edge_t eEdge0; // the left child of the node - Dec_Edge_t eEdge1; // the right child of the node - // other info - void * pFunc; // the function of the node (BDD or AIG) - unsigned Level : 14; // the level of this node in the global AIG - // printing info - unsigned fNodeOr : 1; // marks the original OR node - unsigned fCompl0 : 1; // marks the original complemented edge - unsigned fCompl1 : 1; // marks the original complemented edge - // latch info - unsigned nLat0 : 5; // the number of latches on the first edge - unsigned nLat1 : 5; // the number of latches on the second edge - unsigned nLat2 : 5; // the number of latches on the output edge -}; - -typedef struct Dec_Graph_t_ Dec_Graph_t; -struct Dec_Graph_t_ -{ - int fConst; // marks the constant 1 graph - int nLeaves; // the number of leaves - int nSize; // the number of nodes (including the leaves) - int nCap; // the number of allocated nodes - Dec_Node_t * pNodes; // the array of leaves and internal nodes - Dec_Edge_t eRoot; // the pointer to the topmost node -}; - -typedef struct Dec_Man_t_ Dec_Man_t; -struct Dec_Man_t_ -{ - void * pMvcMem; // memory manager for MVC cover (used for factoring) - Vec_Int_t * vCubes; // storage for cubes - Vec_Int_t * vLits; // storage for literals - // precomputation information about 4-variable functions - unsigned short * puCanons; // canonical forms - char * pPhases; // canonical phases - char * pPerms; // canonical permutations - unsigned char * pMap; // mapping of functions into class numbers -}; - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// interator throught the leaves -#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ - for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) -// interator throught the internal nodes -#define Dec_GraphForEachNode( pGraph, pAnd, i ) \ - for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates an edge pointing to the node in the given polarity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) -{ - Dec_Edge_t eEdge = { fCompl, Node }; - return eEdge; -} - -/**Function************************************************************* - - Synopsis [Converts the edge into unsigned integer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) -{ - return (eEdge.Node << 1) | eEdge.fCompl; -} - -/**Function************************************************************* - - Synopsis [Converts unsigned integer into the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) -{ - return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); -} - -/**Function************************************************************* - - Synopsis [Converts the edge into unsigned integer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge ) -{ - return *(unsigned *)&eEdge; -} - -/**Function************************************************************* - - Synopsis [Converts unsigned integer into the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge ) -{ - return *(Dec_Edge_t *)&Edge; -} - -/**Function************************************************************* - - Synopsis [Creates a graph with the given number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves ) -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->nLeaves = nLeaves; - pGraph->nSize = nLeaves; - pGraph->nCap = 2 * nLeaves + 50; - pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap ); - memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates constant 0 graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateConst0() -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->fConst = 1; - pGraph->eRoot.fCompl = 1; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates constant 1 graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateConst1() -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->fConst = 1; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates the literal graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) -{ - Dec_Graph_t * pGraph; - assert( 0 <= iLeaf && iLeaf < nLeaves ); - pGraph = Dec_GraphCreate( nLeaves ); - pGraph->eRoot.Node = iLeaf; - pGraph->eRoot.fCompl = fCompl; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates a graph with the given number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) -{ - FREE( pGraph->pNodes ); - free( pGraph ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst && pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is constant 1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst && !pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is complemented.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph ) -{ - return pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Checks if the graph is complemented.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphComplement( Dec_Graph_t * pGraph ) -{ - pGraph->eRoot.fCompl ^= 1; -} - - -/**Function************************************************************* - - Synopsis [Returns the number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph ) -{ - return pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the number of internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph ) -{ - return pGraph->nSize - pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i ) -{ - return pGraph->pNodes + i; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph ) -{ - return pGraph->pNodes + pGraph->nSize - 1; -} - -/**Function************************************************************* - - Synopsis [Returns the number of the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) -{ - return pNode - pGraph->pNodes; -} - -/**Function************************************************************* - - Synopsis [Check if the graph represents elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph ) -{ - return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Check if the graph represents elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) -{ - return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the elementary variable elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph ) -{ - assert( Dec_GraphIsVar( pGraph ) ); - return Dec_GraphNode( pGraph, pGraph->eRoot.Node ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of the elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph ) -{ - assert( Dec_GraphIsVar( pGraph ) ); - return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Sets the root of the graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot ) -{ - pGraph->eRoot = eRoot; -} - -/**Function************************************************************* - - Synopsis [Appends a new node to the graph.] - - Description [This procedure is meant for internal use.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph ) -{ - Dec_Node_t * pNode; - if ( pGraph->nSize == pGraph->nCap ) - { - pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); - pGraph->nCap = 2 * pGraph->nCap; - } - pNode = pGraph->pNodes + pGraph->nSize++; - memset( pNode, 0, sizeof(Dec_Node_t) ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates an AND node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) -{ - Dec_Node_t * pNode; - // get the new node - pNode = Dec_GraphAppendNode( pGraph ); - // set the inputs and other info - pNode->eEdge0 = eEdge0; - pNode->eEdge1 = eEdge1; - pNode->fCompl0 = eEdge0.fCompl; - pNode->fCompl1 = eEdge1.fCompl; - return Dec_EdgeCreate( pGraph->nSize - 1, 0 ); -} - -/**Function************************************************************* - - Synopsis [Creates an OR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) -{ - Dec_Node_t * pNode; - // get the new node - pNode = Dec_GraphAppendNode( pGraph ); - // set the inputs and other info - pNode->eEdge0 = eEdge0; - pNode->eEdge1 = eEdge1; - pNode->fCompl0 = eEdge0.fCompl; - pNode->fCompl1 = eEdge1.fCompl; - // make adjustments for the OR gate - pNode->fNodeOr = 1; - pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; - pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; - return Dec_EdgeCreate( pGraph->nSize - 1, 1 ); -} - -/**Function************************************************************* - - Synopsis [Creates an XOR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - if ( Type == 0 ) - { - // derive the first AND - eEdge0.fCompl ^= 1; - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - eEdge0.fCompl ^= 1; - // derive the second AND - eEdge1.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - } - else - { - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the second AND - eEdge0.fCompl ^= 1; - eEdge1.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eNode.fCompl ^= 1; - } - return eNode; -} - -/**Function************************************************************* - - Synopsis [Creates an XOR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - if ( Type == 0 ) - { - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); - // derive the second AND - eEdgeC.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - } - else - { - // complement the arguments - eEdgeT.fCompl ^= 1; - eEdgeE.fCompl ^= 1; - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); - // derive the second AND - eEdgeC.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eNode.fCompl ^= 1; - } - return eNode; -} - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/deco/module.make b/src/temp/deco/module.make deleted file mode 100644 index d6d908e7..00000000 --- a/src/temp/deco/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += diff --git a/src/temp/ivy/ivy.h b/src/temp/ivy/ivy.h deleted file mode 100644 index a8c8b289..00000000 --- a/src/temp/ivy/ivy.h +++ /dev/null @@ -1,555 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivy.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivy.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __IVY_H__ -#define __IVY_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ivy_Man_t_ Ivy_Man_t; -typedef struct Ivy_Obj_t_ Ivy_Obj_t; -typedef int Ivy_Edge_t; -typedef struct Ivy_FraigParams_t_ Ivy_FraigParams_t; - -// object types -typedef enum { - IVY_NONE, // 0: non-existent object - IVY_PI, // 1: primary input (and constant 1 node) - IVY_PO, // 2: primary output - IVY_ASSERT, // 3: assertion - IVY_LATCH, // 4: sequential element - IVY_AND, // 5: AND node - IVY_EXOR, // 6: EXOR node - IVY_BUF, // 7: buffer (temporary) - IVY_VOID // 8: unused object -} Ivy_Type_t; - -// latch initial values -typedef enum { - IVY_INIT_NONE, // 0: not a latch - IVY_INIT_0, // 1: zero - IVY_INIT_1, // 2: one - IVY_INIT_DC // 3: don't-care -} Ivy_Init_t; - -// the AIG node -struct Ivy_Obj_t_ // 24 bytes (32-bit) or 32 bytes (64-bit) // 10 words - 16 words -{ - int Id; // integer ID - int TravId; // traversal ID - unsigned Type : 4; // object type - unsigned fMarkA : 1; // multipurpose mask - unsigned fMarkB : 1; // multipurpose mask - unsigned fExFan : 1; // set to 1 if last fanout added is EXOR - unsigned fPhase : 1; // value under 000...0 pattern - unsigned fFailTfo : 1; // the TFO of the failed node - unsigned Init : 2; // latch initial value - unsigned Level : 21; // logic level - int nRefs; // reference counter - Ivy_Obj_t * pFanin0; // fanin - Ivy_Obj_t * pFanin1; // fanin - Ivy_Obj_t * pFanout; // fanout - Ivy_Obj_t * pNextFan0; // next fanout of the first fanin - Ivy_Obj_t * pNextFan1; // next fanout of the second fanin - Ivy_Obj_t * pPrevFan0; // prev fanout of the first fanin - Ivy_Obj_t * pPrevFan1; // prev fanout of the second fanin - Ivy_Obj_t * pEquiv; // equivalent node -}; - -// the AIG manager -struct Ivy_Man_t_ -{ - // AIG nodes - Vec_Ptr_t * vPis; // the array of PIs - Vec_Ptr_t * vPos; // the array of POs - Vec_Ptr_t * vBufs; // the array of buffers - Vec_Ptr_t * vObjs; // the array of objects - Ivy_Obj_t * pConst1; // the constant 1 node - Ivy_Obj_t Ghost; // the ghost node - // AIG node counters - int nObjs[IVY_VOID];// the number of objects by type - int nCreated; // the number of created objects - int nDeleted; // the number of deleted objects - // stuctural hash table - int * pTable; // structural hash table - int nTableSize; // structural hash table size - // various data members - int fCatchExor; // set to 1 to detect EXORs - int nTravIds; // the traversal ID - int nLevelMax; // the maximum level - Vec_Int_t * vRequired; // required times - int fFanout; // fanout is allocated - void * pData; // the temporary data - void * pCopy; // the temporary data - Ivy_Man_t * pHaig; // history AIG if present - int nClassesSkip; // the number of skipped classes - // memory management - Vec_Ptr_t * vChunks; // allocated memory pieces - Vec_Ptr_t * vPages; // memory pages used by nodes - Ivy_Obj_t * pListFree; // the list of free nodes - // timing statistics - int time1; - int time2; -}; - -struct Ivy_FraigParams_t_ -{ - int nSimWords; // the number of words in the simulation info - double dSimSatur; // the ratio of refined classes when saturation is reached - int fPatScores; // enables simulation pattern scoring - int MaxScore; // max score after which resimulation is used - double dActConeRatio; // the ratio of cone to be bumped - double dActConeBumpMax; // the largest bump in activity - int fProve; // prove the miter outputs - int fVerbose; // verbose output - int fDoSparse; // skip sparse functions - int nBTLimitNode; // conflict limit at a node - int nBTLimitMiter; // conflict limit at an output - int nBTLimitGlobal; // conflict limit global - int nInsLimitNode; // inspection limit at a node - int nInsLimitMiter; // inspection limit at an output - int nInsLimitGlobal; // inspection limit global -}; - - -#define IVY_CUT_LIMIT 256 -#define IVY_CUT_INPUT 6 - -typedef struct Ivy_Cut_t_ Ivy_Cut_t; -struct Ivy_Cut_t_ -{ - short nSize; - short nSizeMax; - int pArray[IVY_CUT_INPUT]; - unsigned uHash; -}; - -typedef struct Ivy_Store_t_ Ivy_Store_t; -struct Ivy_Store_t_ -{ - int nCuts; - int nCutsM; - int nCutsMax; - int fSatur; - Ivy_Cut_t pCuts[IVY_CUT_LIMIT]; // storage for cuts -}; - -#define IVY_LEAF_MASK 255 -#define IVY_LEAF_BITS 8 - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IVY_MIN(a,b) (((a) < (b))? (a) : (b)) -#define IVY_MAX(a,b) (((a) > (b))? (a) : (b)) - -static inline int Ivy_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -static inline int Ivy_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline int Ivy_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } -static inline void Ivy_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } -static inline void Ivy_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } - -static inline Ivy_Obj_t * Ivy_Regular( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) & ~01); } -static inline Ivy_Obj_t * Ivy_Not( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ 01); } -static inline Ivy_Obj_t * Ivy_NotCond( Ivy_Obj_t * p, int c ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ (c)); } -static inline int Ivy_IsComplement( Ivy_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } - -static inline Ivy_Obj_t * Ivy_ManConst0( Ivy_Man_t * p ) { return Ivy_Not(p->pConst1); } -static inline Ivy_Obj_t * Ivy_ManConst1( Ivy_Man_t * p ) { return p->pConst1; } -static inline Ivy_Obj_t * Ivy_ManGhost( Ivy_Man_t * p ) { return &p->Ghost; } -static inline Ivy_Obj_t * Ivy_ManPi( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPis, i); } -static inline Ivy_Obj_t * Ivy_ManPo( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPos, i); } -static inline Ivy_Obj_t * Ivy_ManObj( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vObjs, i); } - -static inline Ivy_Edge_t Ivy_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } -static inline int Ivy_EdgeId( Ivy_Edge_t Edge ) { return Edge >> 1; } -static inline int Ivy_EdgeIsComplement( Ivy_Edge_t Edge ) { return Edge & 1; } -static inline Ivy_Edge_t Ivy_EdgeRegular( Ivy_Edge_t Edge ) { return (Edge >> 1) << 1; } -static inline Ivy_Edge_t Ivy_EdgeNot( Ivy_Edge_t Edge ) { return Edge ^ 1; } -static inline Ivy_Edge_t Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond ) { return Edge ^ fCond; } -static inline Ivy_Edge_t Ivy_EdgeFromNode( Ivy_Obj_t * pNode ) { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) ); } -static inline Ivy_Obj_t * Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); } - -static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << IVY_LEAF_BITS) | Lat; } -static inline int Ivy_LeafId( int Leaf ) { return Leaf >> IVY_LEAF_BITS; } -static inline int Ivy_LeafLat( int Leaf ) { return Leaf & IVY_LEAF_MASK; } - -static inline int Ivy_ManPiNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PI]; } -static inline int Ivy_ManPoNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PO]; } -static inline int Ivy_ManAssertNum( Ivy_Man_t * p ) { return p->nObjs[IVY_ASSERT]; } -static inline int Ivy_ManLatchNum( Ivy_Man_t * p ) { return p->nObjs[IVY_LATCH]; } -static inline int Ivy_ManAndNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]; } -static inline int Ivy_ManExorNum( Ivy_Man_t * p ) { return p->nObjs[IVY_EXOR]; } -static inline int Ivy_ManBufNum( Ivy_Man_t * p ) { return p->nObjs[IVY_BUF]; } -static inline int Ivy_ManObjNum( Ivy_Man_t * p ) { return p->nCreated - p->nDeleted; } -static inline int Ivy_ManObjIdMax( Ivy_Man_t * p ) { return Vec_PtrSize(p->vObjs)-1; } -static inline int Ivy_ManNodeNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR];} -static inline int Ivy_ManHashObjNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH]; } -static inline int Ivy_ManGetCost( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; } - -static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { return pObj->Type; } -static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { return pObj->Init; } -static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { return pObj->Id == 0; } -static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { return pObj->Id < 0; } -static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_NONE; } -static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI; } -static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO; } -static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_ASSERT; } -static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND; } -static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_EXOR; } -static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_BUF; } -static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; } -static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; } -static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; } - -static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { return pObj->fMarkA; } -static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 1; } -static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 0; } - -static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } -static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } -static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } -static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } -static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds - 1); } - -static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { return pObj->Id; } -static inline int Ivy_ObjTravId( Ivy_Obj_t * pObj ) { return pObj->TravId; } -static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { return pObj->fPhase; } -static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { return pObj->fExFan; } -static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { return pObj->nRefs; } -static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { pObj->nRefs++; } -static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } -static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; } -static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; } -static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin0); } -static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin1); } -static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin0); } -static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin1); } -static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { return pObj->pFanin0; } -static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { return pObj->pFanin1; } -static inline Ivy_Obj_t * Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL; } -static inline Ivy_Obj_t * Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL; } -static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { return pObj->Level; } -static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); } -static inline int Ivy_ObjFaninPhase( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj)? !Ivy_Regular(pObj)->fPhase : pObj->fPhase; } - -static inline void Ivy_ObjClean( Ivy_Obj_t * pObj ) -{ - int IdSaved = pObj->Id; - memset( pObj, 0, sizeof(Ivy_Obj_t) ); - pObj->Id = IdSaved; -} -static inline void Ivy_ObjOverwrite( Ivy_Obj_t * pBase, Ivy_Obj_t * pData ) -{ - int IdSaved = pBase->Id; - memcpy( pBase, pData, sizeof(Ivy_Obj_t) ); - pBase->Id = IdSaved; -} -static inline int Ivy_ObjWhatFanin( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanin ) -{ - if ( Ivy_ObjFanin0(pObj) == pFanin ) return 0; - if ( Ivy_ObjFanin1(pObj) == pFanin ) return 1; - assert(0); return -1; -} -static inline int Ivy_ObjFanoutC( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - if ( Ivy_ObjFanin0(pFanout) == pObj ) return Ivy_ObjFaninC0(pObj); - if ( Ivy_ObjFanin1(pFanout) == pObj ) return Ivy_ObjFaninC1(pObj); - assert(0); return -1; -} - -// create the ghost of the new node -static inline Ivy_Obj_t * Ivy_ObjCreateGhost( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type, Ivy_Init_t Init ) -{ - Ivy_Obj_t * pGhost, * pTemp; - assert( Type != IVY_AND || !Ivy_ObjIsConst1(Ivy_Regular(p0)) ); - assert( p1 == NULL || !Ivy_ObjIsConst1(Ivy_Regular(p1)) ); - assert( Type == IVY_PI || Ivy_Regular(p0) != Ivy_Regular(p1) ); - assert( Type != IVY_LATCH || !Ivy_IsComplement(p0) ); -// assert( p1 == NULL || (!Ivy_ObjIsLatch(Ivy_Regular(p0)) || !Ivy_ObjIsLatch(Ivy_Regular(p1))) ); - pGhost = Ivy_ManGhost(p); - pGhost->Type = Type; - pGhost->Init = Init; - pGhost->pFanin0 = p0; - pGhost->pFanin1 = p1; - if ( p1 && Ivy_ObjFaninId0(pGhost) > Ivy_ObjFaninId1(pGhost) ) - pTemp = pGhost->pFanin0, pGhost->pFanin0 = pGhost->pFanin1, pGhost->pFanin1 = pTemp; - return pGhost; -} - -// get the complemented initial state -static Ivy_Init_t Ivy_InitNotCond( Ivy_Init_t Init, int fCompl ) -{ - assert( Init != IVY_INIT_NONE ); - if ( fCompl == 0 ) - return Init; - if ( Init == IVY_INIT_0 ) - return IVY_INIT_1; - if ( Init == IVY_INIT_1 ) - return IVY_INIT_0; - return IVY_INIT_DC; -} - -// get the initial state after forward retiming over AND gate -static Ivy_Init_t Ivy_InitAnd( Ivy_Init_t InitA, Ivy_Init_t InitB ) -{ - assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); - if ( InitA == IVY_INIT_0 || InitB == IVY_INIT_0 ) - return IVY_INIT_0; - if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) - return IVY_INIT_DC; - return IVY_INIT_1; -} - -// get the initial state after forward retiming over EXOR gate -static Ivy_Init_t Ivy_InitExor( Ivy_Init_t InitA, Ivy_Init_t InitB ) -{ - assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); - if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) - return IVY_INIT_DC; - if ( InitA == IVY_INIT_0 && InitB == IVY_INIT_1 ) - return IVY_INIT_1; - if ( InitA == IVY_INIT_1 && InitB == IVY_INIT_0 ) - return IVY_INIT_1; - return IVY_INIT_0; -} - -// internal memory manager -static inline Ivy_Obj_t * Ivy_ManFetchMemory( Ivy_Man_t * p ) -{ - extern void Ivy_ManAddMemory( Ivy_Man_t * p ); - Ivy_Obj_t * pTemp; - if ( p->pListFree == NULL ) - Ivy_ManAddMemory( p ); - pTemp = p->pListFree; - p->pListFree = *((Ivy_Obj_t **)pTemp); - memset( pTemp, 0, sizeof(Ivy_Obj_t) ); - return pTemp; -} -static inline void Ivy_ManRecycleMemory( Ivy_Man_t * p, Ivy_Obj_t * pEntry ) -{ - pEntry->Type = IVY_NONE; // distinquishes dead node from live node - *((Ivy_Obj_t **)pEntry) = p->pListFree; - p->pListFree = pEntry; -} - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over the primary inputs -#define Ivy_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPis, pObj, i ) -// iterator over the primary outputs -#define Ivy_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPos, pObj, i ) -// iterator over all objects, including those currently not used -#define Ivy_ManForEachObj( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else -// iterator over the combinational inputs -#define Ivy_ManForEachCi( p, pObj, i ) \ - Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCi(pObj) ) {} else -// iterator over the combinational outputs -#define Ivy_ManForEachCo( p, pObj, i ) \ - Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCo(pObj) ) {} else -// iterator over logic nodes (AND and EXOR gates) -#define Ivy_ManForEachNode( p, pObj, i ) \ - Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsNode(pObj) ) {} else -// iterator over logic latches -#define Ivy_ManForEachLatch( p, pObj, i ) \ - Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsLatch(pObj) ) {} else -// iterator over the nodes whose IDs are stored in the array -#define Ivy_ManForEachNodeVec( p, vIds, pObj, i ) \ - for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Ivy_ManObj(p, Vec_IntEntry(vIds,i))); i++ ) -// iterator over the fanouts of an object -#define Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, i ) \ - for ( i = 0, Ivy_ObjCollectFanouts(p, pObj, vArray); \ - i < Vec_PtrSize(vArray) && ((pFanout) = Vec_PtrEntry(vArray,i)); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== ivyBalance.c ========================================================*/ -extern Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ); -extern Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ); -/*=== ivyCanon.c ========================================================*/ -extern Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); -/*=== ivyCheck.c ========================================================*/ -extern int Ivy_ManCheck( Ivy_Man_t * p ); -extern int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ); -extern int Ivy_ManCheckFanouts( Ivy_Man_t * p ); -extern int Ivy_ManCheckChoices( Ivy_Man_t * p ); -/*=== ivyCut.c ==========================================================*/ -extern void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ); -extern Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); -/*=== ivyDfs.c ==========================================================*/ -extern Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ); -extern Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ); -extern void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ); -extern Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ); -extern Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ); -extern int Ivy_ManIsAcyclic( Ivy_Man_t * p ); -extern int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ); -/*=== ivyDsd.c ==========================================================*/ -extern int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ); -extern void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ); -extern unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ); -extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); -extern Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ); -/*=== ivyFanout.c ==========================================================*/ -extern void Ivy_ManStartFanout( Ivy_Man_t * p ); -extern void Ivy_ManStopFanout( Ivy_Man_t * p ); -extern void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); -extern void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); -extern void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ); -extern void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ); -extern Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -/*=== ivyFastMap.c =============================================================*/ -extern void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ); -extern void Ivy_FastMapStop( Ivy_Man_t * pAig ); -extern void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ); -extern void Ivy_FastMapReverseLevel( Ivy_Man_t * pAig ); -/*=== ivyFraig.c ==========================================================*/ -extern int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ); -extern Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); -extern Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); -extern void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ); -/*=== ivyHaig.c ==========================================================*/ -extern void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ); -extern void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ); -extern void Ivy_ManHaigStop( Ivy_Man_t * p ); -extern void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ); -extern void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ); -extern void Ivy_ManHaigSimulate( Ivy_Man_t * p ); -/*=== ivyIsop.c ==========================================================*/ -extern int Ivy_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vCover, int fTryBoth ); -/*=== ivyMan.c ==========================================================*/ -extern Ivy_Man_t * Ivy_ManStart(); -extern Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ); -extern Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ); -extern Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ); -extern void Ivy_ManStop( Ivy_Man_t * p ); -extern int Ivy_ManCleanup( Ivy_Man_t * p ); -extern int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ); -extern void Ivy_ManPrintStats( Ivy_Man_t * p ); -extern void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ); -/*=== ivyMem.c ==========================================================*/ -extern void Ivy_ManStartMemory( Ivy_Man_t * p ); -extern void Ivy_ManStopMemory( Ivy_Man_t * p ); -/*=== ivyMulti.c ==========================================================*/ -extern Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); -extern Ivy_Obj_t * Ivy_Multi1( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); -extern Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ); -extern Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); -extern int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol ); -/*=== ivyObj.c ==========================================================*/ -extern Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ); -extern Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ); -extern Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ); -extern void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ); -extern void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ); -extern void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); -extern void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); -extern void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ); -extern void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ); -/*=== ivyOper.c =========================================================*/ -extern Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ); -extern Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ); -extern Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ); -extern Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ); -extern Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); -/*=== ivyResyn.c =========================================================*/ -extern Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); -extern Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); -extern Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ); -/*=== ivyRewrite.c =========================================================*/ -extern int Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); -extern int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); -extern int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ); -/*=== ivySeq.c =========================================================*/ -extern int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ); -/*=== ivyShow.c =========================================================*/ -extern void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); -/*=== ivyTable.c ========================================================*/ -extern Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ); -extern int Ivy_TableCountEntries( Ivy_Man_t * p ); -extern void Ivy_TableProfile( Ivy_Man_t * p ); -/*=== ivyUtil.c =========================================================*/ -extern void Ivy_ManIncrementTravId( Ivy_Man_t * p ); -extern void Ivy_ManCleanTravId( Ivy_Man_t * p ); -extern unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ); -extern void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ); -extern Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ); -extern int Ivy_ManLevels( Ivy_Man_t * p ); -extern void Ivy_ManResetLevels( Ivy_Man_t * p ); -extern int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ); -extern int Ivy_ObjIsMuxType( Ivy_Obj_t * pObj ); -extern Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObjT, Ivy_Obj_t ** ppObjE ); -extern Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ); -extern void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ); -extern void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/ivy/ivyBalance.c b/src/temp/ivy/ivyBalance.c deleted file mode 100644 index 5627039a..00000000 --- a/src/temp/ivy/ivyBalance.c +++ /dev/null @@ -1,404 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyBalance.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Algebraic AIG balancing.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); -static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); -static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); -static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); -static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs algebraic balancing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ) -{ - Ivy_Man_t * pNew; - Ivy_Obj_t * pObj, * pDriver; - Vec_Vec_t * vStore; - int i, NewNodeId; - // clean the old manager - Ivy_ManCleanTravId( p ); - // create the new manager - pNew = Ivy_ManStart(); - // map the nodes - Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) ); - Ivy_ManForEachPi( p, pObj, i ) - pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) ); - // if HAIG is defined, trasfer the pointers to the PIs/latches -// if ( p->pHaig ) -// Ivy_ManHaigTrasfer( p, pNew ); - // balance the AIG - vStore = Vec_VecAlloc( 50 ); - Ivy_ManForEachPo( p, pObj, i ) - { - pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) ); - NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel ); - NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) ); - Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) ); - } - Vec_VecFree( vStore ); - if ( i = Ivy_ManCleanup( pNew ) ) - { -// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); - } - // check the resulting AIG - if ( !Ivy_ManCheck(pNew) ) - printf( "Ivy_ManBalance(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) -{ - int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level; - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the ID of new node constructed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) -{ - Ivy_Obj_t * pObjNew; - Vec_Ptr_t * vSuper; - int i, NewNodeId; - assert( !Ivy_IsComplement(pObjOld) ); - assert( !Ivy_ObjIsBuf(pObjOld) ); - // return if the result is known - if ( Ivy_ObjIsConst1(pObjOld) ) - return pObjOld->TravId; - if ( pObjOld->TravId ) - return pObjOld->TravId; - assert( Ivy_ObjIsNode(pObjOld) ); - // get the implication supergate - vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level ); - if ( vSuper->nSize == 0 ) - { // it means that the supergate contains two nodes in the opposite polarity - pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) ); - return pObjOld->TravId; - } - if ( vSuper->nSize < 2 ) - printf( "BUG!\n" ); - // for each old node, derive the new well-balanced node - for ( i = 0; i < vSuper->nSize; i++ ) - { - NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); - NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(vSuper->pArray[i]) ); - vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId ); - } - // build the supergate - pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel ); - vSuper->nSize = 0; - // make sure the balanced node is not assigned - assert( pObjOld->TravId == 0 ); - pObjOld->TravId = Ivy_EdgeFromNode( pObjNew ); -// assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level ); - return pObjOld->TravId; -} - -/**Function************************************************************* - - Synopsis [Builds implication supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ) -{ - Ivy_Obj_t * pObj1, * pObj2; - int LeftBound; - assert( vSuper->nSize > 1 ); - // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, Ivy_NodeCompareLevelsDecrease ); - // balance the nodes - while ( vSuper->nSize > 1 ) - { - // find the left bound on the node to be paired - LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper ); - // find the node that can be shared (if no such node, randomize choice) - Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR ); - // pull out the last two nodes - pObj1 = Vec_PtrPop(vSuper); - pObj2 = Vec_PtrPop(vSuper); - Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) ); - } - return Vec_PtrEntry(vSuper, 0); -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Ivy_Regular(pObj)->fMarkB ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pObj ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Ivy_Not(pObj) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1) ) - { - Vec_PtrPush( vSuper, pObj ); - Ivy_Regular(pObj)->fMarkB = 1; - return 0; - } - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsNode(pObj) ); - // go through the branches - RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper ); - RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) -{ - Vec_Ptr_t * vNodes; - int RetValue, i; - assert( !Ivy_IsComplement(pObj) ); - // extend the storage - if ( Vec_VecSize( vStore ) <= Level ) - Vec_VecPush( vStore, Level, 0 ); - // get the temporary array of nodes - vNodes = Vec_VecEntry( vStore, Level ); - Vec_PtrClear( vNodes ); - // collect the nodes in the implication supergate - RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - Ivy_Regular(pObj)->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Finds the left bound on the next candidate to be paired.] - - Description [The nodes in the array are in the decreasing order of levels. - The last node in the array has the smallest level. By default it would be paired - with the next node on the left. However, it may be possible to pair it with some - other node on the left, in such a way that the new node is shared. This procedure - finds the index of the left-most node, which can be paired with the last node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) -{ - Ivy_Obj_t * pObjRight, * pObjLeft; - int Current; - // if two or less nodes, pair with the first - if ( Vec_PtrSize(vSuper) < 3 ) - return 0; - // set the pointer to the one before the last - Current = Vec_PtrSize(vSuper) - 2; - pObjRight = Vec_PtrEntry( vSuper, Current ); - // go through the nodes to the left of this one - for ( Current--; Current >= 0; Current-- ) - { - // get the next node on the left - pObjLeft = Vec_PtrEntry( vSuper, Current ); - // if the level of this node is different, quit the loop - if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level ) - break; - } - Current++; - // get the node, for which the equality holds - pObjLeft = Vec_PtrEntry( vSuper, Current ); - assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level ); - return Current; -} - -/**Function************************************************************* - - Synopsis [Moves closer to the end the node that is best for sharing.] - - Description [If there is no node with sharing, randomly chooses one of - the legal nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) -{ - Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; - int RightBound, i; - // get the right bound - RightBound = Vec_PtrSize(vSuper) - 2; - assert( LeftBound <= RightBound ); - if ( LeftBound == RightBound ) - return; - // get the two last nodes - pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); - pObj2 = Vec_PtrEntry( vSuper, RightBound ); - if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 ) - return; - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - pObj3 = Vec_PtrEntry( vSuper, i ); - if ( Ivy_Regular(pObj3) == p->pConst1 ) - { - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE ); - if ( Ivy_TableLookup( p, pGhost ) ) - { - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - } -/* - // we did not find the node to share, randomize choice - { - int Choice = rand() % (RightBound - LeftBound + 1); - pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pObj1, * pObj2; - int i; - if ( Vec_PtrPushUnique(vStore, pObj) ) - return; - // find the p of the node - for ( i = vStore->nSize-1; i > 0; i-- ) - { - pObj1 = vStore->pArray[i ]; - pObj2 = vStore->pArray[i-1]; - if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level ) - break; - vStore->pArray[i ] = pObj2; - vStore->pArray[i-1] = pObj1; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyCanon.c b/src/temp/ivy/ivyCanon.c deleted file mode 100644 index 5768b87e..00000000 --- a/src/temp/ivy/ivyCanon.c +++ /dev/null @@ -1,144 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyCanon.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Finding canonical form of objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyCanon.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Ivy_Obj_t * Ivy_TableLookupPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1, int fCompl0, int fCompl1, Ivy_Type_t Type ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_CanonPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) -{ - Ivy_Obj_t * pResult, * pLat0, * pLat1; - Ivy_Init_t Init, Init0, Init1; - int fCompl0, fCompl1; - Ivy_Type_t Type; - assert( Ivy_ObjIsNode(pGhost) ); - assert( Ivy_ObjIsAnd(pGhost) || (!Ivy_ObjFaninC0(pGhost) && !Ivy_ObjFaninC1(pGhost)) ); - assert( Ivy_ObjFaninId0(pGhost) != 0 && Ivy_ObjFaninId1(pGhost) != 0 ); - // consider the case when the pair is canonical - if ( !Ivy_ObjIsLatch(Ivy_ObjFanin0(pGhost)) || !Ivy_ObjIsLatch(Ivy_ObjFanin1(pGhost)) ) - { - if ( pResult = Ivy_TableLookup( p, pGhost ) ) - return pResult; - return Ivy_ObjCreate( p, pGhost ); - } - /// remember the latches - pLat0 = Ivy_ObjFanin0(pGhost); - pLat1 = Ivy_ObjFanin1(pGhost); - // remember type and compls - Type = Ivy_ObjType(pGhost); - fCompl0 = Ivy_ObjFaninC0(pGhost); - fCompl1 = Ivy_ObjFaninC1(pGhost); - // call recursively - pResult = Ivy_Oper( p, Ivy_NotCond(Ivy_ObjFanin0(pLat0), fCompl0), Ivy_NotCond(Ivy_ObjFanin0(pLat1), fCompl1), Type ); - // build latch on top of this - Init0 = Ivy_InitNotCond( Ivy_ObjInit(pLat0), fCompl0 ); - Init1 = Ivy_InitNotCond( Ivy_ObjInit(pLat1), fCompl1 ); - Init = (Type == IVY_AND)? Ivy_InitAnd(Init0, Init1) : Ivy_InitExor(Init0, Init1); - return Ivy_Latch( p, pResult, Init ); -} - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) -{ - Ivy_Obj_t * pGhost, * pResult; - pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_AND, IVY_INIT_NONE ); - pResult = Ivy_CanonPair_rec( p, pGhost ); - return pResult; -} - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) -{ - Ivy_Obj_t * pGhost, * pResult; - int fCompl = Ivy_IsComplement(pObj0) ^ Ivy_IsComplement(pObj1); - pObj0 = Ivy_Regular(pObj0); - pObj1 = Ivy_Regular(pObj1); - pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_EXOR, IVY_INIT_NONE ); - pResult = Ivy_CanonPair_rec( p, pGhost ); - return Ivy_NotCond( pResult, fCompl ); -} - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) -{ - Ivy_Obj_t * pGhost, * pResult; - int fCompl = Ivy_IsComplement(pObj); - pObj = Ivy_Regular(pObj); - pGhost = Ivy_ObjCreateGhost( p, pObj, NULL, IVY_LATCH, Ivy_InitNotCond(Init, fCompl) ); - pResult = Ivy_TableLookup( p, pGhost ); - if ( pResult == NULL ) - pResult = Ivy_ObjCreate( p, pGhost ); - return Ivy_NotCond( pResult, fCompl ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyCheck.c b/src/temp/ivy/ivyCheck.c deleted file mode 100644 index 55448f19..00000000 --- a/src/temp/ivy/ivyCheck.c +++ /dev/null @@ -1,273 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [AIG checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks the consistency of the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCheck( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj, * pObj2; - int i; - Ivy_ManForEachObj( p, pObj, i ) - { - // skip deleted nodes - if ( Ivy_ObjId(pObj) != i ) - { - printf( "Ivy_ManCheck: Node with ID %d is listed as number %d in the array of objects.\n", pObj->Id, i ); - return 0; - } - // consider the constant node and PIs - if ( i == 0 || Ivy_ObjIsPi(pObj) ) - { - if ( Ivy_ObjFaninId0(pObj) || Ivy_ObjFaninId1(pObj) || Ivy_ObjLevel(pObj) ) - { - printf( "Ivy_ManCheck: The AIG has non-standard constant or PI node with ID \"%d\".\n", pObj->Id ); - return 0; - } - continue; - } - if ( Ivy_ObjIsPo(pObj) ) - { - if ( Ivy_ObjFaninId1(pObj) ) - { - printf( "Ivy_ManCheck: The AIG has non-standard PO node with ID \"%d\".\n", pObj->Id ); - return 0; - } - continue; - } - if ( Ivy_ObjIsBuf(pObj) ) - { - if ( Ivy_ObjFanin1(pObj) ) - { - printf( "Ivy_ManCheck: The buffer with ID \"%d\" contains second fanin.\n", pObj->Id ); - return 0; - } - continue; - } - if ( Ivy_ObjIsLatch(pObj) ) - { - if ( Ivy_ObjFanin1(pObj) ) - { - printf( "Ivy_ManCheck: The latch with ID \"%d\" contains second fanin.\n", pObj->Id ); - return 0; - } - if ( Ivy_ObjInit(pObj) == IVY_INIT_NONE ) - { - printf( "Ivy_ManCheck: The latch with ID \"%d\" does not have initial state.\n", pObj->Id ); - return 0; - } - pObj2 = Ivy_TableLookup( p, pObj ); - if ( pObj2 != pObj ) - printf( "Ivy_ManCheck: Latch with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); - continue; - } - // consider the AND node - if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) ) - { - printf( "Ivy_ManCheck: The AIG has internal node \"%d\" with a NULL fanin.\n", pObj->Id ); - return 0; - } - if ( Ivy_ObjFaninId0(pObj) >= Ivy_ObjFaninId1(pObj) ) - { - printf( "Ivy_ManCheck: The AIG has node \"%d\" with a wrong ordering of fanins.\n", pObj->Id ); - return 0; - } - if ( Ivy_ObjLevel(pObj) != Ivy_ObjLevelNew(pObj) ) - printf( "Ivy_ManCheck: Node with ID \"%d\" has level %d but should have level %d.\n", pObj->Id, Ivy_ObjLevel(pObj), Ivy_ObjLevelNew(pObj) ); - pObj2 = Ivy_TableLookup( p, pObj ); - if ( pObj2 != pObj ) - printf( "Ivy_ManCheck: Node with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); - if ( Ivy_ObjRefs(pObj) == 0 ) - printf( "Ivy_ManCheck: Node with ID \"%d\" has no fanouts.\n", pObj->Id ); - // check fanouts - if ( p->fFanout && Ivy_ObjRefs(pObj) != Ivy_ObjFanoutNum(p, pObj) ) - printf( "Ivy_ManCheck: Node with ID \"%d\" has mismatch between the number of fanouts and refs.\n", pObj->Id ); - } - // count the number of nodes in the table - if ( Ivy_TableCountEntries(p) != Ivy_ManAndNum(p) + Ivy_ManExorNum(p) + Ivy_ManLatchNum(p) ) - { - printf( "Ivy_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); - return 0; - } -// if ( !Ivy_ManCheckFanouts(p) ) -// return 0; - if ( !Ivy_ManIsAcyclic(p) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i, Counter = 0; - Ivy_ManForEachObj( p, pObj, i ) - if ( Ivy_ObjIsNode(pObj) ) - Counter += (Ivy_ObjRefs(pObj) == 0); - if ( Counter ) - printf( "Sequential AIG has %d dangling nodes.\n", Counter ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Verifies the fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCheckFanouts( Ivy_Man_t * p ) -{ - Vec_Ptr_t * vFanouts; - Ivy_Obj_t * pObj, * pFanout, * pFanin; - int i, k, RetValue = 1; - if ( !p->fFanout ) - return 1; - vFanouts = Vec_PtrAlloc( 100 ); - // make sure every fanin is a fanout - Ivy_ManForEachObj( p, pObj, i ) - { - pFanin = Ivy_ObjFanin0(pObj); - if ( pFanin == NULL ) - continue; - Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) - if ( pFanout == pObj ) - break; - if ( k == Vec_PtrSize(vFanouts) ) - { - printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); - RetValue = 0; - } - - pFanin = Ivy_ObjFanin1(pObj); - if ( pFanin == NULL ) - continue; - Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) - if ( pFanout == pObj ) - break; - if ( k == Vec_PtrSize(vFanouts) ) - { - printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); - RetValue = 0; - } - // check that the previous fanout has the same fanin - if ( pObj->pPrevFan0 ) - { - if ( Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && - Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) && - Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && - Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) ) - { - printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan0->Id ); - RetValue = 0; - } - } - // check that the previous fanout has the same fanin - if ( pObj->pPrevFan1 ) - { - if ( Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && - Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) && - Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && - Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) ) - { - printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan1->Id ); - RetValue = 0; - } - } - } - // make sure every fanout is a fanin - Ivy_ManForEachObj( p, pObj, i ) - { - Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, k ) - if ( Ivy_ObjFanin0(pFanout) != pObj && Ivy_ObjFanin1(pFanout) != pObj ) - { - printf( "Node %d is a fanout of node %d but the fanin is not there.\n", pFanout->Id, pObj->Id ); - RetValue = 0; - } - } - Vec_PtrFree( vFanouts ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Checks that each choice node has exactly one node with fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCheckChoices( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj, * pTemp; - int i; - Ivy_ManForEachObj( p->pHaig, pObj, i ) - { - if ( Ivy_ObjRefs(pObj) == 0 ) - continue; - // count the number of nodes in the loop - assert( !Ivy_IsComplement(pObj->pEquiv) ); - for ( pTemp = pObj->pEquiv; pTemp && pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - if ( Ivy_ObjRefs(pTemp) > 1 ) - printf( "Node %d has member %d in its equiv class with %d fanouts.\n", pObj->Id, pTemp->Id, Ivy_ObjRefs(pTemp) ); - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyCut.c b/src/temp/ivy/ivyCut.c deleted file mode 100644 index d918c96c..00000000 --- a/src/temp/ivy/ivyCut.c +++ /dev/null @@ -1,987 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Computes reconvergence driven sequential cut.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyCut.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Ivy_NodeCutHashValue( int NodeId ) { return 1 << (NodeId % 31); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Evaluate the cost of removing the node from the set of leaves.] - - Description [Returns the number of new leaves that will be brought in. - Returns large number if the node cannot be removed from the set of leaves.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_NodeGetLeafCostOne( Ivy_Man_t * p, int Leaf, Vec_Int_t * vInside ) -{ - Ivy_Obj_t * pNode; - int nLatches, FaninLeaf, Cost; - // make sure leaf is not a contant node - assert( Leaf > 0 ); - // get the node - pNode = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); - // cannot expand over the PI node - if ( Ivy_ObjIsPi(pNode) || Ivy_ObjIsConst1(pNode) ) - return 999; - // get the number of latches - nLatches = Ivy_LeafLat(Leaf) + Ivy_ObjIsLatch(pNode); - if ( nLatches > 15 ) - return 999; - // get the first fanin - FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); - Cost = FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); - // quit if this is the one fanin node - if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) - return Cost; - assert( Ivy_ObjIsNode(pNode) ); - // get the second fanin - FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); - Cost += FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); - return Cost; -} - -/**Function************************************************************* - - Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] - - Description [This procedure looks at the current leaves and tries to change - one leaf at a time in such a way that the cut grows as little as possible. - In evaluating the fanins, this procedure looks only at their immediate - predecessors (this is why it is called a one-level construction procedure).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManSeqFindCut_int( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSizeLimit ) -{ - Ivy_Obj_t * pNode; - int CostBest, CostCur, Leaf, LeafBest, Next, nLatches, i; - int LeavesBest[10]; - int Counter; - - // add random selection of the best fanin!!! - - // find the best fanin - CostBest = 99; - LeafBest = -1; - Counter = -1; -//printf( "Evaluating fanins of the cut:\n" ); - Vec_IntForEachEntry( vFront, Leaf, i ) - { - CostCur = Ivy_NodeGetLeafCostOne( p, Leaf, vInside ); -//printf( " Fanin %s has cost %d.\n", Ivy_ObjName(pNode), CostCur ); - if ( CostBest > CostCur ) - { - CostBest = CostCur; - LeafBest = Leaf; - LeavesBest[0] = Leaf; - Counter = 1; - } - else if ( CostBest == CostCur ) - LeavesBest[Counter++] = Leaf; - - if ( CostBest <= 1 ) // can be if ( CostBest <= 1 ) - break; - } - if ( CostBest == 99 ) - return 0; -// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); - - assert( CostBest < 3 ); - if ( Vec_IntSize(vFront) - 1 + CostBest > nSizeLimit ) - return 0; -// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); - - assert( Counter > 0 ); -printf( "%d", Counter ); - - LeafBest = LeavesBest[rand() % Counter]; - - // remove the node from the array - assert( LeafBest >= 0 ); - Vec_IntRemove( vFront, LeafBest ); -//printf( "Removing fanin %s.\n", Ivy_ObjName(pNode) ); - - // get the node and its latches - pNode = Ivy_ManObj( p, Ivy_LeafId(LeafBest) ); - nLatches = Ivy_LeafLat(LeafBest) + Ivy_ObjIsLatch(pNode); - assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ); - - // add the left child to the fanins - Next = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); - if ( Next && Vec_IntFind(vInside, Next) == -1 ) - { -//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); - Vec_IntPush( vFront, Next ); - Vec_IntPush( vInside, Next ); - } - - // quit if this is the one fanin node - if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) - return 1; - assert( Ivy_ObjIsNode(pNode) ); - - // add the right child to the fanins - Next = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); - if ( Next && Vec_IntFind(vInside, Next) == -1 ) - { -//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); - Vec_IntPush( vFront, Next ); - Vec_IntPush( vInside, Next ); - } - assert( Vec_IntSize(vFront) <= nSizeLimit ); - // keep doing this - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes one sequential cut of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ) -{ - assert( !Ivy_IsComplement(pRoot) ); - assert( Ivy_ObjIsNode(pRoot) ); - assert( Ivy_ObjFaninId0(pRoot) ); - assert( Ivy_ObjFaninId1(pRoot) ); - - // start the cut - Vec_IntClear( vFront ); - Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); - Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); - - // start the visited nodes - Vec_IntClear( vInside ); - Vec_IntPush( vInside, Ivy_LeafCreate(pRoot->Id, 0) ); - Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); - Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); - - // compute the cut - while ( Ivy_ManSeqFindCut_int( p, vFront, vInside, nSize ) ); - assert( Vec_IntSize(vFront) <= nSize ); -} - - - - - -/**Function************************************************************* - - Synopsis [Computing Boolean cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindBoolCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume, Ivy_Obj_t * pPivot ) -{ - int RetValue0, RetValue1; - if ( pObj == pPivot ) - { - Vec_PtrPushUnique( vLeaves, pObj ); - Vec_PtrPushUnique( vVolume, pObj ); - return 1; - } - if ( pObj->fMarkA ) - return 0; - -// assert( !Ivy_ObjIsCi(pObj) ); - if ( Ivy_ObjIsCi(pObj) ) - return 0; - - if ( Ivy_ObjIsBuf(pObj) ) - { - RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); - if ( !RetValue0 ) - return 0; - Vec_PtrPushUnique( vVolume, pObj ); - return 1; - } - assert( Ivy_ObjIsNode(pObj) ); - RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); - RetValue1 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin1(pObj), vLeaves, vVolume, pPivot ); - if ( !RetValue0 && !RetValue1 ) - return 0; - // add new leaves - if ( !RetValue0 ) - { - Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin0(pObj) ); - Vec_PtrPushUnique( vVolume, Ivy_ObjFanin0(pObj) ); - } - if ( !RetValue1 ) - { - Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin1(pObj) ); - Vec_PtrPushUnique( vVolume, Ivy_ObjFanin1(pObj) ); - } - Vec_PtrPushUnique( vVolume, pObj ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns the cost of one node (how many new nodes are added.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindBoolCutCost( Ivy_Obj_t * pObj ) -{ - int Cost; - // make sure the node is in the construction zone - assert( pObj->fMarkA == 1 ); - // cannot expand over the PI node - if ( Ivy_ObjIsCi(pObj) ) - return 999; - // always expand over the buffer - if ( Ivy_ObjIsBuf(pObj) ) - return !Ivy_ObjFanin0(pObj)->fMarkA; - // get the cost of the cone - Cost = (!Ivy_ObjFanin0(pObj)->fMarkA) + (!Ivy_ObjFanin1(pObj)->fMarkA); - // return the number of nodes to be added to the leaves if this node is removed - return Cost; -} - -/**Function************************************************************* - - Synopsis [Computing Boolean cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindBoolCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolume, Vec_Ptr_t * vLeaves ) -{ - Ivy_Obj_t * pObj, * pFaninC, * pFanin0, * pFanin1, * pPivot; - int RetValue, LevelLimit, Lev, k; - assert( !Ivy_IsComplement(pRoot) ); - // clear the frontier and collect the nodes - Vec_PtrClear( vFront ); - Vec_PtrClear( vVolume ); - if ( Ivy_ObjIsMuxType(pRoot) ) - pFaninC = Ivy_ObjRecognizeMux( pRoot, &pFanin0, &pFanin1 ); - else - { - pFaninC = NULL; - pFanin0 = Ivy_ObjFanin0(pRoot); - pFanin1 = Ivy_ObjFanin1(pRoot); - } - // start cone A - pFanin0->fMarkA = 1; - Vec_PtrPush( vFront, pFanin0 ); - Vec_PtrPush( vVolume, pFanin0 ); - // start cone B - pFanin1->fMarkB = 1; - Vec_PtrPush( vFront, pFanin1 ); - Vec_PtrPush( vVolume, pFanin1 ); - // iteratively expand until the common node (pPivot) is found or limit is reached - assert( Ivy_ObjLevel(pRoot) == Ivy_ObjLevelNew(pRoot) ); - pPivot = NULL; - LevelLimit = IVY_MAX( Ivy_ObjLevel(pRoot) - 10, 1 ); - for ( Lev = Ivy_ObjLevel(pRoot) - 1; Lev >= LevelLimit; Lev-- ) - { - while ( 1 ) - { - // find the next node to expand on this level - Vec_PtrForEachEntry( vFront, pObj, k ) - if ( (int)pObj->Level == Lev ) - break; - if ( k == Vec_PtrSize(vFront) ) - break; - assert( (int)pObj->Level <= Lev ); - assert( pObj->fMarkA ^ pObj->fMarkB ); - // remove the old node - Vec_PtrRemove( vFront, pObj ); - - // expand this node - pFanin0 = Ivy_ObjFanin0(pObj); - if ( !pFanin0->fMarkA && !pFanin0->fMarkB ) - { - Vec_PtrPush( vFront, pFanin0 ); - Vec_PtrPush( vVolume, pFanin0 ); - } - // mark the new nodes - if ( pObj->fMarkA ) - pFanin0->fMarkA = 1; - if ( pObj->fMarkB ) - pFanin0->fMarkB = 1; - - if ( Ivy_ObjIsBuf(pObj) ) - { - if ( pFanin0->fMarkA && pFanin0->fMarkB ) - { - pPivot = pFanin0; - break; - } - continue; - } - - // expand this node - pFanin1 = Ivy_ObjFanin1(pObj); - if ( !pFanin1->fMarkA && !pFanin1->fMarkB ) - { - Vec_PtrPush( vFront, pFanin1 ); - Vec_PtrPush( vVolume, pFanin1 ); - } - // mark the new nodes - if ( pObj->fMarkA ) - pFanin1->fMarkA = 1; - if ( pObj->fMarkB ) - pFanin1->fMarkB = 1; - - // consider if it is time to quit - if ( pFanin0->fMarkA && pFanin0->fMarkB ) - { - pPivot = pFanin0; - break; - } - if ( pFanin1->fMarkA && pFanin1->fMarkB ) - { - pPivot = pFanin1; - break; - } - } - if ( pPivot != NULL ) - break; - } - if ( pPivot == NULL ) - return 0; - // if the MUX control is defined, it should not be - if ( pFaninC && !pFaninC->fMarkA && !pFaninC->fMarkB ) - Vec_PtrPush( vFront, pFaninC ); - // clean the markings - Vec_PtrForEachEntry( vVolume, pObj, k ) - pObj->fMarkA = pObj->fMarkB = 0; - - // mark the nodes on the frontier (including the pivot) - Vec_PtrForEachEntry( vFront, pObj, k ) - pObj->fMarkA = 1; - // cut exists, collect all the nodes on the shortest path to the pivot - Vec_PtrClear( vLeaves ); - Vec_PtrClear( vVolume ); - RetValue = Ivy_ManFindBoolCut_rec( p, pRoot, vLeaves, vVolume, pPivot ); - assert( RetValue == 1 ); - // unmark the nodes on the frontier (including the pivot) - Vec_PtrForEachEntry( vFront, pObj, k ) - pObj->fMarkA = 0; - - // mark the nodes in the volume - Vec_PtrForEachEntry( vVolume, pObj, k ) - pObj->fMarkA = 1; - // expand the cut without increasing its size - while ( 1 ) - { - Vec_PtrForEachEntry( vLeaves, pObj, k ) - if ( Ivy_ManFindBoolCutCost(pObj) < 2 ) - break; - if ( k == Vec_PtrSize(vLeaves) ) - break; - // the node can be expanded - // remove the old node - Vec_PtrRemove( vLeaves, pObj ); - // expand this node - pFanin0 = Ivy_ObjFanin0(pObj); - if ( !pFanin0->fMarkA ) - { - pFanin0->fMarkA = 1; - Vec_PtrPush( vVolume, pFanin0 ); - Vec_PtrPush( vLeaves, pFanin0 ); - } - if ( Ivy_ObjIsBuf(pObj) ) - continue; - // expand this node - pFanin1 = Ivy_ObjFanin1(pObj); - if ( !pFanin1->fMarkA ) - { - pFanin1->fMarkA = 1; - Vec_PtrPush( vVolume, pFanin1 ); - Vec_PtrPush( vLeaves, pFanin1 ); - } - } - // unmark the nodes in the volume - Vec_PtrForEachEntry( vVolume, pObj, k ) - pObj->fMarkA = 0; - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManTestCutsBool( Ivy_Man_t * p ) -{ - Vec_Ptr_t * vFront, * vVolume, * vLeaves; - Ivy_Obj_t * pObj;//, * pTemp; - int i, RetValue;//, k; - vFront = Vec_PtrAlloc( 100 ); - vVolume = Vec_PtrAlloc( 100 ); - vLeaves = Vec_PtrAlloc( 100 ); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( !Ivy_ObjIsNode(pObj) ) - continue; - if ( Ivy_ObjIsMuxType(pObj) ) - { - printf( "m" ); - continue; - } - if ( Ivy_ObjIsExor(pObj) ) - printf( "x" ); - RetValue = Ivy_ManFindBoolCut( p, pObj, vFront, vVolume, vLeaves ); - if ( RetValue == 0 ) - printf( "- " ); - else - printf( "%d ", Vec_PtrSize(vLeaves) ); -/* - printf( "( " ); - Vec_PtrForEachEntry( vFront, pTemp, k ) - printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); - printf( ")\n" ); -*/ - } - printf( "\n" ); - Vec_PtrFree( vFront ); - Vec_PtrFree( vVolume ); - Vec_PtrFree( vLeaves ); -} - - - -/**Function************************************************************* - - Synopsis [Find the hash value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) -{ - int i; -// for ( i = 1; i < pCut->nSize; i++ ) -// assert( pCut->pArray[i-1] < pCut->pArray[i] ); - pCut->uHash = 0; - for ( i = 0; i < pCut->nSize; i++ ) - pCut->uHash |= (1 << (pCut->pArray[i] % 31)); - return pCut->uHash; -} - -/**Function************************************************************* - - Synopsis [Removes one node to the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld ) -{ - int i, k; - for ( i = k = 0; i < pCut->nSize; i++ ) - if ( pCut->pArray[i] != iOld ) - pCut->pArray[k++] = pCut->pArray[i]; - assert( k == pCut->nSize - 1 ); - pCut->nSize--; -} - -/**Function************************************************************* - - Synopsis [Adds one node to the cut.] - - Description [Returns 1 if the cuts is still okay.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew ) -{ - int i; - for ( i = 0; i < pCut->nSize; i++ ) - if ( pCut->pArray[i] == iNew ) - return 1; - // check if there is room - if ( pCut->nSize == pCut->nSizeMax ) - return 0; - // add the new one - for ( i = pCut->nSize - 1; i >= 0; i-- ) - if ( pCut->pArray[i] > iNew ) - pCut->pArray[i+1] = pCut->pArray[i]; - else - { - assert( pCut->pArray[i] < iNew ); - break; - } - pCut->pArray[i+1] = iNew; - pCut->nSize++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_NodeCutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) -{ - int i; - if ( pCut->nSize < pCut->nSizeMax ) - return 1; - for ( i = 0; i < pCut->nSize; i++ ) - if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Derives new cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_NodeCutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) -{ - unsigned uHash = 0; - int i, k; - assert( pCut->nSize > 0 ); - assert( IdNew0 < IdNew1 ); - for ( i = k = 0; i < pCut->nSize; i++ ) - { - if ( pCut->pArray[i] == IdOld ) - continue; - if ( IdNew0 <= pCut->pArray[i] ) - { - if ( IdNew0 < pCut->pArray[i] ) - { - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_NodeCutHashValue( IdNew0 ); - } - IdNew0 = 0x7FFFFFFF; - } - if ( IdNew1 <= pCut->pArray[i] ) - { - if ( IdNew1 < pCut->pArray[i] ) - { - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_NodeCutHashValue( IdNew1 ); - } - IdNew1 = 0x7FFFFFFF; - } - pCutNew->pArray[ k++ ] = pCut->pArray[i]; - uHash |= Ivy_NodeCutHashValue( pCut->pArray[i] ); - } - if ( IdNew0 < 0x7FFFFFFF ) - { - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_NodeCutHashValue( IdNew0 ); - } - if ( IdNew1 < 0x7FFFFFFF ) - { - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_NodeCutHashValue( IdNew1 ); - } - pCutNew->nSize = k; - pCutNew->uHash = uHash; - assert( pCutNew->nSize <= pCut->nSizeMax ); -// for ( i = 1; i < pCutNew->nSize; i++ ) -// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Check if the cut exists.] - - Description [Returns 1 if the cut exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) -{ - Ivy_Cut_t * pCut; - int i, k; - assert( pCutNew->uHash ); - // try to find the cut - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize ) - { - for ( k = 0; k < pCutNew->nSize; k++ ) - if ( pCut->pArray[k] != pCutNew->pArray[k] ) - break; - if ( k == pCutNew->nSize ) - return 1; - } - } - assert( pCutStore->nCuts < pCutStore->nCutsMax ); - // add the cut - pCut = pCutStore->pCuts + pCutStore->nCuts++; - *pCut = *pCutNew; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) -{ - int i, k; - for ( i = 0; i < pDom->nSize; i++ ) - { - for ( k = 0; k < pCut->nSize; k++ ) - if ( pDom->pArray[i] == pCut->pArray[k] ) - break; - if ( k == pCut->nSize ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Check if the cut exists.] - - Description [Returns 1 if the cut exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) -{ - Ivy_Cut_t * pCut; - int i, k; - assert( pCutNew->uHash ); - // try to find the cut - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - if ( pCut->nSize == pCutNew->nSize ) - { - if ( pCut->uHash == pCutNew->uHash ) - { - for ( k = 0; k < pCutNew->nSize; k++ ) - if ( pCut->pArray[k] != pCutNew->pArray[k] ) - break; - if ( k == pCutNew->nSize ) - return 1; - } - continue; - } - if ( pCut->nSize < pCutNew->nSize ) - { - // skip the non-contained cuts - if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) - continue; - // check containment seriously - if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) - return 1; - continue; - } - // check potential containment of other cut - - // skip the non-contained cuts - if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) - continue; - // check containment seriously - if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) - { - // remove the current cut -// --pCutStore->nCuts; -// for ( k = i; k < pCutStore->nCuts; k++ ) -// pCutStore->pCuts[k] = pCutStore->pCuts[k+1]; -// i--; - pCut->nSize = 0; - } - } - assert( pCutStore->nCuts < pCutStore->nCutsMax ); - // add the cut - pCut = pCutStore->pCuts + pCutStore->nCuts++; - *pCut = *pCutNew; - return 0; -} - -/**Function************************************************************* - - Synopsis [Print the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore ) -{ - Ivy_Cut_t * pCut; - int i, k; - for ( i = k = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - pCutStore->pCuts[k++] = *pCut; - } - pCutStore->nCuts = k; -} - -/**Function************************************************************* - - Synopsis [Print the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodePrintCut( Ivy_Cut_t * pCut ) -{ - int i; - assert( pCut->nSize > 0 ); - printf( "%d : {", pCut->nSize ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %d", pCut->pArray[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore ) -{ - int i; - printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); - for ( i = 0; i < pCutStore->nCuts; i++ ) - Ivy_NodePrintCut( pCutStore->pCuts + i ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_Obj_t * Ivy_ObjRealFanin( Ivy_Obj_t * pObj ) -{ - if ( !Ivy_ObjIsBuf(pObj) ) - return pObj; - return Ivy_ObjRealFanin( Ivy_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) -{ - static Ivy_Store_t CutStore, * pCutStore = &CutStore; - Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; - Ivy_Obj_t * pLeaf; - int i, k, iLeaf0, iLeaf1; - - assert( nLeaves <= IVY_CUT_INPUT ); - - // start the structure - pCutStore->nCuts = 0; - pCutStore->nCutsMax = IVY_CUT_LIMIT; - // start the trivial cut - pCutNew->uHash = 0; - pCutNew->nSize = 1; - pCutNew->nSizeMax = nLeaves; - pCutNew->pArray[0] = pObj->Id; - Ivy_NodeCutHash( pCutNew ); - // add the trivial cut - Ivy_NodeCutFindOrAdd( pCutStore, pCutNew ); - assert( pCutStore->nCuts == 1 ); - - // explore the cuts - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - // expand this cut - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - for ( k = 0; k < pCut->nSize; k++ ) - { - pLeaf = Ivy_ManObj( p, pCut->pArray[k] ); - if ( Ivy_ObjIsCi(pLeaf) ) - continue; -/* - *pCutNew = *pCut; - Ivy_NodeCutShrink( pCutNew, pLeaf->Id ); - if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) ) - continue; - if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) ) - continue; - Ivy_NodeCutHash( pCutNew ); -*/ - iLeaf0 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin0(pLeaf)) ); - iLeaf1 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin1(pLeaf)) ); - if ( !Ivy_NodeCutPrescreen( pCut, iLeaf0, iLeaf1 ) ) - continue; - if ( iLeaf0 > iLeaf1 ) - Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf1, iLeaf0 ); - else - Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ); - Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew ); - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - break; - } - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - break; - } - Ivy_NodeCompactCuts( pCutStore ); -// Ivy_NodePrintCuts( pCutStore ); - return pCutStore; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManTestCutsAll( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; - int clk = clock(); - nNodeTotal = nNodeOver = 0; - nCutsTotal = -Ivy_ManNodeNum(p); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( !Ivy_ObjIsNode(pObj) ) - continue; - nCutsCut = Ivy_NodeFindCutsAll( p, pObj, 5 )->nCuts; - nCutsTotal += nCutsCut; - nNodeOver += (nCutsCut == IVY_CUT_LIMIT); - nNodeTotal++; - } - printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", - nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); - PRT( "Time", clock() - clk ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyCutTrav.c b/src/temp/ivy/ivyCutTrav.c deleted file mode 100644 index ea57c9f5..00000000 --- a/src/temp/ivy/ivyCutTrav.c +++ /dev/null @@ -1,473 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyCutTrav.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ); -static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ); -static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes cuts for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, - Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts ) -{ - static Ivy_Store_t CutStore, * pCutStore = &CutStore; - Vec_Ptr_t * vCuts, * vCuts0, * vCuts1; - unsigned * pBitCut; - Ivy_Obj_t * pLeaf; - Ivy_Cut_t * pCut; - int i, k, nWords, nNodes; - - assert( nLeaves <= IVY_CUT_INPUT ); - - // find the given number of nodes in the TFI - Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront ); - nNodes = Vec_PtrSize(vNodes); -// assert( nNodes <= nNodeLimit ); - - // make sure vBitCuts has enough room - Vec_VecExpand( vBitCuts, nNodes-1 ); - Vec_VecClear( vBitCuts ); - - // prepare the memory manager - Vec_IntClear( vStore ); - Vec_IntGrow( vStore, 64000 ); - - // set elementary cuts for the leaves - nWords = Extra_BitWordNum( nNodes ); - Vec_PtrForEachEntry( vFront, pLeaf, i ) - { - assert( Ivy_ObjTravId(pLeaf) < nNodes ); - // get the new bitcut - pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); - // set it as the cut of this leaf - Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); - } - - // compute the cuts for each node - Vec_PtrForEachEntry( vNodes, pLeaf, i ) - { - // skip the leaves - vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) ); - if ( Vec_PtrSize(vCuts) > 0 ) - continue; - // add elementary cut - pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); - // set it as the cut of this leaf - Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); - // get the fanin cuts - vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) ); - vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) ); - assert( Vec_PtrSize(vCuts0) > 0 ); - assert( Vec_PtrSize(vCuts1) > 0 ); - // merge the cuts - Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore ); - } - - // start the structure - pCutStore->nCuts = 0; - pCutStore->nCutsMax = IVY_CUT_LIMIT; - // collect the cuts of the root node - vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) ); - Vec_PtrForEachEntry( vCuts, pBitCut, i ) - { - pCut = pCutStore->pCuts + pCutStore->nCuts++; - pCut->nSize = 0; - pCut->nSizeMax = nLeaves; - pCut->uHash = 0; - for ( k = 0; k < nNodes; k++ ) - if ( Extra_TruthHasBit(pBitCut, k) ) - pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( Vec_PtrEntry(vNodes, k) ); - assert( pCut->nSize <= nLeaves ); - if ( pCutStore->nCuts == pCutStore->nCutsMax ) - break; - } - - // clean the travIds - Vec_PtrForEachEntry( vNodes, pLeaf, i ) - pLeaf->TravId = 0; - return pCutStore; -} - -/**Function************************************************************* - - Synopsis [Creates elementary bit-cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) -{ - unsigned * pBitCut; - pBitCut = Vec_IntFetch( vStore, nWords ); - memset( pBitCut, 0, 4 * nWords ); - Extra_TruthSetBit( pBitCut, NodeId ); - return pBitCut; -} - -/**Function************************************************************* - - Synopsis [Compares the node by level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 ) -{ - Ivy_Obj_t * pObj1 = *ppObj1; - Ivy_Obj_t * pObj2 = *ppObj2; - if ( pObj1->Level < pObj2->Level ) - return -1; - if ( pObj1->Level > pObj2->Level ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Mark all nodes up to the given depth.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth ) -{ - if ( Ivy_ObjIsCi(pObj) || Depth == 0 ) - return; - Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 ); - Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 ); - pObj->fMarkA = 1; -} - -/**Function************************************************************* - - Synopsis [Collect the marked nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( !pObj->fMarkA ) - return; - Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes ); - Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pTemp, * pFanin; - int i, nNodes; - // mark nodes up to the given depth - Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 ); - // collect the marked nodes - Vec_PtrClear( vFront ); - Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront ); - // find the fanins that are not marked - Vec_PtrClear( vNodes ); - Vec_PtrForEachEntry( vFront, pTemp, i ) - { - pFanin = Ivy_ObjFanin0(pTemp); - if ( !pFanin->fMarkA ) - { - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - } - pFanin = Ivy_ObjFanin1(pTemp); - if ( !pFanin->fMarkA ) - { - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - } - } - // remember the number of nodes in the frontier - nNodes = Vec_PtrSize( vNodes ); - // add the remaining nodes - Vec_PtrForEachEntry( vFront, pTemp, i ) - Vec_PtrPush( vNodes, pTemp ); - // unmark the nodes - Vec_PtrForEachEntry( vNodes, pTemp, i ) - { - pTemp->fMarkA = 0; - pTemp->TravId = i; - } - // collect the frontier nodes - Vec_PtrClear( vFront ); - Vec_PtrForEachEntryStop( vNodes, pTemp, i, nNodes ) - Vec_PtrPush( vFront, pTemp ); -// printf( "%d ", Vec_PtrSize(vNodes) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pLeaf, * pPivot, * pFanin; - int LevelMax, i; - assert( Ivy_ObjIsNode(pObj) ); - // clear arrays - Vec_PtrClear( vNodes ); - Vec_PtrClear( vFront ); - // add the root - pObj->fMarkA = 1; - Vec_PtrPush( vNodes, pObj ); - Vec_PtrPush( vFront, pObj ); - // expand node with maximum level - LevelMax = pObj->Level; - do { - // get the node to expand - pPivot = NULL; - Vec_PtrForEachEntryReverse( vFront, pLeaf, i ) - { - if ( (int)pLeaf->Level == LevelMax ) - { - pPivot = pLeaf; - break; - } - } - // decrease level if we did not find the node - if ( pPivot == NULL ) - { - if ( --LevelMax == 0 ) - break; - continue; - } - // the node to expand is found - // remove it from frontier - Vec_PtrRemove( vFront, pPivot ); - // add fanins - pFanin = Ivy_ObjFanin0(pPivot); - if ( !pFanin->fMarkA ) - { - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - Vec_PtrPush( vFront, pFanin ); - } - pFanin = Ivy_ObjFanin1(pPivot); - if ( pFanin && !pFanin->fMarkA ) - { - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - Vec_PtrPush( vFront, pFanin ); - } - // quit if we collected enough nodes - } while ( Vec_PtrSize(vNodes) < nNodeLimit ); - - // sort nodes by level - Vec_PtrSort( vNodes, Ivy_CompareNodesByLevel ); - // make sure the nodes are ordered in the increasing number of levels - pFanin = Vec_PtrEntry( vNodes, 0 ); - pPivot = Vec_PtrEntryLast( vNodes ); - assert( pFanin->Level <= pPivot->Level ); - - // clean the marks and remember node numbers in the TravId - Vec_PtrForEachEntry( vNodes, pFanin, i ) - { - pFanin->fMarkA = 0; - pFanin->TravId = i; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords ) -{ - int w; - for ( w = nWords-1; w >= 0; w-- ) - pOut[w] = pIn0[w] | pIn1[w]; -} -static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords ) -{ - int w; - for ( w = nWords-1; w >= 0; w-- ) - if ( pIn1[w] & ~pIn2[w] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Merges two sets of bit-cuts at a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, - int nLeaves, int nWords, Vec_Int_t * vStore ) -{ - unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest; - int i, k, c, w, Counter; - // iterate through the cut pairs - Vec_PtrForEachEntry( vCuts0, pBitCut0, i ) - Vec_PtrForEachEntry( vCuts1, pBitCut1, k ) - { - // skip infeasible cuts - Counter = 0; - for ( w = 0; w < nWords; w++ ) - { - Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] ); - if ( Counter > nLeaves ) - break; - } - if ( Counter > nLeaves ) - continue; - // the new cut is feasible - create it - pBitCutTest = Vec_IntFetch( vStore, nWords ); - Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords ); - // filter contained cuts; try to find containing cut - w = 0; - Vec_PtrForEachEntry( vCuts, pBitCut, c ) - { - if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) ) - break; - if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) ) - continue; - Vec_PtrWriteEntry( vCuts, w++, pBitCut ); - } - if ( c != Vec_PtrSize(vCuts) ) - continue; - Vec_PtrShrink( vCuts, w ); - // add the cut - Vec_PtrPush( vCuts, pBitCutTest ); - } -} - -/**Function************************************************************* - - Synopsis [Compute the set of all cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManTestCutsTravAll( Ivy_Man_t * p ) -{ - Ivy_Store_t * pStore; - Ivy_Obj_t * pObj; - Vec_Ptr_t * vNodes, * vFront; - Vec_Int_t * vStore; - Vec_Vec_t * vBitCuts; - int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; - int clk = clock(); - - vNodes = Vec_PtrAlloc( 100 ); - vFront = Vec_PtrAlloc( 100 ); - vStore = Vec_IntAlloc( 100 ); - vBitCuts = Vec_VecAlloc( 100 ); - - nNodeTotal = nNodeOver = 0; - nCutsTotal = -Ivy_ManNodeNum(p); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( !Ivy_ObjIsNode(pObj) ) - continue; - pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts ); - nCutsCut = pStore->nCuts; - nCutsTotal += nCutsCut; - nNodeOver += (nCutsCut == IVY_CUT_LIMIT); - nNodeTotal++; - } - printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", - nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); - PRT( "Time", clock() - clk ); - - Vec_PtrFree( vNodes ); - Vec_PtrFree( vFront ); - Vec_IntFree( vStore ); - Vec_VecFree( vBitCuts ); - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyDfs.c b/src/temp/ivy/ivyDfs.c deleted file mode 100644 index c27cba31..00000000 --- a/src/temp/ivy/ivyDfs.c +++ /dev/null @@ -1,493 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [DFS collection procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManDfs_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Int_t * vNodes ) -{ - if ( Ivy_ObjIsMarkA(pObj) ) - return; - Ivy_ObjSetMarkA(pObj); - if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) - { - if ( p->pHaig == NULL && pObj->pEquiv ) - Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); - return; - } -//printf( "visiting node %d\n", pObj->Id ); -/* - if ( pObj->Id == 87 || pObj->Id == 90 ) - { - int y = 0; - } -*/ - assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); - Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); - if ( !Ivy_ObjIsBuf(pObj) ) - Ivy_ManDfs_rec( p, Ivy_ObjFanin1(pObj), vNodes ); - if ( p->pHaig == NULL && pObj->pEquiv ) - Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); - Vec_IntPush( vNodes, pObj->Id ); - -//printf( "adding node %d with fanins %d and %d and equiv %d (refs = %d)\n", -// pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id, -// pObj->pEquiv? Ivy_Regular(pObj->pEquiv)->Id: -1, Ivy_ObjRefs(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ) -{ - Vec_Int_t * vNodes; - Ivy_Obj_t * pObj; - int i; - assert( Ivy_ManLatchNum(p) == 0 ); - // make sure the nodes are not marked - Ivy_ManForEachObj( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - // collect the nodes - vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); - Ivy_ManForEachPo( p, pObj, i ) - Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); - // unmark the collected nodes -// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) -// Ivy_ObjClearMarkA(pObj); - Ivy_ManForEachObj( p, pObj, i ) - Ivy_ObjClearMarkA(pObj); - // make sure network does not have dangling nodes - assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ) -{ - Vec_Int_t * vNodes, * vLatches; - Ivy_Obj_t * pObj; - int i; -// assert( Ivy_ManLatchNum(p) > 0 ); - // make sure the nodes are not marked - Ivy_ManForEachObj( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - // collect the latches - vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); - Ivy_ManForEachLatch( p, pObj, i ) - Vec_IntPush( vLatches, pObj->Id ); - // collect the nodes - vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); - Ivy_ManForEachPo( p, pObj, i ) - Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); - // unmark the collected nodes -// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) -// Ivy_ObjClearMarkA(pObj); - Ivy_ManForEachObj( p, pObj, i ) - Ivy_ObjClearMarkA(pObj); - // make sure network does not have dangling nodes -// assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); - -// temporary!!! - - if ( pvLatches == NULL ) - Vec_IntFree( vLatches ); - else - *pvLatches = vLatches; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects nodes in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone ) -{ - if ( pObj->fMarkA ) - return; - if ( Ivy_ObjIsBuf(pObj) ) - { - Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); - Vec_PtrPush( vCone, pObj ); - return; - } - assert( Ivy_ObjIsNode(pObj) ); - Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); - Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone ); - Vec_PtrPushUnique( vCone, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects nodes in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) -{ - Ivy_Obj_t * pTemp; - int i; - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsNode(pObj) ); - // mark the nodes - Vec_PtrForEachEntry( vFront, pTemp, i ) - Ivy_Regular(pTemp)->fMarkA = 1; - assert( pObj->fMarkA == 0 ); - // collect the cone - Vec_PtrClear( vCone ); - Ivy_ManCollectCone_rec( pObj, vCone ); - // unmark the nodes - Vec_PtrForEachEntry( vFront, pTemp, i ) - Ivy_Regular(pTemp)->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Returns the nodes by level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ) -{ - Vec_Vec_t * vNodes; - Ivy_Obj_t * pObj; - int i; - vNodes = Vec_VecAlloc( 100 ); - Ivy_ManForEachObj( p, pObj, i ) - { - assert( !Ivy_ObjIsBuf(pObj) ); - if ( Ivy_ObjIsNode(pObj) ) - Vec_VecPush( vNodes, pObj->Level, pObj ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes required levels for each node.] - - Description [Assumes topological ordering of the nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - Vec_Int_t * vLevelsR; - Vec_Vec_t * vNodes; - int i, k, Level, LevelMax; - assert( p->vRequired == NULL ); - // start the required times - vLevelsR = Vec_IntStart( Ivy_ManObjIdMax(p) + 1 ); - // iterate through the nodes in the reverse order - vNodes = Ivy_ManLevelize( p ); - Vec_VecForEachEntryReverseReverse( vNodes, pObj, i, k ) - { - Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj); - if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level ) - Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level ); - if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level ) - Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level ); - } - Vec_VecFree( vNodes ); - // convert it into the required times - LevelMax = Ivy_ManLevels( p ); -//printf( "max %5d\n",LevelMax ); - Ivy_ManForEachObj( p, pObj, i ) - { - Level = Vec_IntEntry( vLevelsR, pObj->Id ); - Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level ); -//printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level ); - } - p->vRequired = vLevelsR; - return vLevelsR; -} - -/**Function************************************************************* - - Synopsis [Recursively detects combinational loops.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManIsAcyclic_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - // skip the node if it is already visited - if ( Ivy_ObjIsTravIdPrevious(p, pObj) ) - return 1; - // check if the node is part of the combinational loop - if ( Ivy_ObjIsTravIdCurrent(p, pObj) ) - { - fprintf( stdout, "Manager contains combinational loop!\n" ); - fprintf( stdout, "Node \"%d\" is encountered twice on the following path:\n", Ivy_ObjId(pObj) ); - fprintf( stdout, " %d", Ivy_ObjId(pObj) ); - return 0; - } - // mark this node as a node on the current path - Ivy_ObjSetTravIdCurrent( p, pObj ); - // explore equivalent nodes if pObj is the main node - if ( p->pHaig == NULL && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) - { - Ivy_Obj_t * pTemp; - assert( !Ivy_IsComplement(pObj->pEquiv) ); - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { - // traverse the fanin's cone searching for the loop - if ( !Ivy_ManIsAcyclic_rec(p, pTemp) ) - { - // return as soon as the loop is detected - fprintf( stdout, " -> (%d", Ivy_ObjId(pObj) ); - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - fprintf( stdout, " %d", Ivy_ObjId(pTemp) ); - fprintf( stdout, ")" ); - return 0; - } - } - } - // quite if it is a CI node - if ( Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) - { - // mark this node as a visited node - Ivy_ObjSetTravIdPrevious( p, pObj ); - return 1; - } - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); - // traverse the fanin's cone searching for the loop - if ( !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) - { - // return as soon as the loop is detected - fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); - return 0; - } - // traverse the fanin's cone searching for the loop - if ( Ivy_ObjIsNode(pObj) && !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin1(pObj)) ) - { - // return as soon as the loop is detected - fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); - return 0; - } - // mark this node as a visited node - Ivy_ObjSetTravIdPrevious( p, pObj ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Detects combinational loops.] - - Description [This procedure is based on the idea suggested by Donald Chai. - As we traverse the network and visit the nodes, we need to distinquish - three types of nodes: (1) those that are visited for the first time, - (2) those that have been visited in this traversal but are currently not - on the traversal path, (3) those that have been visited and are currently - on the travesal path. When the node of type (3) is encountered, it means - that there is a combinational loop. To mark the three types of nodes, - two new values of the traversal IDs are used.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManIsAcyclic( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int fAcyclic, i; - // set the traversal ID for this DFS ordering - Ivy_ManIncrementTravId( p ); - Ivy_ManIncrementTravId( p ); - // pObj->TravId == pNet->nTravIds means "pObj is on the path" - // pObj->TravId == pNet->nTravIds - 1 means "pObj is visited but is not on the path" - // pObj->TravId < pNet->nTravIds - 1 means "pObj is not visited" - // traverse the network to detect cycles - fAcyclic = 1; - Ivy_ManForEachCo( p, pObj, i ) - { - // traverse the output logic cone - if ( fAcyclic = Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) - continue; - // stop as soon as the first loop is detected - fprintf( stdout, " (cone of %s \"%d\")\n", Ivy_ObjIsLatch(pObj)? "latch" : "PO", Ivy_ObjId(pObj) ); - break; - } - return fAcyclic; -} - -/**Function************************************************************* - - Synopsis [Sets the levels of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManSetLevels_rec( Ivy_Obj_t * pObj, int fHaig ) -{ - // quit if the node is visited - if ( Ivy_ObjIsMarkA(pObj) ) - return pObj->Level; - Ivy_ObjSetMarkA(pObj); - // quit if this is a CI - if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) - return 0; - assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); - // get levels of the fanins - Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); - if ( !Ivy_ObjIsBuf(pObj) ) - Ivy_ManSetLevels_rec( Ivy_ObjFanin1(pObj), fHaig ); - // get level of the node - if ( Ivy_ObjIsBuf(pObj) ) - pObj->Level = 1 + Ivy_ObjFanin0(pObj)->Level; - else if ( Ivy_ObjIsNode(pObj) ) - pObj->Level = Ivy_ObjLevelNew( pObj ); - else assert( 0 ); - // get level of other choices - if ( fHaig && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) - { - Ivy_Obj_t * pTemp; - unsigned LevelMax = pObj->Level; - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { - Ivy_ManSetLevels_rec( pTemp, fHaig ); - LevelMax = IVY_MAX( LevelMax, pTemp->Level ); - } - // get this level - pObj->Level = LevelMax; - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - pTemp->Level = LevelMax; - } - return pObj->Level; -} - -/**Function************************************************************* - - Synopsis [Sets the levels of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ) -{ - Ivy_Obj_t * pObj; - int i, LevelMax; - // check if CIs have choices - if ( fHaig ) - { - Ivy_ManForEachCi( p, pObj, i ) - if ( pObj->pEquiv ) - printf( "CI %d has a choice, which will not be visualized.\n", pObj->Id ); - } - // clean the levels - Ivy_ManForEachObj( p, pObj, i ) - pObj->Level = 0; - // compute the levels - LevelMax = 0; - Ivy_ManForEachCo( p, pObj, i ) - { - Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); - LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); - } - // compute levels of nodes without fanout - Ivy_ManForEachObj( p, pObj, i ) - if ( (Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj)) && Ivy_ObjRefs(pObj) == 0 ) - { - Ivy_ManSetLevels_rec( pObj, fHaig ); - LevelMax = IVY_MAX( LevelMax, (int)pObj->Level ); - } - // clean the marks - Ivy_ManForEachObj( p, pObj, i ) - Ivy_ObjClearMarkA(pObj); - return LevelMax; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyDsd.c b/src/temp/ivy/ivyDsd.c deleted file mode 100644 index 3b8a2e68..00000000 --- a/src/temp/ivy/ivyDsd.c +++ /dev/null @@ -1,819 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyDsd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Disjoint-support decomposition.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyDsd.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// decomposition types -typedef enum { - IVY_DEC_PI, // 0: var - IVY_DEC_CONST1, // 1: CONST1 - IVY_DEC_BUF, // 2: BUF - IVY_DEC_AND, // 3: AND - IVY_DEC_EXOR, // 4: EXOR - IVY_DEC_MUX, // 5: MUX - IVY_DEC_MAJ, // 6: MAJ - IVY_DEC_PRIME // 7: undecomposable -} Ivy_DecType_t; - -typedef struct Ivy_Dec_t_ Ivy_Dec_t; -struct Ivy_Dec_t_ -{ - unsigned Type : 4; // the node type (PI, CONST1, AND, EXOR, MUX, PRIME) - unsigned fCompl : 1; // shows if node is complemented (root node only) - unsigned nFans : 3; // the number of fanins - unsigned Fan0 : 4; // fanin 0 - unsigned Fan1 : 4; // fanin 1 - unsigned Fan2 : 4; // fanin 2 - unsigned Fan3 : 4; // fanin 3 - unsigned Fan4 : 4; // fanin 4 - unsigned Fan5 : 4; // fanin 5 -}; - -static inline int Ivy_DecToInt( Ivy_Dec_t Node ) { return *((int *)&Node); } -static inline Ivy_Dec_t Ivy_IntToDec( int Node ) { return *((Ivy_Dec_t *)&Node); } -static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *((int *)pNode) = 0; } - - -static unsigned s_Masks[6][2] = { - { 0x55555555, 0xAAAAAAAA }, - { 0x33333333, 0xCCCCCCCC }, - { 0x0F0F0F0F, 0xF0F0F0F0 }, - { 0x00FF00FF, 0xFF00FF00 }, - { 0x0000FFFF, 0xFFFF0000 }, - { 0x00000000, 0xFFFFFFFF } -}; - -static inline int Ivy_TruthWordCountOnes( unsigned uWord ) -{ - uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); - uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); - uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); - uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); - return (uWord & 0x0000FFFF) + (uWord>>16); -} - -static inline int Ivy_TruthCofactorIsConst( unsigned uTruth, int Var, int Cof, int Const ) -{ - if ( Const == 0 ) - return (uTruth & s_Masks[Var][Cof]) == 0; - else - return (uTruth & s_Masks[Var][Cof]) == s_Masks[Var][Cof]; -} - -static inline int Ivy_TruthCofactorIsOne( unsigned uTruth, int Var ) -{ - return (uTruth & s_Masks[Var][0]) == 0; -} - -static inline unsigned Ivy_TruthCofactor( unsigned uTruth, int Var ) -{ - unsigned uCofactor = uTruth & s_Masks[Var >> 1][(Var & 1) == 0]; - int Shift = (1 << (Var >> 1)); - if ( Var & 1 ) - return uCofactor | (uCofactor << Shift); - return uCofactor | (uCofactor >> Shift); -} - -static inline unsigned Ivy_TruthCofactor2( unsigned uTruth, int Var0, int Var1 ) -{ - return Ivy_TruthCofactor( Ivy_TruthCofactor(uTruth, Var0), Var1 ); -} - -// returns 1 if the truth table depends on this var (var is regular interger var) -static inline int Ivy_TruthDepends( unsigned uTruth, int Var ) -{ - return Ivy_TruthCofactor(uTruth, Var << 1) != Ivy_TruthCofactor(uTruth, (Var << 1) | 1); -} - -static inline void Ivy_DecSetVar( Ivy_Dec_t * pNode, int iNum, unsigned Var ) -{ - assert( iNum >= 0 && iNum <= 5 ); - switch( iNum ) - { - case 0: pNode->Fan0 = Var; break; - case 1: pNode->Fan1 = Var; break; - case 2: pNode->Fan2 = Var; break; - case 3: pNode->Fan3 = Var; break; - case 4: pNode->Fan4 = Var; break; - case 5: pNode->Fan5 = Var; break; - } -} - -static inline unsigned Ivy_DecGetVar( Ivy_Dec_t * pNode, int iNum ) -{ - assert( iNum >= 0 && iNum <= 5 ); - switch( iNum ) - { - case 0: return pNode->Fan0; - case 1: return pNode->Fan1; - case 2: return pNode->Fan2; - case 3: return pNode->Fan3; - case 4: return pNode->Fan4; - case 5: return pNode->Fan5; - } - return ~0; -} - -static int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ); -static int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ); - -//int nTruthDsd; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes DSD of truth table of 5 variables or less.] - - Description [Returns 1 if the function is a constant or is fully - DSD decomposable using AND/EXOR/MUX gates.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ) -{ - Ivy_Dec_t Node; - int i, RetValue; - // set the PI variables - Vec_IntClear( vTree ); - for ( i = 0; i < 5; i++ ) - Vec_IntPush( vTree, 0 ); - // check if it is a constant - if ( uTruth == 0 || ~uTruth == 0 ) - { - Ivy_DecClear( &Node ); - Node.Type = IVY_DEC_CONST1; - Node.fCompl = (uTruth == 0); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - return 1; - } - // perform the decomposition - RetValue = Ivy_TruthDecompose_rec( uTruth, vTree ); - if ( RetValue == -1 ) - return 0; - // get the topmost node - if ( (RetValue >> 1) < 5 ) - { // add buffer - Ivy_DecClear( &Node ); - Node.Type = IVY_DEC_BUF; - Node.fCompl = (RetValue & 1); - Node.Fan0 = ((RetValue >> 1) << 1); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - } - else if ( RetValue & 1 ) - { // check if the topmost node has to be complemented - Node = Ivy_IntToDec( Vec_IntPop(vTree) ); - assert( Node.fCompl == 0 ); - Node.fCompl = (RetValue & 1); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - } - if ( uTruth != Ivy_TruthDsdCompute(vTree) ) - printf( "Verification failed.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes DSD of truth table.] - - Description [Returns the number of topmost decomposition node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ) -{ - Ivy_Dec_t Node; - int Supp[5], Vars0[5], Vars1[5], Vars2[5], * pVars; - int nSupp, Count0, Count1, Count2, nVars, RetValue, fCompl, i; - unsigned uTruthCof, uCof0, uCof1; - - // get constant confactors - Count0 = Count1 = Count2 = nSupp = 0; - for ( i = 0; i < 5; i++ ) - { - if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 0) ) - Vars0[Count0++] = (i << 1) | 0; - else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 0) ) - Vars0[Count0++] = (i << 1) | 1; - else if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 1) ) - Vars1[Count1++] = (i << 1) | 0; - else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 1) ) - Vars1[Count1++] = (i << 1) | 1; - else - { - uCof0 = Ivy_TruthCofactor( uTruth, (i << 1) | 1 ); - uCof1 = Ivy_TruthCofactor( uTruth, (i << 1) | 0 ); - if ( uCof0 == ~uCof1 ) - Vars2[Count2++] = (i << 1) | 0; - else if ( uCof0 != uCof1 ) - Supp[nSupp++] = i; - } - } - assert( Count0 == 0 || Count1 == 0 ); - assert( Count0 == 0 || Count2 == 0 ); - assert( Count1 == 0 || Count2 == 0 ); - - // consider the case of a single variable - if ( Count0 == 1 && nSupp == 0 ) - return Vars0[0]; - - // consider more complex decompositions - if ( Count0 == 0 && Count1 == 0 && Count2 == 0 ) - return Ivy_TruthRecognizeMuxMaj( uTruth, Supp, nSupp, vTree ); - - // extract the nodes - Ivy_DecClear( &Node ); - if ( Count0 > 0 ) - nVars = Count0, pVars = Vars0, Node.Type = IVY_DEC_AND, fCompl = 0; - else if ( Count1 > 0 ) - nVars = Count1, pVars = Vars1, Node.Type = IVY_DEC_AND, fCompl = 1, uTruth = ~uTruth; - else if ( Count2 > 0 ) - nVars = Count2, pVars = Vars2, Node.Type = IVY_DEC_EXOR, fCompl = 0; - else - assert( 0 ); - Node.nFans = nVars+(nSupp>0); - - // compute cofactor - uTruthCof = uTruth; - for ( i = 0; i < nVars; i++ ) - { - uTruthCof = Ivy_TruthCofactor( uTruthCof, pVars[i] ); - Ivy_DecSetVar( &Node, i, pVars[i] ); - } - - if ( Node.Type == IVY_DEC_EXOR ) - fCompl ^= ((Node.nFans & 1) == 0); - - if ( nSupp > 0 ) - { - assert( uTruthCof != 0 && ~uTruthCof != 0 ); - // call recursively - RetValue = Ivy_TruthDecompose_rec( uTruthCof, vTree ); - // quit if non-decomposable - if ( RetValue == -1 ) - return -1; - // remove the complement from the child if the node is EXOR - if ( Node.Type == IVY_DEC_EXOR && (RetValue & 1) ) - { - fCompl ^= 1; - RetValue ^= 1; - } - // set the new decomposition - Ivy_DecSetVar( &Node, nVars, RetValue ); - } - else if ( Node.Type == IVY_DEC_EXOR ) - fCompl ^= (uTruthCof == 0); - - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - return ((Vec_IntSize(vTree)-1) << 1) | fCompl; -} - -/**Function************************************************************* - - Synopsis [Returns a non-negative number if the truth table is a MUX.] - - Description [If the truth table is a MUX, returns the variable as follows: - first, control variable; second, positive cofactor; third, negative cofactor.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ) -{ - Ivy_Dec_t Node; - int i, k, RetValue0, RetValue1; - unsigned uCof0, uCof1, Num; - char Count[3]; - assert( nSupp >= 3 ); - // start the node - Ivy_DecClear( &Node ); - Node.Type = IVY_DEC_MUX; - Node.nFans = 3; - // try each of the variables - for ( i = 0; i < nSupp; i++ ) - { - // get the cofactors with respect to these variables - uCof0 = Ivy_TruthCofactor( uTruth, (pSupp[i] << 1) | 1 ); - uCof1 = Ivy_TruthCofactor( uTruth, pSupp[i] << 1 ); - // go through all other variables and make sure - // each of them belongs to the support of one cofactor - for ( k = 0; k < nSupp; k++ ) - { - if ( k == i ) - continue; - if ( Ivy_TruthDepends(uCof0, pSupp[k]) && Ivy_TruthDepends(uCof1, pSupp[k]) ) - break; - } - if ( k < nSupp ) - continue; - // MUX decomposition exists - RetValue0 = Ivy_TruthDecompose_rec( uCof0, vTree ); - if ( RetValue0 == -1 ) - break; - RetValue1 = Ivy_TruthDecompose_rec( uCof1, vTree ); - if ( RetValue1 == -1 ) - break; - // both of them exist; create the node - Ivy_DecSetVar( &Node, 0, pSupp[i] << 1 ); - Ivy_DecSetVar( &Node, 1, RetValue1 ); - Ivy_DecSetVar( &Node, 2, RetValue0 ); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - return ((Vec_IntSize(vTree)-1) << 1) | 0; - } - // check majority gate - if ( nSupp > 3 ) - return -1; - if ( Ivy_TruthWordCountOnes(uTruth) != 16 ) - return -1; - // this is a majority gate; determine polarity - Node.Type = IVY_DEC_MAJ; - Count[0] = Count[1] = Count[2] = 0; - for ( i = 0; i < 8; i++ ) - { - Num = 0; - for ( k = 0; k < 3; k++ ) - if ( i & (1 << k) ) - Num |= (1 << pSupp[k]); - assert( Num < 32 ); - if ( (uTruth & (1 << Num)) == 0 ) - continue; - for ( k = 0; k < 3; k++ ) - if ( i & (1 << k) ) - Count[k]++; - } - assert( Count[0] == 1 || Count[0] == 3 ); - assert( Count[1] == 1 || Count[1] == 3 ); - assert( Count[2] == 1 || Count[2] == 3 ); - Ivy_DecSetVar( &Node, 0, (pSupp[0] << 1)|(Count[0] == 1) ); - Ivy_DecSetVar( &Node, 1, (pSupp[1] << 1)|(Count[1] == 1) ); - Ivy_DecSetVar( &Node, 2, (pSupp[2] << 1)|(Count[2] == 1) ); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - return ((Vec_IntSize(vTree)-1) << 1) | 0; -} - - -/**Function************************************************************* - - Synopsis [Computes truth table of decomposition tree for verification.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_TruthDsdCompute_rec( int iNode, Vec_Int_t * vTree ) -{ - unsigned uTruthChild, uTruthTotal; - int Var, i; - // get the node - Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); - // compute the node function - if ( Node.Type == IVY_DEC_CONST1 ) - return s_Masks[5][ !Node.fCompl ]; - if ( Node.Type == IVY_DEC_PI ) - return s_Masks[iNode][ !Node.fCompl ]; - if ( Node.Type == IVY_DEC_BUF ) - { - uTruthTotal = Ivy_TruthDsdCompute_rec( Node.Fan0 >> 1, vTree ); - return Node.fCompl? ~uTruthTotal : uTruthTotal; - } - if ( Node.Type == IVY_DEC_AND ) - { - uTruthTotal = s_Masks[5][1]; - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - uTruthChild = Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); - uTruthTotal = (Var & 1)? uTruthTotal & ~uTruthChild : uTruthTotal & uTruthChild; - } - return Node.fCompl? ~uTruthTotal : uTruthTotal; - } - if ( Node.Type == IVY_DEC_EXOR ) - { - uTruthTotal = 0; - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - uTruthTotal ^= Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); - assert( (Var & 1) == 0 ); - } - return Node.fCompl? ~uTruthTotal : uTruthTotal; - } - assert( Node.fCompl == 0 ); - if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) - { - unsigned uTruthChildC, uTruthChild1, uTruthChild0; - int VarC, Var1, Var0; - VarC = Ivy_DecGetVar( &Node, 0 ); - Var1 = Ivy_DecGetVar( &Node, 1 ); - Var0 = Ivy_DecGetVar( &Node, 2 ); - uTruthChildC = Ivy_TruthDsdCompute_rec( VarC >> 1, vTree ); - uTruthChild1 = Ivy_TruthDsdCompute_rec( Var1 >> 1, vTree ); - uTruthChild0 = Ivy_TruthDsdCompute_rec( Var0 >> 1, vTree ); - assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); - uTruthChildC = (VarC & 1)? ~uTruthChildC : uTruthChildC; - uTruthChild1 = (Var1 & 1)? ~uTruthChild1 : uTruthChild1; - uTruthChild0 = (Var0 & 1)? ~uTruthChild0 : uTruthChild0; - if ( Node.Type == IVY_DEC_MUX ) - return (uTruthChildC & uTruthChild1) | (~uTruthChildC & uTruthChild0); - else - return (uTruthChildC & uTruthChild1) | (uTruthChildC & uTruthChild0) | (uTruthChild1 & uTruthChild0); - } - assert( 0 ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Computes truth table of decomposition tree for verification.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ) -{ - return Ivy_TruthDsdCompute_rec( Vec_IntSize(vTree)-1, vTree ); -} - -/**Function************************************************************* - - Synopsis [Prints the decomposition tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthDsdPrint_rec( FILE * pFile, int iNode, Vec_Int_t * vTree ) -{ - int Var, i; - // get the node - Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); - // compute the node function - if ( Node.Type == IVY_DEC_CONST1 ) - fprintf( pFile, "Const1%s", (Node.fCompl? "\'" : "") ); - else if ( Node.Type == IVY_DEC_PI ) - fprintf( pFile, "%c%s", 'a' + iNode, (Node.fCompl? "\'" : "") ); - else if ( Node.Type == IVY_DEC_BUF ) - { - Ivy_TruthDsdPrint_rec( pFile, Node.Fan0 >> 1, vTree ); - fprintf( pFile, "%s", (Node.fCompl? "\'" : "") ); - } - else if ( Node.Type == IVY_DEC_AND ) - { - fprintf( pFile, "AND(" ); - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); - fprintf( pFile, "%s", (Var & 1)? "\'" : "" ); - if ( i != (int)Node.nFans-1 ) - fprintf( pFile, "," ); - } - fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); - } - else if ( Node.Type == IVY_DEC_EXOR ) - { - fprintf( pFile, "EXOR(" ); - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); - if ( i != (int)Node.nFans-1 ) - fprintf( pFile, "," ); - assert( (Var & 1) == 0 ); - } - fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); - } - else if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) - { - int VarC, Var1, Var0; - assert( Node.fCompl == 0 ); - VarC = Ivy_DecGetVar( &Node, 0 ); - Var1 = Ivy_DecGetVar( &Node, 1 ); - Var0 = Ivy_DecGetVar( &Node, 2 ); - fprintf( pFile, "%s", (Node.Type == IVY_DEC_MUX)? "MUX(" : "MAJ(" ); - Ivy_TruthDsdPrint_rec( pFile, VarC >> 1, vTree ); - fprintf( pFile, "%s", (VarC & 1)? "\'" : "" ); - fprintf( pFile, "," ); - Ivy_TruthDsdPrint_rec( pFile, Var1 >> 1, vTree ); - fprintf( pFile, "%s", (Var1 & 1)? "\'" : "" ); - fprintf( pFile, "," ); - Ivy_TruthDsdPrint_rec( pFile, Var0 >> 1, vTree ); - fprintf( pFile, "%s", (Var0 & 1)? "\'" : "" ); - fprintf( pFile, ")" ); - } - else assert( 0 ); -} - - -/**Function************************************************************* - - Synopsis [Prints the decomposition tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ) -{ - fprintf( pFile, "F = " ); - Ivy_TruthDsdPrint_rec( pFile, Vec_IntSize(vTree)-1, vTree ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Implement DSD in the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ManDsdConstruct_rec( Ivy_Man_t * p, Vec_Int_t * vFront, int iNode, Vec_Int_t * vTree ) -{ - Ivy_Obj_t * pResult, * pChild, * pNodes[16]; - int Var, i; - // get the node - Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); - // compute the node function - if ( Node.Type == IVY_DEC_CONST1 ) - return Ivy_NotCond( Ivy_ManConst1(p), Node.fCompl ); - if ( Node.Type == IVY_DEC_PI ) - { - pResult = Ivy_ManObj( p, Vec_IntEntry(vFront, iNode) ); - return Ivy_NotCond( pResult, Node.fCompl ); - } - if ( Node.Type == IVY_DEC_BUF ) - { - pResult = Ivy_ManDsdConstruct_rec( p, vFront, Node.Fan0 >> 1, vTree ); - return Ivy_NotCond( pResult, Node.fCompl ); - } - if ( Node.Type == IVY_DEC_AND || Node.Type == IVY_DEC_EXOR ) - { - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - assert( Node.Type == IVY_DEC_AND || (Var & 1) == 0 ); - pChild = Ivy_ManDsdConstruct_rec( p, vFront, Var >> 1, vTree ); - pChild = Ivy_NotCond( pChild, (Var & 1) ); - pNodes[i] = pChild; - } - -// Ivy_MultiEval( pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); - - pResult = Ivy_Multi( p, pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); - return Ivy_NotCond( pResult, Node.fCompl ); - } - assert( Node.fCompl == 0 ); - if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) - { - int VarC, Var1, Var0; - VarC = Ivy_DecGetVar( &Node, 0 ); - Var1 = Ivy_DecGetVar( &Node, 1 ); - Var0 = Ivy_DecGetVar( &Node, 2 ); - pNodes[0] = Ivy_ManDsdConstruct_rec( p, vFront, VarC >> 1, vTree ); - pNodes[1] = Ivy_ManDsdConstruct_rec( p, vFront, Var1 >> 1, vTree ); - pNodes[2] = Ivy_ManDsdConstruct_rec( p, vFront, Var0 >> 1, vTree ); - assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); - pNodes[0] = Ivy_NotCond( pNodes[0], (VarC & 1) ); - pNodes[1] = Ivy_NotCond( pNodes[1], (Var1 & 1) ); - pNodes[2] = Ivy_NotCond( pNodes[2], (Var0 & 1) ); - if ( Node.Type == IVY_DEC_MUX ) - return Ivy_Mux( p, pNodes[0], pNodes[1], pNodes[2] ); - else - return Ivy_Maj( p, pNodes[0], pNodes[1], pNodes[2] ); - } - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Implement DSD in the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ) -{ - int Entry, i; - // implement latches on the frontier (TEMPORARY!!!) - Vec_IntForEachEntry( vFront, Entry, i ) - Vec_IntWriteEntry( vFront, i, Ivy_LeafId(Entry) ); - // recursively construct the tree - return Ivy_ManDsdConstruct_rec( p, vFront, Vec_IntSize(vTree)-1, vTree ); -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthDsdComputePrint( unsigned uTruth ) -{ - static Vec_Int_t * vTree = NULL; - if ( vTree == NULL ) - vTree = Vec_IntAlloc( 12 ); - if ( Ivy_TruthDsd( uTruth, vTree ) ) - Ivy_TruthDsdPrint( stdout, vTree ); - else - printf( "Undecomposable\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthTestOne( unsigned uTruth ) -{ - static int Counter = 0; - static Vec_Int_t * vTree = NULL; - // decompose - if ( vTree == NULL ) - vTree = Vec_IntAlloc( 12 ); - - if ( !Ivy_TruthDsd( uTruth, vTree ) ) - { -// printf( "Undecomposable\n" ); - } - else - { -// nTruthDsd++; - printf( "%5d : ", Counter++ ); - Extra_PrintBinary( stdout, &uTruth, 32 ); - printf( " " ); - Ivy_TruthDsdPrint( stdout, vTree ); - if ( uTruth != Ivy_TruthDsdCompute(vTree) ) - printf( "Verification failed.\n" ); - } -// Vec_IntFree( vTree ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthTest() -{ - FILE * pFile; - char Buffer[100]; - unsigned uTruth; - int i; - - pFile = fopen( "npn4.txt", "r" ); - for ( i = 0; i < 222; i++ ) -// pFile = fopen( "npn5.txt", "r" ); -// for ( i = 0; i < 616126; i++ ) - { - fscanf( pFile, "%s", Buffer ); - Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); -// Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); - uTruth |= (uTruth << 16); -// uTruth = ~uTruth; - Ivy_TruthTestOne( uTruth ); - } - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthTest3() -{ - FILE * pFile; - char Buffer[100]; - unsigned uTruth; - int i; - - pFile = fopen( "npn3.txt", "r" ); - for ( i = 0; i < 14; i++ ) - { - fscanf( pFile, "%s", Buffer ); - Extra_ReadHexadecimal( &uTruth, Buffer+2, 3 ); - uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24); - Ivy_TruthTestOne( uTruth ); - } - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthTest5() -{ - FILE * pFile; - char Buffer[100]; - unsigned uTruth; - int i; - -// pFile = fopen( "npn4.txt", "r" ); -// for ( i = 0; i < 222; i++ ) - pFile = fopen( "npn5.txt", "r" ); - for ( i = 0; i < 616126; i++ ) - { - fscanf( pFile, "%s", Buffer ); -// Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); - Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); -// uTruth |= (uTruth << 16); -// uTruth = ~uTruth; - Ivy_TruthTestOne( uTruth ); - } - fclose( pFile ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyFanout.c b/src/temp/ivy/ivyFanout.c deleted file mode 100644 index 3930186a..00000000 --- a/src/temp/ivy/ivyFanout.c +++ /dev/null @@ -1,309 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyFanout.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Representation of the fanouts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyFanout.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// getting hold of the next fanout of the node -static inline Ivy_Obj_t * Ivy_ObjNextFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - if ( pFanout == NULL ) - return NULL; - if ( Ivy_ObjFanin0(pFanout) == pObj ) - return pFanout->pNextFan0; - assert( Ivy_ObjFanin1(pFanout) == pObj ); - return pFanout->pNextFan1; -} - -// getting hold of the previous fanout of the node -static inline Ivy_Obj_t * Ivy_ObjPrevFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - if ( pFanout == NULL ) - return NULL; - if ( Ivy_ObjFanin0(pFanout) == pObj ) - return pFanout->pPrevFan0; - assert( Ivy_ObjFanin1(pFanout) == pObj ); - return pFanout->pPrevFan1; -} - -// getting hold of the place where the next fanout will be attached -static inline Ivy_Obj_t ** Ivy_ObjNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - if ( Ivy_ObjFanin0(pFanout) == pObj ) - return &pFanout->pNextFan0; - assert( Ivy_ObjFanin1(pFanout) == pObj ); - return &pFanout->pNextFan1; -} - -// getting hold of the place where the next fanout will be attached -static inline Ivy_Obj_t ** Ivy_ObjPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - if ( Ivy_ObjFanin0(pFanout) == pObj ) - return &pFanout->pPrevFan0; - assert( Ivy_ObjFanin1(pFanout) == pObj ); - return &pFanout->pPrevFan1; -} - -// getting hold of the place where the next fanout will be attached -static inline Ivy_Obj_t ** Ivy_ObjPrevNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - Ivy_Obj_t * pTemp; - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - pTemp = Ivy_ObjPrevFanout(pObj, pFanout); - if ( pTemp == NULL ) - return &pObj->pFanout; - if ( Ivy_ObjFanin0(pTemp) == pObj ) - return &pTemp->pNextFan0; - assert( Ivy_ObjFanin1(pTemp) == pObj ); - return &pTemp->pNextFan1; -} - -// getting hold of the place where the next fanout will be attached -static inline Ivy_Obj_t ** Ivy_ObjNextPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - Ivy_Obj_t * pTemp; - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - pTemp = Ivy_ObjNextFanout(pObj, pFanout); - if ( pTemp == NULL ) - return NULL; - if ( Ivy_ObjFanin0(pTemp) == pObj ) - return &pTemp->pPrevFan0; - assert( Ivy_ObjFanin1(pTemp) == pObj ); - return &pTemp->pPrevFan1; -} - -// iterator through the fanouts of the node -#define Ivy_ObjForEachFanoutInt( pObj, pFanout ) \ - for ( pFanout = (pObj)->pFanout; pFanout; \ - pFanout = Ivy_ObjNextFanout(pObj, pFanout) ) - -// safe iterator through the fanouts of the node -#define Ivy_ObjForEachFanoutIntSafe( pObj, pFanout, pFanout2 ) \ - for ( pFanout = (pObj)->pFanout, \ - pFanout2 = Ivy_ObjNextFanout(pObj, pFanout); \ - pFanout; \ - pFanout = pFanout2, \ - pFanout2 = Ivy_ObjNextFanout(pObj, pFanout) ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the fanout representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStartFanout( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - assert( !p->fFanout ); - p->fFanout = 1; - Ivy_ManForEachObj( p, pObj, i ) - { - if ( Ivy_ObjFanin0(pObj) ) - Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); - if ( Ivy_ObjFanin1(pObj) ) - Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Stops the fanout representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStopFanout( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - assert( p->fFanout ); - p->fFanout = 0; - Ivy_ManForEachObj( p, pObj, i ) - pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; -} - -/**Function************************************************************* - - Synopsis [Add the fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) -{ - assert( p->fFanout ); - if ( pFanin->pFanout ) - { - *Ivy_ObjNextFanoutPlace(pFanin, pFanout) = pFanin->pFanout; - *Ivy_ObjPrevFanoutPlace(pFanin, pFanin->pFanout) = pFanout; - } - pFanin->pFanout = pFanout; -} - -/**Function************************************************************* - - Synopsis [Removes the fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) -{ - Ivy_Obj_t ** ppPlace1, ** ppPlace2, ** ppPlaceN; - assert( pFanin->pFanout != NULL ); - - ppPlace1 = Ivy_ObjNextFanoutPlace(pFanin, pFanout); - ppPlaceN = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanout); - assert( *ppPlaceN == pFanout ); - if ( ppPlaceN ) - *ppPlaceN = *ppPlace1; - - ppPlace2 = Ivy_ObjPrevFanoutPlace(pFanin, pFanout); - ppPlaceN = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanout); - assert( ppPlaceN == NULL || *ppPlaceN == pFanout ); - if ( ppPlaceN ) - *ppPlaceN = *ppPlace2; - - *ppPlace1 = NULL; - *ppPlace2 = NULL; -} - -/**Function************************************************************* - - Synopsis [Replaces the fanout of pOld to be pFanoutNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ) -{ - Ivy_Obj_t ** ppPlace; - ppPlace = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanoutOld); - assert( *ppPlace == pFanoutOld ); - if ( ppPlace ) - *ppPlace = pFanoutNew; - ppPlace = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanoutOld); - assert( ppPlace == NULL || *ppPlace == pFanoutOld ); - if ( ppPlace ) - *ppPlace = pFanoutNew; - // assuming that pFanoutNew already points to the next fanout -} - -/**Function************************************************************* - - Synopsis [Starts iteration through the fanouts.] - - Description [Copies the currently available fanouts into the array.] - - SideEffects [Can be used while the fanouts are being removed.] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ) -{ - Ivy_Obj_t * pFanout; - assert( p->fFanout ); - assert( !Ivy_IsComplement(pObj) ); - Vec_PtrClear( vArray ); - Ivy_ObjForEachFanoutInt( pObj, pFanout ) - Vec_PtrPush( vArray, pFanout ); -} - -/**Function************************************************************* - - Synopsis [Reads one fanout.] - - Description [Returns fanout if there is only one fanout.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - return pObj->pFanout; -} - -/**Function************************************************************* - - Synopsis [Reads one fanout.] - - Description [Returns fanout if there is only one fanout.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanout; - int Counter = 0; - Ivy_ObjForEachFanoutInt( pObj, pFanout ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyFastMap.c b/src/temp/ivy/ivyFastMap.c deleted file mode 100644 index c4a043f2..00000000 --- a/src/temp/ivy/ivyFastMap.c +++ /dev/null @@ -1,1593 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyFastMap.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Fast FPGA mapping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IVY_INFINITY 10000 - -typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t; -struct Ivy_SuppMan_t_ -{ - int nLimit; // the limit on the number of inputs - int nObjs; // the number of entries - int nSize; // size of each entry in bytes - char * pMem; // memory allocated - Vec_Vec_t * vLuts; // the array of nodes used in the mapping -}; - -typedef struct Ivy_Supp_t_ Ivy_Supp_t; -struct Ivy_Supp_t_ -{ - char nSize; // the number of support nodes - char fMark; // multipurpose mask - char fMark2; // multipurpose mask - char fMark3; // multipurpose mask - int nRefs; // the number of references - short Delay; // the delay of the node - short DelayR; // the reverse delay of the node - int pArray[0]; // the support nodes -}; - -static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize); -} -static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp; - pSupp = Ivy_ObjSupp( pAig, pObj ); - pSupp->fMark = 0; - pSupp->Delay = 0; - pSupp->nSize = 1; - pSupp->pArray[0] = pObj->Id; - return pSupp; -} - -static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr ); -static int Ivy_FastMapDelay( Ivy_Man_t * pAig ); -static int Ivy_FastMapArea( Ivy_Man_t * pAig ); -static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); -static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); -static int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ); -static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ); -static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ); -static int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); -static int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); -static int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); -static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ); -static int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); -static int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); - - -extern int s_MappingTime; -extern int s_MappingMem; - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs fast K-LUT mapping of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ) -{ - Ivy_SuppMan_t * pMan; - Ivy_Obj_t * pObj; - int i, Delay, Area, clk, clkTotal = clock(); - // start the memory for supports - pMan = ALLOC( Ivy_SuppMan_t, 1 ); - memset( pMan, 0, sizeof(Ivy_SuppMan_t) ); - pMan->nLimit = nLimit; - pMan->nObjs = Ivy_ManObjIdMax(pAig) + 1; - pMan->nSize = sizeof(Ivy_Supp_t) + nLimit * sizeof(int); - pMan->pMem = (char *)malloc( pMan->nObjs * pMan->nSize ); - memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize ); - pMan->vLuts = Vec_VecAlloc( 100 ); - pAig->pData = pMan; -clk = clock(); - // set the PI mapping - Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) ); - Ivy_ManForEachPi( pAig, pObj, i ) - Ivy_ObjSuppStart( pAig, pObj ); - // iterate through all nodes in the topological order - Ivy_ManForEachNode( pAig, pObj, i ) - Ivy_FastMapNode( pAig, pObj, nLimit ); - // find the best arrival time and area - Delay = Ivy_FastMapDelay( pAig ); - Area = Ivy_FastMapArea(pAig); - if ( fVerbose ) - Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Delay oriented mapping: " ); - -// 2-1-2 (doing 2-1-2-1-2 improves 0.5%) - - if ( fRecovery ) - { -clk = clock(); - Ivy_FastMapRequired( pAig, Delay, 0 ); - // remap the nodes - Ivy_FastMapRecover( pAig, nLimit ); - Delay = Ivy_FastMapDelay( pAig ); - Area = Ivy_FastMapArea(pAig); - if ( fVerbose ) - Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " ); - -clk = clock(); - Ivy_FastMapRequired( pAig, Delay, 0 ); - // iterate through all nodes in the topological order - Ivy_ManForEachNode( pAig, pObj, i ) - Ivy_FastMapNodeArea( pAig, pObj, nLimit ); - Delay = Ivy_FastMapDelay( pAig ); - Area = Ivy_FastMapArea(pAig); - if ( fVerbose ) - Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 1 : " ); - -clk = clock(); - Ivy_FastMapRequired( pAig, Delay, 0 ); - // remap the nodes - Ivy_FastMapRecover( pAig, nLimit ); - Delay = Ivy_FastMapDelay( pAig ); - Area = Ivy_FastMapArea(pAig); - if ( fVerbose ) - Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " ); - } - - - s_MappingTime = clock() - clkTotal; - s_MappingMem = pMan->nObjs * pMan->nSize; -/* - { - Vec_Ptr_t * vNodes; - vNodes = Vec_PtrAlloc( 100 ); - Vec_VecForEachEntry( pMan->vLuts, pObj, i, k ) - Vec_PtrPush( vNodes, pObj ); - Ivy_ManShow( pAig, 0, vNodes ); - Vec_PtrFree( vNodes ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Cleans memory used for decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapStop( Ivy_Man_t * pAig ) -{ - Ivy_SuppMan_t * p = pAig->pData; - Vec_VecFree( p->vLuts ); - free( p->pMem ); - free( p ); - pAig->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Prints statistics.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr ) -{ - printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area ); - PRT( "Time", Time ); -} - -/**Function************************************************************* - - Synopsis [Computes delay after LUT mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapDelay( Ivy_Man_t * pAig ) -{ - Ivy_Supp_t * pSupp; - Ivy_Obj_t * pObj; - int i, DelayMax = 0; - Ivy_ManForEachPo( pAig, pObj, i ) - { - pObj = Ivy_ObjFanin0(pObj); - if ( !Ivy_ObjIsNode(pObj) ) - continue; - pSupp = Ivy_ObjSupp( pAig, pObj ); - if ( DelayMax < pSupp->Delay ) - DelayMax = pSupp->Delay; - } - return DelayMax; -} - -/**Function************************************************************* - - Synopsis [Computes area after mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts ) -{ - Ivy_Supp_t * pSupp; - int i, Counter; - pSupp = Ivy_ObjSupp( pAig, pObj ); - // skip visited nodes and PIs - if ( pSupp->fMark || pSupp->nSize == 1 ) - return 0; - pSupp->fMark = 1; - // compute the area of this node - Counter = 0; - for ( i = 0; i < pSupp->nSize; i++ ) - Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts ); - // add the node to the array of LUTs - Vec_VecPush( vLuts, pSupp->Delay, pObj ); - return 1 + Counter; -} - -/**Function************************************************************* - - Synopsis [Computes area after mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapArea( Ivy_Man_t * pAig ) -{ - Vec_Vec_t * vLuts; - Ivy_Obj_t * pObj; - int i, Counter = 0; - // get the array to store the nodes - vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; - Vec_VecClear( vLuts ); - // explore starting from each node - Ivy_ManForEachPo( pAig, pObj, i ) - Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts ); - // clean the marks - Ivy_ManForEachNode( pAig, pObj, i ) - Ivy_ObjSupp( pAig, pObj )->fMark = 0; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj ) -{ - return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1; -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj ) -{ - return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2; -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntSelectSort( int * pArray, int nSize ) -{ - int temp, i, j, best_i; - for ( i = 0; i < nSize-1; i++ ) - { - best_i = i; - for ( j = i+1; j < nSize; j++ ) - if ( pArray[j] < pArray[best_i] ) - best_i = j; - temp = pArray[i]; - pArray[i] = pArray[best_i]; - pArray[best_i] = temp; - } -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntRemoveDup( int * pArray, int nSize ) -{ - int i, k; - if ( nSize < 2 ) - return nSize; - for ( i = k = 1; i < nSize; i++ ) - if ( pArray[i] != pArray[i-1] ) - pArray[k++] = pArray[i]; - return k; -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) -{ - static int Store[32], StoreSize; - static char Supp0[16], Supp1[16]; - static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; - static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; - Ivy_Obj_t * pFanin0, * pFanin1; - Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; - int RetValue, DelayOld; - assert( nLimit <= 32 ); - assert( Ivy_ObjIsNode(pObj) ); - // get the fanins - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - // get the supports - pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); - pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->fMark == 0 ); - // get the old delay of the node - DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); - assert( DelayOld <= pSupp->DelayR ); - // copy the current cut - memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); - StoreSize = pSupp->nSize; - // get the fanin support - if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR ) - { - pSupp0 = pTemp0; - pSupp0->nSize = 1; - pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); - } - // get the fanin support - if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR ) - { - pSupp1 = pTemp1; - pSupp1->nSize = 1; - pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); - } - // merge the cuts - if ( pSupp0->nSize < pSupp1->nSize ) - RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); - else - RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); - if ( !RetValue ) - { - pSupp->nSize = 2; - pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); - pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); - } - // check the resulting delay - pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); - if ( pSupp->Delay > pSupp->DelayR ) - { - pSupp->nSize = StoreSize; - memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); - pSupp->Delay = DelayOld; - } -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) -{ - static int Store[32], StoreSize; - static char Supp0[16], Supp1[16]; - static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; - static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; - Ivy_Obj_t * pFanin0, * pFanin1; - Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; - int RetValue, DelayOld, RefsOld; - int AreaBef, AreaAft; - assert( nLimit <= 32 ); - assert( Ivy_ObjIsNode(pObj) ); - // get the fanins - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - // get the supports - pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); - pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->fMark == 0 ); - - // get the area - if ( pSupp->nRefs == 0 ) - AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); - else - AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); -// if ( AreaBef == 1 ) -// return; - - // deref the cut if the node is refed - if ( pSupp->nRefs != 0 ) - Ivy_FastMapNodeDeref( pAig, pObj ); - - // get the old delay of the node - DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); - assert( DelayOld <= pSupp->DelayR ); - // copy the current cut - memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); - StoreSize = pSupp->nSize; - // get the fanin support - if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR ) -// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results - { - pSupp0 = pTemp0; - pSupp0->nSize = 1; - pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); - } - // get the fanin support - if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR ) -// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR ) - { - pSupp1 = pTemp1; - pSupp1->nSize = 1; - pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); - } - // merge the cuts - if ( pSupp0->nSize < pSupp1->nSize ) - RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); - else - RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); - if ( !RetValue ) - { - pSupp->nSize = 2; - pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); - pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); - } - - // check the resulting delay - pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); - - RefsOld = pSupp->nRefs; pSupp->nRefs = 0; - AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); - pSupp->nRefs = RefsOld; - - if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) -// if ( pSupp->Delay > pSupp->DelayR ) - { - pSupp->nSize = StoreSize; - memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); - pSupp->Delay = DelayOld; -// printf( "-" ); - } -// else -// printf( "+" ); - - if ( pSupp->nRefs != 0 ) - Ivy_FastMapNodeRef( pAig, pObj ); -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) -{ - Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; - int fFaninParam = 2; - int RetValue; - assert( Ivy_ObjIsNode(pObj) ); - // get the supports - pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); - pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - pSupp->fMark = 0; - // get the delays - if ( pSupp0->Delay == pSupp1->Delay ) - pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay; - else if ( pSupp0->Delay > pSupp1->Delay ) - { - pSupp->Delay = pSupp0->Delay; - pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); - pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); - } - else // if ( pSupp0->Delay < pSupp1->Delay ) - { - pSupp->Delay = pSupp1->Delay; - pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); - pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); - } - // merge the cuts - if ( pSupp0->nSize < pSupp1->nSize ) - RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); - else - RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); - if ( !RetValue ) - { - pSupp->Delay++; - if ( fFaninParam == 2 ) - { - pSupp->nSize = 2; - pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); - pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); - } - else if ( fFaninParam == 3 ) - { - Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - pSupp->nSize = 0; - // process the first fanin - if ( Ivy_ObjIsNodeInt1(pFanin0) ) - { - pFaninA = Ivy_ObjFanin0(pFanin0); - pFaninB = Ivy_ObjFanin1(pFanin0); - if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); - else - { - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); - } - } - else - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); - // process the second fanin - if ( Ivy_ObjIsNodeInt1(pFanin1) ) - { - pFaninA = Ivy_ObjFanin0(pFanin1); - pFaninB = Ivy_ObjFanin1(pFanin1); - if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); - else - { - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); - } - } - else - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); - // sort the fanins - Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); - pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); - assert( pSupp->pArray[0] < pSupp->pArray[1] ); - } - else if ( fFaninParam == 4 ) - { - Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - pSupp->nSize = 0; - // consider the case when exactly one of them is internal - if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) ) - { - pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); - pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); - if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit ) - { - pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 ); - pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); - pSupp1->pArray[0] = Ivy_ObjId(pFanin1); - // merge the cuts - RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); - assert( RetValue ); - assert( pSupp->nSize > 1 ); - return; - } - if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit ) - { - pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 ); - pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); - pSupp0->pArray[0] = Ivy_ObjId(pFanin0); - // merge the cuts - RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); - assert( RetValue ); - assert( pSupp->nSize > 1 ); - return; - } - } - // process the first fanin - if ( Ivy_ObjIsNodeInt1(pFanin0) ) - { - pFaninA = Ivy_ObjFanin0(pFanin0); - pFaninB = Ivy_ObjFanin1(pFanin0); - if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); - else - { - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); - } - } - else - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); - // process the second fanin - if ( Ivy_ObjIsNodeInt1(pFanin1) ) - { - pFaninA = Ivy_ObjFanin0(pFanin1); - pFaninB = Ivy_ObjFanin1(pFanin1); - if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); - else - { - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); - } - } - else - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); - // sort the fanins - Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); - pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); - assert( pSupp->pArray[0] < pSupp->pArray[1] ); - assert( pSupp->nSize > 1 ); - } - } - assert( pSupp->Delay > 0 ); -} - -/**Function************************************************************* - - Synopsis [Merges two supports] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ) -{ - int i, k, c; - assert( pSupp0->nSize >= pSupp1->nSize ); - // the case of the largest cut sizes - if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit ) - { - for ( i = 0; i < pSupp0->nSize; i++ ) - if ( pSupp0->pArray[i] != pSupp1->pArray[i] ) - return 0; - for ( i = 0; i < pSupp0->nSize; i++ ) - pSupp->pArray[i] = pSupp0->pArray[i]; - pSupp->nSize = pSupp0->nSize; - return 1; - } - // the case when one of the cuts is the largest - if ( pSupp0->nSize == nLimit ) - { - for ( i = 0; i < pSupp1->nSize; i++ ) - { - for ( k = pSupp0->nSize - 1; k >= 0; k-- ) - if ( pSupp0->pArray[k] == pSupp1->pArray[i] ) - break; - if ( k == -1 ) // did not find - return 0; - } - for ( i = 0; i < pSupp0->nSize; i++ ) - pSupp->pArray[i] = pSupp0->pArray[i]; - pSupp->nSize = pSupp0->nSize; - return 1; - } - - // compare two cuts with different numbers - i = k = 0; - for ( c = 0; c < nLimit; c++ ) - { - if ( k == pSupp1->nSize ) - { - if ( i == pSupp0->nSize ) - { - pSupp->nSize = c; - return 1; - } - pSupp->pArray[c] = pSupp0->pArray[i++]; - continue; - } - if ( i == pSupp0->nSize ) - { - if ( k == pSupp1->nSize ) - { - pSupp->nSize = c; - return 1; - } - pSupp->pArray[c] = pSupp1->pArray[k++]; - continue; - } - if ( pSupp0->pArray[i] < pSupp1->pArray[k] ) - { - pSupp->pArray[c] = pSupp0->pArray[i++]; - continue; - } - if ( pSupp0->pArray[i] > pSupp1->pArray[k] ) - { - pSupp->pArray[c] = pSupp1->pArray[k++]; - continue; - } - pSupp->pArray[c] = pSupp0->pArray[i++]; - k++; - } - if ( i < pSupp0->nSize || k < pSupp1->nSize ) - return 0; - pSupp->nSize = c; - return 1; -} - -/**Function************************************************************* - - Synopsis [Creates integer vector with the support of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ) -{ - Ivy_Supp_t * pSupp; - pSupp = Ivy_ObjSupp( pAig, pObj ); - vLeaves->nCap = 8; - vLeaves->nSize = pSupp->nSize; - vLeaves->pArray = pSupp->pArray; -} - -/**Function************************************************************* - - Synopsis [Sets the required times of the intermediate nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR ) -{ - Ivy_Supp_t * pSupp; - pSupp = Ivy_ObjSupp( pAig, pObj ); - if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) ) - return; - Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR ); - Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR ); -// assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY ); - pSupp->DelayR = DelayR; -} - -/**Function************************************************************* - - Synopsis [Computes the required times for each node.] - - Description [Sets reference counters for each node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ) -{ - Vec_Vec_t * vLuts; - Vec_Ptr_t * vNodes; - Ivy_Obj_t * pObj; - Ivy_Supp_t * pSupp, * pSuppF; - int i, k, c; - // clean the required times - Ivy_ManForEachPi( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - pSupp->DelayR = IVY_INFINITY; - pSupp->nRefs = 0; - } - Ivy_ManForEachNode( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - pSupp->DelayR = IVY_INFINITY; - pSupp->nRefs = 0; - } - // set the required times of the POs - Ivy_ManForEachPo( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); - pSupp->DelayR = Delay; - pSupp->nRefs++; - } - // get the levelized nodes used in the mapping - vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; - // propagate the required times - Vec_VecForEachLevelReverse( vLuts, vNodes, i ) - Vec_PtrForEachEntry( vNodes, pObj, k ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nRefs > 0 ); - for ( c = 0; c < pSupp->nSize; c++ ) - { - pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); - pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 ); - pSuppF->nRefs++; - } - } -/* - // print out some of the required times - Ivy_ManForEachPi( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - printf( "%d ", pSupp->DelayR ); - } - printf( "\n" ); -*/ - - if ( fSetInter ) - { - // set the required times of the intermediate nodes - Vec_VecForEachLevelReverse( vLuts, vNodes, i ) - Vec_PtrForEachEntry( vNodes, pObj, k ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR ); - } - // make sure that all required times are assigned - Ivy_ManForEachNode( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->DelayR < IVY_INFINITY ); - } - } -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ) -{ - Vec_Ptr_t * vFront, * vFrontOld; - Ivy_Obj_t * pObj; - int i; - vFront = Vec_PtrAlloc( nLimit ); - vFrontOld = Vec_PtrAlloc( nLimit ); - Ivy_ManCleanTravId( pAig ); - // iterate through all nodes in the topological order - Ivy_ManForEachNode( pAig, pObj, i ) - Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld ); - Vec_PtrFree( vFrontOld ); - Vec_PtrFree( vFront ); -} - -/**Function************************************************************* - - Synopsis [Computes the delay of the cut rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp, * pSuppF; - int c, Delay = 0; - pSupp = Ivy_ObjSupp( pAig, pObj ); - for ( c = 0; c < pSupp->nSize; c++ ) - { - pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); - Delay = IVY_MAX( Delay, pSuppF->Delay ); - } - return 1 + Delay; -} - - -/**function************************************************************* - - synopsis [References the cut.] - - description [This procedure is similar to the procedure NodeReclaim.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp, * pSuppF; - Ivy_Obj_t * pNodeChild; - int aArea, i; - // start the area of this cut - aArea = 1; - // go through the children - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nSize > 1 ); - for ( i = 0; i < pSupp->nSize; i++ ) - { - pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); - pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); - assert( pSuppF->nRefs >= 0 ); - if ( pSuppF->nRefs++ > 0 ) - continue; - if ( pSuppF->nSize == 1 ) - continue; - aArea += Ivy_FastMapNodeRef( pAig, pNodeChild ); - } - return aArea; -} - -/**function************************************************************* - - synopsis [Dereferences the cut.] - - description [This procedure is similar to the procedure NodeRecusiveDeref.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp, * pSuppF; - Ivy_Obj_t * pNodeChild; - int aArea, i; - // start the area of this cut - aArea = 1; - // go through the children - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nSize > 1 ); - for ( i = 0; i < pSupp->nSize; i++ ) - { - pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); - pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); - assert( pSuppF->nRefs > 0 ); - if ( --pSuppF->nRefs > 0 ) - continue; - if ( pSuppF->nSize == 1 ) - continue; - aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild ); - } - return aArea; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp; - int aResult, aResult2; - if ( Ivy_ObjIsCi(pObj) ) - return 0; - assert( Ivy_ObjIsNode(pObj) ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nRefs > 0 ); - aResult = Ivy_FastMapNodeDeref( pAig, pObj ); - aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); - assert( aResult == aResult2 ); - return aResult; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp; - int aResult, aResult2; - if ( Ivy_ObjIsCi(pObj) ) - return 0; - assert( Ivy_ObjIsNode(pObj) ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nRefs == 0 ); - aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); - aResult = Ivy_FastMapNodeDeref( pAig, pObj ); - assert( aResult == aResult2 ); - return aResult; -} - - - - -/**Function************************************************************* - - Synopsis [Counts the number of nodes with no external fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront ) -{ - Ivy_Supp_t * pSuppF; - Ivy_Obj_t * pFanin; - int i, Counter = 0; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - pSuppF = Ivy_ObjSupp( pAig, pFanin ); - if ( pSuppF->nRefs == 0 ) - Counter++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) ) - return; - assert( Ivy_ObjIsNode(pObj) ); - Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) ); - Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) ); - Ivy_ObjSetTravIdCurrent(pAig, pObj); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the number of fanins will grow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanin0, * pFanin1; - assert( Ivy_ObjIsNode(pObj) ); - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1); -} - -/**Function************************************************************* - - Synopsis [Returns the increase in the number of fanins with no external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSuppF; - Ivy_Obj_t * pFanin; - int Counter = 0; - assert( Ivy_ObjIsNode(pObj) ); - // check if the node has external refs - pSuppF = Ivy_ObjSupp( pAig, pObj ); - if ( pSuppF->nRefs == 0 ) - Counter--; - // increment the number of fanins without external refs - pFanin = Ivy_ObjFanin0(pObj); - pSuppF = Ivy_ObjSupp( pAig, pFanin ); - if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) - Counter++; - // increment the number of fanins without external refs - pFanin = Ivy_ObjFanin1(pObj); - pSuppF = Ivy_ObjSupp( pAig, pFanin ); - if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Updates the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pFanin; - assert( Ivy_ObjIsNode(pObj) ); - Vec_PtrRemove( vFront, pObj ); - pFanin = Ivy_ObjFanin0(pObj); - if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) - { - Ivy_ObjSetTravIdCurrent(pAig, pFanin); - Vec_PtrPush( vFront, pFanin ); - } - pFanin = Ivy_ObjFanin1(pObj); - if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) - { - Ivy_ObjSetTravIdCurrent(pAig, pFanin); - Vec_PtrPush( vFront, pFanin ); - } -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( Ivy_ObjIsCi(pFanin) ) - continue; - if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) ) - continue; - if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) - { - Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( Ivy_ObjIsCi(pFanin) ) - continue; - if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 ) - { - Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( Ivy_ObjIsCi(pFanin) ) - continue; - if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) - { - Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) ) - return 1; - if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) ) - return 1; - if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) ) - return 1; - assert( Vec_PtrSize(vFront) <= nLimit ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) ); -} - -/**Function************************************************************* - - Synopsis [Prepares node mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) -{ - Ivy_Supp_t * pSupp; - Ivy_Obj_t * pFanin; - int i; - pSupp = Ivy_ObjSupp( pAig, pObj ); - // expand the cut downwards from the given place - Vec_PtrClear( vFront ); - Vec_PtrClear( vFrontOld ); - Ivy_ManIncrementTravId( pAig ); - for ( i = 0; i < pSupp->nSize; i++ ) - { - pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]); - Vec_PtrPush( vFront, pFanin ); - Vec_PtrPush( vFrontOld, pFanin ); - Ivy_ObjSetTravIdCurrent( pAig, pFanin ); - } - // mark the nodes in the cone - Ivy_FastMapMark_rec( pAig, pObj ); -} - -/**Function************************************************************* - - Synopsis [Updates the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) -{ - Ivy_Supp_t * pSupp; - Ivy_Obj_t * pFanin; - int i; - pSupp = Ivy_ObjSupp( pAig, pObj ); - // deref node's cut - Ivy_FastMapNodeDeref( pAig, pObj ); - // update the node's cut - pSupp->nSize = Vec_PtrSize(vFront); - Vec_PtrForEachEntry( vFront, pFanin, i ) - pSupp->pArray[i] = pFanin->Id; - // ref the new cut - Ivy_FastMapNodeRef( pAig, pObj ); -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) -{ - Ivy_Supp_t * pSupp; - int CostBef, CostAft; - int AreaBef, AreaAft; - pSupp = Ivy_ObjSupp( pAig, pObj ); -// if ( pSupp->nRefs == 0 ) -// return; - if ( pSupp->nRefs == 0 ) - AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); - else - AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - // get the area - if ( AreaBef == 1 ) - return; - - if ( pSupp->nRefs == 0 ) - { - pSupp->nRefs = 1000000; - Ivy_FastMapNodeRef( pAig, pObj ); - } - // the cut is non-trivial - Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); - // iteratively modify the cut - CostBef = Ivy_FastMapCutCost( pAig, vFront ); - Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); - CostAft = Ivy_FastMapCutCost( pAig, vFront ); - assert( CostBef >= CostAft ); - // update the node - Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); - // get the new area - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - if ( AreaAft > AreaBef ) - { - Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - assert( AreaAft == AreaBef ); - } - if ( pSupp->nRefs == 1000000 ) - { - pSupp->nRefs = 0; - Ivy_FastMapNodeDeref( pAig, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) -{ - Ivy_Supp_t * pSupp; - int CostBef, CostAft; - int AreaBef, AreaAft; - int DelayOld; - pSupp = Ivy_ObjSupp( pAig, pObj ); - DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); - assert( pSupp->Delay <= pSupp->DelayR ); - if ( pSupp->nRefs == 0 ) - return; - // get the area - AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); -// if ( AreaBef == 1 ) -// return; - if ( pObj->Id == 102 ) - { - int x = 0; - } - // the cut is non-trivial - Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); - // iteratively modify the cut - Ivy_FastMapNodeDeref( pAig, pObj ); - CostBef = Ivy_FastMapCutCost( pAig, vFront ); - Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); - CostAft = Ivy_FastMapCutCost( pAig, vFront ); - Ivy_FastMapNodeRef( pAig, pObj ); - assert( CostBef >= CostAft ); - // update the node - Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); - pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); - // get the new area - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) - { - Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - assert( AreaAft == AreaBef ); - pSupp->Delay = DelayOld; - } -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) -{ - Ivy_Supp_t * pSupp; - int CostBef, CostAft; - int AreaBef, AreaAft; - int DelayOld; - pSupp = Ivy_ObjSupp( pAig, pObj ); - DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); - assert( pSupp->Delay <= pSupp->DelayR ); -// if ( pSupp->nRefs == 0 ) -// return; -// AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - // get the area - if ( pSupp->nRefs == 0 ) - AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); - else - AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - if ( AreaBef == 1 ) - return; - - if ( pSupp->nRefs == 0 ) - { - pSupp->nRefs = 1000000; - Ivy_FastMapNodeRef( pAig, pObj ); - } - // the cut is non-trivial - Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); - // iteratively modify the cut - CostBef = Ivy_FastMapCutCost( pAig, vFront ); - Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); - CostAft = Ivy_FastMapCutCost( pAig, vFront ); - assert( CostBef >= CostAft ); - // update the node - Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); - pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); - // get the new area - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) - { - Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - assert( AreaAft == AreaBef ); - pSupp->Delay = DelayOld; - } - if ( pSupp->nRefs == 1000000 ) - { - pSupp->nRefs = 0; - Ivy_FastMapNodeDeref( pAig, pObj ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyFraig.c b/src/temp/ivy/ivyFraig.c deleted file mode 100644 index 209ff8e7..00000000 --- a/src/temp/ivy/ivyFraig.c +++ /dev/null @@ -1,2520 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyFraig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Functional reduction of AIGs] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" -#include "satSolver.h" -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ivy_FraigMan_t_ Ivy_FraigMan_t; -typedef struct Ivy_FraigSim_t_ Ivy_FraigSim_t; -typedef struct Ivy_FraigList_t_ Ivy_FraigList_t; - -struct Ivy_FraigList_t_ -{ - Ivy_Obj_t * pHead; - Ivy_Obj_t * pTail; - int nItems; -}; - -struct Ivy_FraigSim_t_ -{ - int Type; - Ivy_FraigSim_t * pNext; - Ivy_FraigSim_t * pFanin0; - Ivy_FraigSim_t * pFanin1; - unsigned pData[0]; -}; - -struct Ivy_FraigMan_t_ -{ - // general info - Ivy_FraigParams_t * pParams; // various parameters - // AIG manager - Ivy_Man_t * pManAig; // the starting AIG manager - Ivy_Man_t * pManFraig; // the final AIG manager - // simulation information - int nSimWords; // the number of words - char * pSimWords; // the simulation info - Ivy_FraigSim_t * pSimStart; // the list of simulation info for internal nodes - // counter example storage - int nPatWords; // the number of words in the counter example - unsigned * pPatWords; // the counter example - int * pPatScores; // the scores of each pattern - // equivalence classes - Ivy_FraigList_t lClasses; // equivalence classes - Ivy_FraigList_t lCand; // candidatates - int nPairs; // the number of pairs of nodes - // equivalence checking - sat_solver * pSat; // SAT solver - int nSatVars; // the number of variables currently used - Vec_Ptr_t * vPiVars; // the PIs of the cone used - // other - ProgressBar * pProgress; - // statistics - int nSimRounds; - int nNodesMiter; - int nClassesZero; - int nClassesBeg; - int nClassesEnd; - int nPairsBeg; - int nPairsEnd; - int nSatCalls; - int nSatCallsSat; - int nSatCallsUnsat; - int nSatProof; - int nSatFails; - int nSatFailsReal; - // runtime - int timeSim; - int timeTrav; - int timeSat; - int timeSatUnsat; - int timeSatSat; - int timeSatFail; - int timeRef; - int timeTotal; - int time1; - int time2; -}; - -typedef struct Prove_ParamsStruct_t_ Prove_Params_t; -struct Prove_ParamsStruct_t_ -{ - // general parameters - int fUseFraiging; // enables fraiging - int fUseRewriting; // enables rewriting - int fUseBdds; // enables BDD construction when other methods fail - int fVerbose; // prints verbose stats - // iterations - int nItersMax; // the number of iterations - // mitering - int nMiteringLimitStart; // starting mitering limit - float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // rewriting - int nRewritingLimitStart; // the number of rewriting iterations - float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // fraiging - int nFraigingLimitStart; // starting backtrack(conflict) limit - float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // last-gasp BDD construction - int nBddSizeLimit; // the number of BDD nodes when construction is aborted - int fBddReorder; // enables dynamic BDD variable reordering - // last-gasp mitering - int nMiteringLimitLast; // final mitering limit - // global SAT solver limits - sint64 nTotalBacktrackLimit; // global limit on the number of backtracks - sint64 nTotalInspectLimit; // global limit on the number of clause inspects - // global resources applied - sint64 nTotalBacktracksMade; // the total number of backtracks made - sint64 nTotalInspectsMade; // the total number of inspects made -}; - -static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj ) { return (Ivy_FraigSim_t *)pObj->pFanout; } -static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } -static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } -static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj ) { return pObj->pNextFan1; } -static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } -static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } -static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj ) { return pObj->pPrevFan1; } -static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj ) { return pObj->pEquiv; } -static inline int Ivy_ObjSatNum( Ivy_Obj_t * pObj ) { return (int)pObj->pNextFan0; } -static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj ) { return (Vec_Ptr_t *)pObj->pNextFan1; } - -static inline void Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim ) { pObj->pFanout = (Ivy_Obj_t *)pSim; } -static inline void Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; } -static inline void Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; } -static inline void Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; } -static inline void Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } -static inline void Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } -static inline void Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; } -static inline void Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode ) { pObj->pEquiv = pNode; } -static inline void Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num ) { pObj->pNextFan0 = (Ivy_Obj_t *)Num; } -static inline void Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins ) { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; } - -static inline unsigned Ivy_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } - -// iterate through equivalence classes -#define Ivy_FraigForEachEquivClass( pList, pEnt ) \ - for ( pEnt = pList; \ - pEnt; \ - pEnt = Ivy_ObjEquivListNext(pEnt) ) -#define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 ) \ - for ( pEnt = pList, \ - pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL ) -// iterate through nodes in one class -#define Ivy_FraigForEachClassNode( pClass, pEnt ) \ - for ( pEnt = pClass; \ - pEnt; \ - pEnt = Ivy_ObjClassNodeNext(pEnt) ) -// iterate through nodes in the hash table -#define Ivy_FraigForEachBinNode( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = Ivy_ObjNodeHashNext(pEnt) ) - -static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); -static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); -static Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 * pnSatConfs, sint64 * pnSatInspects ); -static void Ivy_FraigPrint( Ivy_FraigMan_t * p ); -static void Ivy_FraigStop( Ivy_FraigMan_t * p ); -static void Ivy_FraigSimulate( Ivy_FraigMan_t * p ); -static void Ivy_FraigSweep( Ivy_FraigMan_t * p ); -static Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ); -static int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); -static int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ); -static void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); -static int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ); -static void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ); -static int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ); -static void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ); -static void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose ); -static int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sets the default solving parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ) -{ - memset( pParams, 0, sizeof(Ivy_FraigParams_t) ); - pParams->nSimWords = 32; // the number of words in the simulation info - pParams->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached - pParams->fPatScores = 0; // enables simulation pattern scoring - pParams->MaxScore = 25; // max score after which resimulation is used - pParams->fDoSparse = 1; // skips sparse functions -// pParams->dActConeRatio = 0.05; // the ratio of cone to be bumped -// pParams->dActConeBumpMax = 5.0; // the largest bump of activity - pParams->dActConeRatio = 0.3; // the ratio of cone to be bumped - pParams->dActConeBumpMax = 10.0; // the largest bump of activity - - pParams->nBTLimitNode = 100; // conflict limit at a node - pParams->nBTLimitMiter = 500000; // conflict limit at an output - pParams->nBTLimitGlobal = 0; // conflict limit global - pParams->nInsLimitNode = 0; // inspection limit at a node - pParams->nInsLimitMiter = 0; // inspection limit at an output - pParams->nInsLimitGlobal = 0; // inspection limit global -} - -/**Function************************************************************* - - Synopsis [Performs combinational equivalence checking for the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ) -{ - Prove_Params_t * pParams = pPars; - Ivy_FraigParams_t Params, * pIvyParams = &Params; - Ivy_Man_t * pManAig, * pManTemp; - int RetValue, nIter, Counter, clk, timeStart = clock(); - sint64 nSatConfs, nSatInspects, nInspectLimit; - - // start the network and parameters - pManAig = *ppManAig; - Ivy_FraigParamsDefault( pIvyParams ); - pIvyParams->fVerbose = pParams->fVerbose; - pIvyParams->fProve = 1; - - if ( pParams->fVerbose ) - { - printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", - pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); - printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", - pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, - pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, - pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); - printf( "Mitering last = %d.\n", - pParams->nMiteringLimitLast ); - } - - // if SAT only, solve without iteration - if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) - { - clk = clock(); - pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); - pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); - *ppManAig = pManAig; - return RetValue; - } - - if ( Ivy_ManNodeNum(pManAig) < 500 ) - { - // run the first mitering - clk = clock(); - pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig); - pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); - if ( RetValue >= 0 ) - { - *ppManAig = pManAig; - return RetValue; - } - } - - // check the current resource limits - RetValue = -1; - for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) - { - if ( pParams->fVerbose ) - { - printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, - (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), - (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); - fflush( stdout ); - } - - // try rewriting - if ( pParams->fUseRewriting ) - { - clk = clock(); - Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); - pManAig = Ivy_ManRwsat( pManAig, 0 ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "Rewriting ", clk, pParams->fVerbose ); - } - if ( RetValue >= 0 ) - break; - - // try fraiging followed by mitering - if ( pParams->fUseFraiging ) - { - clk = clock(); - nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; - pIvyParams->nBTLimitNode = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)); - pIvyParams->nBTLimitMiter = (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig); - pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, &nSatConfs, &nSatInspects ); Ivy_ManStop( pManTemp ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "Fraiging ", clk, pParams->fVerbose ); - } - if ( RetValue >= 0 ) - break; - - // add to the number of backtracks and inspects - pParams->nTotalBacktracksMade += nSatConfs; - pParams->nTotalInspectsMade += nSatInspects; - // check if global resource limit is reached - if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || - (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) - { - printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); - *ppManAig = pManAig; - return -1; - } - } - - if ( RetValue < 0 ) - { - if ( pParams->fVerbose ) - { - printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); - fflush( stdout ); - } - clk = clock(); - nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; - pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); - pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); - } - - // assign the model if it was proved by rewriting (const 1 miter) - if ( RetValue == 0 && pManAig->pData == NULL ) - { - pManAig->pData = ALLOC( int, Ivy_ManPiNum(pManAig) ); - memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) ); - } - *ppManAig = pManAig; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 * pnSatConfs, sint64 * pnSatInspects ) -{ - Ivy_FraigMan_t * p; - Ivy_Man_t * pManAigNew; - int clk; - if ( Ivy_ManNodeNum(pManAig) == 0 ) - return Ivy_ManDup(pManAig); -clk = clock(); - assert( Ivy_ManLatchNum(pManAig) == 0 ); - p = Ivy_FraigStart( pManAig, pParams ); - Ivy_FraigSimulate( p ); - Ivy_FraigSweep( p ); - pManAigNew = p->pManFraig; -p->timeTotal = clock() - clk; - if ( pnSatConfs ) - *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0; - if ( pnSatInspects ) - *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0; - Ivy_FraigStop( p ); - return pManAigNew; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) -{ - Ivy_FraigMan_t * p; - Ivy_Man_t * pManAigNew; - int clk; - if ( Ivy_ManNodeNum(pManAig) == 0 ) - return Ivy_ManDup(pManAig); -clk = clock(); - assert( Ivy_ManLatchNum(pManAig) == 0 ); - p = Ivy_FraigStart( pManAig, pParams ); - Ivy_FraigSimulate( p ); - Ivy_FraigSweep( p ); - pManAigNew = p->pManFraig; -p->timeTotal = clock() - clk; - Ivy_FraigStop( p ); - return pManAigNew; -} - -/**Function************************************************************* - - Synopsis [Applies brute-force SAT to the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) -{ - Ivy_FraigMan_t * p; - Ivy_Man_t * pManAigNew; - Ivy_Obj_t * pObj; - int i, clk; -clk = clock(); - assert( Ivy_ManLatchNum(pManAig) == 0 ); - p = Ivy_FraigStartSimple( pManAig, pParams ); - // duplicate internal nodes - Ivy_ManForEachNode( p->pManAig, pObj, i ) - pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - // try to prove each output of the miter - Ivy_FraigMiterProve( p ); - // add the POs - Ivy_ManForEachPo( p->pManAig, pObj, i ) - Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); - // clean the new manager - Ivy_ManForEachObj( p->pManFraig, pObj, i ) - { - if ( Ivy_ObjFaninVec(pObj) ) - Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); - pObj->pNextFan0 = pObj->pNextFan1 = NULL; - } - // remove dangling nodes - Ivy_ManCleanup( p->pManFraig ); - pManAigNew = p->pManFraig; -p->timeTotal = clock() - clk; - -//printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) ); -//PRT( "Time", p->timeTotal ); - Ivy_FraigStop( p ); - return pManAigNew; -} - -/**Function************************************************************* - - Synopsis [Starts the fraiging manager without simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) -{ - Ivy_FraigMan_t * p; - // allocat the fraiging manager - p = ALLOC( Ivy_FraigMan_t, 1 ); - memset( p, 0, sizeof(Ivy_FraigMan_t) ); - p->pParams = pParams; - p->pManAig = pManAig; - p->pManFraig = Ivy_ManStartFrom( pManAig ); - p->vPiVars = Vec_PtrAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Starts the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) -{ - Ivy_FraigMan_t * p; - Ivy_FraigSim_t * pSims; - Ivy_Obj_t * pObj; - int i, k, EntrySize; - // clean the fanout representation - Ivy_ManForEachObj( pManAig, pObj, i ) -// pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; - assert( !pObj->pEquiv && !pObj->pFanout ); - // allocat the fraiging manager - p = ALLOC( Ivy_FraigMan_t, 1 ); - memset( p, 0, sizeof(Ivy_FraigMan_t) ); - p->pParams = pParams; - p->pManAig = pManAig; - p->pManFraig = Ivy_ManStartFrom( pManAig ); - // allocate simulation info - p->nSimWords = pParams->nSimWords; -// p->pSimWords = ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords ); - EntrySize = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords; - p->pSimWords = (char *)malloc( Ivy_ManObjNum(pManAig) * EntrySize ); - memset( p->pSimWords, 0, EntrySize ); - k = 0; - Ivy_ManForEachObj( pManAig, pObj, i ) - { - pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++); - pSims->pNext = NULL; - if ( Ivy_ObjIsNode(pObj) ) - { - if ( p->pSimStart == NULL ) - p->pSimStart = pSims; - else - ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims; - pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) ); - pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) ); - pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase; - } - else - { - pSims->pFanin0 = NULL; - pSims->pFanin1 = NULL; - pSims->Type = 0; - } - Ivy_ObjSetSim( pObj, pSims ); - } - assert( k == Ivy_ManObjNum(pManAig) ); - // allocate storage for sim pattern - p->nPatWords = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) ); - p->pPatWords = ALLOC( unsigned, p->nPatWords ); - p->pPatScores = ALLOC( int, 32 * p->nSimWords ); - p->vPiVars = Vec_PtrAlloc( 100 ); - // set random number generator - srand( 0xABCABC ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigStop( Ivy_FraigMan_t * p ) -{ - if ( p->pParams->fVerbose ) - Ivy_FraigPrint( p ); - if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); - if ( p->pSat ) sat_solver_delete( p->pSat ); - FREE( p->pPatScores ); - FREE( p->pPatWords ); - FREE( p->pSimWords ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prints stats for the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigPrint( Ivy_FraigMan_t * p ) -{ - double nMemory; - nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20); - printf( "SimWords = %d. Rounds = %d. Mem = %0.2f Mb. ", p->nSimWords, p->nSimRounds, nMemory ); - printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd ); - printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter ); - printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", - p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero ); - printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n", - Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars ); - if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); - PRT( "AIG simulation ", p->timeSim ); - PRT( "AIG traversal ", p->timeTrav ); - PRT( "SAT solving ", p->timeSat ); - PRT( " Unsat ", p->timeSatUnsat ); - PRT( " Sat ", p->timeSatSat ); - PRT( " Fail ", p->timeSatFail ); - PRT( "Class refining ", p->timeRef ); - PRT( "TOTAL RUNTIME ", p->timeTotal ); - if ( p->time1 ) { PRT( "time1 ", p->time1 ); } -} - - - -/**Function************************************************************* - - Synopsis [Assigns random patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims; - int i; - assert( Ivy_ObjIsPi(pObj) ); - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = Ivy_ObjRandomSim(); -} - -/**Function************************************************************* - - Synopsis [Assigns constant patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 ) -{ - Ivy_FraigSim_t * pSims; - int i; - assert( Ivy_ObjIsPi(pObj) ); - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = fConst1? ~(unsigned)0 : 0; -} - -/**Function************************************************************* - - Synopsis [Assings random simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - Ivy_ManForEachPi( p->pManAig, pObj, i ) - Ivy_NodeAssignRandom( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Assings distance-1 simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat ) -{ - Ivy_Obj_t * pObj; - int i, Limit; - Ivy_ManForEachPi( p->pManAig, pObj, i ) - Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) ); - Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 ); - for ( i = 0; i < Limit; i++ ) - Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims; - int i; - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - if ( pSims->pData[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) -{ - Ivy_FraigSim_t * pSims0, * pSims1; - int i; - pSims0 = Ivy_ObjSim(pObj0); - pSims1 = Ivy_ObjSim(pObj1); - for ( i = 0; i < p->nSimWords; i++ ) - if ( pSims0->pData[i] != pSims1->pData[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims ) -{ - unsigned * pData, * pData0, * pData1; - int i; - pData = pSims->pData; - pData0 = pSims->pFanin0->pData; - pData1 = pSims->pFanin1->pData; - switch( pSims->Type ) - { - case 0: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (pData0[i] & pData1[i]); - break; - case 1: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = ~(pData0[i] & pData1[i]); - break; - case 2: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (pData0[i] & ~pData1[i]); - break; - case 3: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (~pData0[i] | pData1[i]); - break; - case 4: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (~pData0[i] & pData1[i]); - break; - case 5: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (pData0[i] | ~pData1[i]); - break; - case 6: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = ~(pData0[i] | pData1[i]); - break; - case 7: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (pData0[i] | pData1[i]); - break; - } -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims, * pSims0, * pSims1; - int fCompl, fCompl0, fCompl1, i; - assert( !Ivy_IsComplement(pObj) ); - // get hold of the simulation information - pSims = Ivy_ObjSim(pObj); - pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj)); - pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj)); - // get complemented attributes of the children using their random info - fCompl = pObj->fPhase; - fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); - fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); - // simulate - if ( fCompl0 && fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]); - else - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]); - } - else if ( fCompl0 && !fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]); - else - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]); - } - else if ( !fCompl0 && fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]); - else - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]); - } - else // if ( !fCompl0 && !fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]); - else - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]); - } -} - -/**Function************************************************************* - - Synopsis [Computes hash value using simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - static int s_FPrimes[128] = { - 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, - 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, - 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, - 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, - 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, - 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, - 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, - 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, - 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, - 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, - 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, - 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, - 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 - }; - Ivy_FraigSim_t * pSims; - unsigned uHash; - int i; - assert( p->nSimWords <= 128 ); - uHash = 0; - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - uHash ^= pSims->pData[i] * s_FPrimes[i]; - return uHash; -} - -/**Function************************************************************* - - Synopsis [Simulates AIG manager.] - - Description [Assumes that the PI simulation info is attached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i, clk; -clk = clock(); - Ivy_ManForEachNode( p->pManAig, pObj, i ) - { - Ivy_NodeSimulate( p, pObj ); -/* - if ( Ivy_ObjFraig(pObj) == NULL ) - printf( "%3d --- -- %d : ", pObj->Id, pObj->fPhase ); - else - printf( "%3d %3d %2d %d : ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase ); - Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 ); - printf( "\n" ); -*/ - } -p->timeSim += clock() - clk; -p->nSimRounds++; -} - -/**Function************************************************************* - - Synopsis [Simulates AIG manager.] - - Description [Assumes that the PI simulation info is attached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p ) -{ - Ivy_FraigSim_t * pSims; - int clk; -clk = clock(); - for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext ) - Ivy_NodeSimulateSim( p, pSims ); -p->timeSim += clock() - clk; -p->nSimRounds++; -} - -/**Function************************************************************* - - Synopsis [Adds one node to the equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj ) -{ - if ( Ivy_ObjClassNodeNext(pClass) == NULL ) - Ivy_ObjSetClassNodeNext( pClass, pObj ); - else - Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj ); - Ivy_ObjSetClassNodeLast( pClass, pObj ); - Ivy_ObjSetClassNodeRepr( pObj, pClass ); - Ivy_ObjSetClassNodeNext( pObj, NULL ); -} - -/**Function************************************************************* - - Synopsis [Adds equivalence class to the list of classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) -{ - if ( pList->pHead == NULL ) - { - pList->pHead = pClass; - pList->pTail = pClass; - Ivy_ObjSetEquivListPrev( pClass, NULL ); - Ivy_ObjSetEquivListNext( pClass, NULL ); - } - else - { - Ivy_ObjSetEquivListNext( pList->pTail, pClass ); - Ivy_ObjSetEquivListPrev( pClass, pList->pTail ); - Ivy_ObjSetEquivListNext( pClass, NULL ); - pList->pTail = pClass; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [Updates the list of classes after base class has split.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass ) -{ - Ivy_ObjSetEquivListPrev( pClass, pBase ); - Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) ); - if ( Ivy_ObjEquivListNext(pBase) ) - Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass ); - Ivy_ObjSetEquivListNext( pBase, pClass ); - if ( pList->pTail == pBase ) - pList->pTail = pClass; - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [Removes equivalence class from the list of classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) -{ - if ( pList->pHead == pClass ) - pList->pHead = Ivy_ObjEquivListNext(pClass); - if ( pList->pTail == pClass ) - pList->pTail = Ivy_ObjEquivListPrev(pClass); - if ( Ivy_ObjEquivListPrev(pClass) ) - Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) ); - if ( Ivy_ObjEquivListNext(pClass) ) - Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) ); - Ivy_ObjSetEquivListNext( pClass, NULL ); - Ivy_ObjSetEquivListPrev( pClass, NULL ); - pClass->fMarkA = 0; - pList->nItems--; -} - -/**Function************************************************************* - - Synopsis [Count the number of pairs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pClass, * pNode; - int nPairs = 0, nNodes; - return nPairs; - - Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) - { - nNodes = 0; - Ivy_FraigForEachClassNode( pClass, pNode ) - nNodes++; - nPairs += nNodes * (nNodes - 1) / 2; - } - return nPairs; -} - -/**Function************************************************************* - - Synopsis [Creates initial simulation classes.] - - Description [Assumes that simulation info is assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t ** pTable; - Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry; - int i, nTableSize; - unsigned Hash; - pConst1 = Ivy_ManConst1(p->pManAig); - // allocate the table - nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13; - pTable = ALLOC( Ivy_Obj_t *, nTableSize ); - memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize ); - // collect nodes into the table - Ivy_ManForEachObj( p->pManAig, pObj, i ) - { - if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) - continue; - Hash = Ivy_NodeHash( p, pObj ); - if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) ) - { - Ivy_NodeAddToClass( pConst1, pObj ); - continue; - } - // add the node to the table - pBin = pTable[Hash % nTableSize]; - Ivy_FraigForEachBinNode( pBin, pEntry ) - if ( Ivy_NodeCompareSims( p, pEntry, pObj ) ) - { - Ivy_NodeAddToClass( pEntry, pObj ); - break; - } - // check if the entry was added - if ( pEntry ) - continue; - Ivy_ObjSetNodeHashNext( pObj, pBin ); - pTable[Hash % nTableSize] = pObj; - } - // collect non-trivial classes - assert( p->lClasses.pHead == NULL ); - Ivy_ManForEachObj( p->pManAig, pObj, i ) - { - if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) - continue; - Ivy_ObjSetNodeHashNext( pObj, NULL ); - if ( Ivy_ObjClassNodeRepr(pObj) == NULL ) - { - assert( Ivy_ObjClassNodeNext(pObj) == NULL ); - continue; - } - // recognize the head of the class - if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL ) - continue; - // clean the class representative and add it to the list - Ivy_ObjSetClassNodeRepr( pObj, NULL ); - Ivy_FraigAddClass( &p->lClasses, pObj ); - } - // free the table - free( pTable ); -} - -/**Function************************************************************* - - Synopsis [Recursively refines the class after simulation.] - - Description [Returns 1 if the class has changed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass ) -{ - Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode; - int RetValue = 0; - // check if there is refinement - pListOld = pClass; - Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew ) - { - if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) ) - { - if ( p->pParams->fPatScores ) - Ivy_FraigAddToPatScores( p, pClass, pClassNew ); - break; - } - pListOld = pClassNew; - } - if ( pClassNew == NULL ) - return 0; - // set representative of the new class - Ivy_ObjSetClassNodeRepr( pClassNew, NULL ); - // start the new list - pListNew = pClassNew; - // go through the remaining nodes and sort them into two groups: - // (1) matches of the old node; (2) non-matches of the old node - Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode ) - if ( Ivy_NodeCompareSims( p, pClass, pNode ) ) - { - Ivy_ObjSetClassNodeNext( pListOld, pNode ); - pListOld = pNode; - } - else - { - Ivy_ObjSetClassNodeNext( pListNew, pNode ); - Ivy_ObjSetClassNodeRepr( pNode, pClassNew ); - pListNew = pNode; - } - // finish both lists - Ivy_ObjSetClassNodeNext( pListNew, NULL ); - Ivy_ObjSetClassNodeNext( pListOld, NULL ); - // update the list of classes - Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew ); - // if the old class is trivial, remove it - if ( Ivy_ObjClassNodeNext(pClass) == NULL ) - Ivy_FraigRemoveClass( &p->lClasses, pClass ); - // if the new class is trivial, remove it; otherwise, try to refine it - if ( Ivy_ObjClassNodeNext(pClassNew) == NULL ) - Ivy_FraigRemoveClass( &p->lClasses, pClassNew ); - else - RetValue = Ivy_FraigRefineClass_rec( p, pClassNew ); - return RetValue + 1; -} - -/**Function************************************************************* - - Synopsis [Creates the counter-example from the successful pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims; - int i, k, BestPat, * pModel; - // find the word of the pattern - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - if ( pSims->pData[i] ) - break; - assert( i < p->nSimWords ); - // find the bit of the pattern - for ( k = 0; k < 32; k++ ) - if ( pSims->pData[i] & (1 << k) ) - break; - assert( k < 32 ); - // determine the best pattern - BestPat = i * 32 + k; - // fill in the counter-example data - pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); - Ivy_ManForEachPi( p->pManAig, pObj, i ) - pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat); - // set the model - assert( p->pManFraig->pData == NULL ); - p->pManFraig->pData = pModel; - return; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the one of the output is already non-constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - Ivy_ManForEachPo( p->pManAig, pObj, i ) - if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) ) - { - // create the counter-example from this pattern - Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) ); - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Refines the classes after simulation.] - - Description [Assumes that simulation info is assigned. Returns the - number of classes refined.] - - SideEffects [Large equivalence class of constant 0 may cause problems.] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pClass, * pClass2; - int clk, RetValue, Counter = 0; - // check if some outputs already became non-constant - // this is a special case when computation can be stopped!!! - if ( p->pParams->fProve ) - Ivy_FraigCheckOutputSims( p ); - if ( p->pManFraig->pData ) - return 0; - // refine the classed -clk = clock(); - Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 ) - { - if ( pClass->fMarkA ) - continue; - RetValue = Ivy_FraigRefineClass_rec( p, pClass ); - Counter += ( RetValue > 0 ); -//if ( Ivy_ObjIsConst1(pClass) ) -//printf( "%d ", RetValue ); -//if ( Ivy_ObjIsConst1(pClass) ) -// p->time1 += clock() - clk; - } -p->timeRef += clock() - clk; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Print the class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigPrintClass( Ivy_Obj_t * pClass ) -{ - Ivy_Obj_t * pObj; - printf( "Class {" ); - Ivy_FraigForEachClassNode( pClass, pObj ) - printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Count the number of elements in the class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass ) -{ - Ivy_Obj_t * pObj; - int Counter = 0; - Ivy_FraigForEachClassNode( pClass, pObj ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pClass; - Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) - { -// Ivy_FraigPrintClass( pClass ); - printf( "%d ", Ivy_FraigCountClassNodes( pClass ) ); - } -// printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Generated const 0 pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p ) -{ - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); -} - -/**Function************************************************************* - - Synopsis [[Generated const 1 pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p ) -{ - memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); -} - -/**Function************************************************************* - - Synopsis [Generates the counter-example satisfying the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ) -{ - int * pModel; - Ivy_Obj_t * pObj; - int i; - pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); - Ivy_ManForEachPi( p->pManFraig, pObj, i ) - pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ); - return pModel; -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); - Ivy_ManForEachPi( p->pManFraig, pObj, i ) -// Vec_PtrForEachEntry( p->vPiVars, pObj, i ) - if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) - Ivy_InfoSetBit( p->pPatWords, i ); -// Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); -// Ivy_ManForEachPi( p->pManFraig, pObj, i ) - Vec_PtrForEachEntry( p->vPiVars, pObj, i ) - if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) -// Ivy_InfoSetBit( p->pPatWords, i ); - Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - for ( i = 0; i < p->nPatWords; i++ ) - p->pPatWords[i] = Ivy_ObjRandomSim(); - Vec_PtrForEachEntry( p->vPiVars, pObj, i ) - if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) ) - Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 ); -} - - -/**Function************************************************************* - - Synopsis [Performs simulation of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSimulate( Ivy_FraigMan_t * p ) -{ - int nChanges, nClasses; - // start the classes - Ivy_FraigAssignRandom( p ); - Ivy_FraigSimulateOne( p ); - Ivy_FraigCreateClasses( p ); -//printf( "Starting classes = %5d. Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) ); - // refine classes by walking 0/1 patterns - Ivy_FraigSavePattern0( p ); - Ivy_FraigAssignDist1( p, p->pPatWords ); - Ivy_FraigSimulateOne( p ); - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; -//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); - Ivy_FraigSavePattern1( p ); - Ivy_FraigAssignDist1( p, p->pPatWords ); - Ivy_FraigSimulateOne( p ); - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; -//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); - // refine classes by random simulation - do { - Ivy_FraigAssignRandom( p ); - Ivy_FraigSimulateOne( p ); - nClasses = p->lClasses.nItems; - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; -//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); - } while ( (double)nChanges / nClasses > p->pParams->dSimSatur ); -// Ivy_FraigPrintSimClasses( p ); -} - - - -/**Function************************************************************* - - Synopsis [Cleans pattern scores.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p ) -{ - int i, nLimit = p->nSimWords * 32; - for ( i = 0; i < nLimit; i++ ) - p->pPatScores[i] = 0; -} - -/**Function************************************************************* - - Synopsis [Adds to pattern scores.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ) -{ - Ivy_FraigSim_t * pSims0, * pSims1; - unsigned uDiff; - int i, w; - // get hold of the simulation information - pSims0 = Ivy_ObjSim(pClass); - pSims1 = Ivy_ObjSim(pClassNew); - // iterate through the differences and record the score - for ( w = 0; w < p->nSimWords; w++ ) - { - uDiff = pSims0->pData[w] ^ pSims1->pData[w]; - if ( uDiff == 0 ) - continue; - for ( i = 0; i < 32; i++ ) - if ( uDiff & ( 1 << i ) ) - p->pPatScores[w*32+i]++; - } -} - -/**Function************************************************************* - - Synopsis [Selects the best pattern.] - - Description [Returns 1 if such pattern is found.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p ) -{ - Ivy_FraigSim_t * pSims; - Ivy_Obj_t * pObj; - int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1; - for ( i = 1; i < nLimit; i++ ) - { - if ( MaxScore < p->pPatScores[i] ) - { - MaxScore = p->pPatScores[i]; - BestPat = i; - } - } - if ( MaxScore == 0 ) - return 0; -// if ( MaxScore > p->pParams->MaxScore ) -// printf( "Max score is %3d. ", MaxScore ); - // copy the best pattern into the selected pattern - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); - Ivy_ManForEachPi( p->pManAig, pObj, i ) - { - pSims = Ivy_ObjSim(pObj); - if ( Ivy_InfoHasBit(pSims->pData, BestPat) ) - Ivy_InfoSetBit(p->pPatWords, i); - } - return MaxScore; -} - -/**Function************************************************************* - - Synopsis [Resimulates fraiging manager after finding a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigResimulate( Ivy_FraigMan_t * p ) -{ - int nChanges; - Ivy_FraigAssignDist1( p, p->pPatWords ); - Ivy_FraigSimulateOne( p ); - if ( p->pParams->fPatScores ) - Ivy_FraigCleanPatScores( p ); - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; - if ( nChanges < 1 ) - printf( "Error: A counter-example did not refine classes!\n" ); - assert( nChanges >= 1 ); -//printf( "Refined classes! = %5d. Changes = %4d.\n", p->lClasses.nItems, nChanges ); - - if ( !p->pParams->fPatScores ) - return; - - // perform additional simulation using dist1 patterns derived from successful patterns - while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore ) - { - Ivy_FraigAssignDist1( p, p->pPatWords ); - Ivy_FraigSimulateOne( p ); - Ivy_FraigCleanPatScores( p ); - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; -//printf( "Refined class!!! = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); - if ( nChanges == 0 ) - break; - } -} - - -/**Function************************************************************* - - Synopsis [Prints the status of the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose ) -{ - if ( !fVerbose ) - return; - printf( "Nodes = %7d. Levels = %4d. ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) ); - PRT( pString, clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Reports the status of the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ) -{ - Ivy_Obj_t * pObj, * pObjNew; - int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; - if ( pMan->pData ) - return 0; - Ivy_ManForEachPo( pMan, pObj, i ) - { - pObjNew = Ivy_ObjChild0(pObj); - // check if the output is constant 1 - if ( pObjNew == pMan->pConst1 ) - { - CountNonConst0++; - continue; - } - // check if the output is constant 0 - if ( pObjNew == Ivy_Not(pMan->pConst1) ) - { - CountConst0++; - continue; - } - // check if the output can be constant 0 - if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) - { - CountNonConst0++; - continue; - } - CountUndecided++; - } -/* - if ( p->pParams->fVerbose ) - { - printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) ); - printf( "Const0 = %d. ", CountConst0 ); - printf( "NonConst0 = %d. ", CountNonConst0 ); - printf( "Undecided = %d. ", CountUndecided ); - printf( "\n" ); - } -*/ - if ( CountNonConst0 ) - return 0; - if ( CountUndecided ) - return -1; - return 1; -} - -/**Function************************************************************* - - Synopsis [Tries to prove each output of the miter until encountering a sat output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj, * pObjNew; - int i, RetValue, clk = clock(); - int fVerbose = 0; - Ivy_ManForEachPo( p->pManAig, pObj, i ) - { - if ( i && fVerbose ) - { - PRT( "Time", clock() -clk ); - } - pObjNew = Ivy_ObjChild0Equiv(pObj); - // check if the output is constant 1 - if ( pObjNew == p->pManFraig->pConst1 ) - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) is constant 1. ", i, Ivy_ManPoNum(p->pManAig) ); - break; - } - // check if the output is constant 0 - if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) ) - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) is already constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); - continue; - } - // check if the output can be constant 0 - if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) cannot be constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); - // assing constant 0 model - p->pManFraig->pData = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); - memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); - break; - } -/* - // check the representative of this node - pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj)); - if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 ) - printf( "Representative is not constant 1.\n" ); - else - printf( "Representative is constant 1.\n" ); -*/ - // try to prove the output constant 0 - RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) ); - if ( RetValue == 1 ) // proved equivalent - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) was proved constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); - // set the constant miter - Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) ); - continue; - } - if ( RetValue == -1 ) // failed - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) has timed out at %d backtracks. ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter ); - continue; - } - // proved satisfiable - if ( fVerbose ) - printf( "Output %2d (out of %2d) was proved NOT a constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); - // create the model - p->pManFraig->pData = Ivy_FraigCreateModel(p); - break; - } - if ( fVerbose ) - { - PRT( "Time", clock() -clk ); - } -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSweep( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj;//, * pTemp; - int i, k = 0; -p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0; -p->nClassesBeg = p->lClasses.nItems; - // duplicate internal nodes - p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) ); - Ivy_ManForEachNode( p->pManAig, pObj, i ) - { - Extra_ProgressBarUpdate( p->pProgress, k++, NULL ); - // default to simple strashing if simulation detected a counter-example for a PO - if ( p->pManFraig->pData ) - pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - else - pObj->pEquiv = Ivy_FraigAnd( p, pObj ); - assert( pObj->pEquiv != NULL ); -// pTemp = Ivy_Regular(pObj->pEquiv); -// assert( Ivy_Regular(pObj->pEquiv)->Type ); - } - Extra_ProgressBarStop( p->pProgress ); -p->nClassesEnd = p->lClasses.nItems; - // try to prove the outputs of the miter - p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig); -// Ivy_FraigMiterStatus( p->pManFraig ); - if ( p->pParams->fProve && p->pManFraig->pData == NULL ) - Ivy_FraigMiterProve( p ); - // add the POs - Ivy_ManForEachPo( p->pManAig, pObj, i ) - Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); - // clean the old manager - Ivy_ManForEachObj( p->pManAig, pObj, i ) - pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; - // clean the new manager - Ivy_ManForEachObj( p->pManFraig, pObj, i ) - { - if ( Ivy_ObjFaninVec(pObj) ) - Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); - pObj->pNextFan0 = pObj->pNextFan1 = NULL; - } - // remove dangling nodes - Ivy_ManCleanup( p->pManFraig ); - // clean up the class marks - Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj ) - pObj->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ) -{ - Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew; - int RetValue; - // get the fraiged fanins - pFanin0New = Ivy_ObjChild0Equiv(pObjOld); - pFanin1New = Ivy_ObjChild1Equiv(pObjOld); - // get the candidate fraig node - pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New ); - // get representative of this class - if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node - (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node - { -// if ( Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1 ) -// { -// int x = 0; -// } - assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) ); - assert( pObjNew != Ivy_Regular(pFanin0New) ); - assert( pObjNew != Ivy_Regular(pFanin1New) ); - return pObjNew; - } - // get the fraiged representative - pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld)); - // if the fraiged nodes are the same return - if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) ) - return pObjNew; - assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) ); - // they are different (the counter-example is in p->pPatWords) - RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) ); - if ( RetValue == 1 ) // proved equivalent - { - // mark the class as proved - if ( Ivy_ObjClassNodeNext(pObjOld) == NULL ) - Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1; - return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase ); - } - if ( RetValue == -1 ) // failed - return pObjNew; - // simulate the counter-example and return the new node - Ivy_FraigResimulate( p ); - return pObjNew; -} - -/**Function************************************************************* - - Synopsis [Prints variable activity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p ) -{ - int i; - for ( i = 0; i < p->nSatVars; i++ ) - printf( "%d %.3f ", i, p->pSat->activity[i] ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Runs equivalence test for the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) -{ - int pLits[4], RetValue, RetValue1, nBTLimit, clk; - - // make sure the nodes are not complemented - assert( !Ivy_IsComplement(pNew) ); - assert( !Ivy_IsComplement(pOld) ); - assert( pNew != pOld ); - - // if at least one of the nodes is a failed node, perform adjustments: - // if the backtrack limit is small, simply skip this node - // if the backtrack limit is > 10, take the quare root of the limit - nBTLimit = p->pParams->nBTLimitNode; - if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) - { - p->nSatFails++; - // fail immediately -// return -1; - if ( nBTLimit <= 10 ) - return -1; - nBTLimit = (int)pow(nBTLimit, 0.7); - } - p->nSatCalls++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - { - p->pSat = sat_solver_new(); - p->nSatVars = 1; - sat_solver_setnvars( p->pSat, 1000 ); - } - - // if the nodes do not have SAT variables, allocate them - Ivy_FraigNodeAddToSolver( p, pOld, pNew ); - - // prepare variable activity - Ivy_FraigSetActivityFactors( p, pOld, pNew ); - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 -clk = clock(); - pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 ); - pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); -//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - nBTLimit, p->pParams->nInsLimitNode, - p->pParams->nBTLimitGlobal, p->pParams->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - // continue solving the other implication - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - Ivy_FraigSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - if ( pOld != p->pManFraig->pConst1 ) - pOld->fFailTfo = 1; - pNew->fFailTfo = 1; - p->nSatFailsReal++; - return -1; - } - - // if the old node was constant 0, we already know the answer - if ( pOld == p->pManFraig->pConst1 ) - { - p->nSatProof++; - return 1; - } - - // solve under assumptions - // A = 0; B = 1 OR A = 0; B = 0 -clk = clock(); - pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 ); - pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - nBTLimit, p->pParams->nInsLimitNode, - p->pParams->nBTLimitGlobal, p->pParams->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - Ivy_FraigSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - pOld->fFailTfo = 1; - pNew->fFailTfo = 1; - p->nSatFailsReal++; - return -1; - } - - // return SAT proof - p->nSatProof++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Runs equivalence test for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew ) -{ - int pLits[2], RetValue1, RetValue, clk; - - // make sure the nodes are not complemented - assert( !Ivy_IsComplement(pNew) ); - assert( pNew != p->pManFraig->pConst1 ); - p->nSatCalls++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - { - p->pSat = sat_solver_new(); - p->nSatVars = 1; - sat_solver_setnvars( p->pSat, 1000 ); - } - - // if the nodes do not have SAT variables, allocate them - Ivy_FraigNodeAddToSolver( p, NULL, pNew ); - - // prepare variable activity - Ivy_FraigSetActivityFactors( p, NULL, pNew ); - - // solve under assumptions -clk = clock(); - pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, - p->pParams->nBTLimitMiter, p->pParams->nInsLimitMiter, - p->pParams->nBTLimitGlobal, p->pParams->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - assert( RetValue ); - // continue solving the other implication - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - if ( p->pPatWords ) - Ivy_FraigSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - pNew->fFailTfo = 1; - p->nSatFailsReal++; - return -1; - } - - // return SAT proof - p->nSatProof++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode ) -{ - Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE; - int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; - - assert( !Ivy_IsComplement( pNode ) ); - assert( Ivy_ObjIsMuxType( pNode ) ); - // get nodes (I = if, T = then, E = else) - pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); - // get the variable numbers - VarF = Ivy_ObjSatNum(pNode); - VarI = Ivy_ObjSatNum(pNodeI); - VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT)); - VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE)); - // get the complementation flags - fCompT = Ivy_IsComplement(pNodeT); - fCompE = Ivy_IsComplement(pNodeE); - - // f = ITE(i, t, e) - - // i' + t' + f - // i' + t + f' - // i + e' + f - // i + e + f' - - // create four clauses - pLits[0] = toLitCond(VarI, 1); - pLits[1] = toLitCond(VarT, 1^fCompT); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 1); - pLits[1] = toLitCond(VarT, 0^fCompT); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 0); - pLits[1] = toLitCond(VarE, 1^fCompE); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 0); - pLits[1] = toLitCond(VarE, 0^fCompE); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - - // two additional clauses - // t' & e' -> f' - // t & e -> f - - // t + e + f' - // t' + e' + f - - if ( VarT == VarE ) - { -// assert( fCompT == !fCompE ); - return; - } - - pLits[0] = toLitCond(VarT, 0^fCompT); - pLits[1] = toLitCond(VarE, 0^fCompE); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarT, 1^fCompT); - pLits[1] = toLitCond(VarE, 1^fCompE); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper ) -{ - Ivy_Obj_t * pFanin; - int * pLits, nLits, RetValue, i; - assert( !Ivy_IsComplement(pNode) ); - assert( Ivy_ObjIsNode( pNode ) ); - // create storage for literals - nLits = Vec_PtrSize(vSuper) + 1; - pLits = ALLOC( int, nLits ); - // suppose AND-gate is A & B = C - // add !A => !C or A + !C - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin)); - pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - } - // add A & B => C or !A + !B + C - Vec_PtrForEachEntry( vSuper, pFanin, i ) - pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin)); - pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); - assert( RetValue ); - free( pLits ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) -{ - // if the new node is complemented or a PI, another gate begins - if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) || - (fUseMuxes && Ivy_ObjIsMuxType(pObj)) ) - { - Vec_PtrPushUnique( vSuper, pObj ); - return; - } - // go through the branches - Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes ); - Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes ) -{ - Vec_Ptr_t * vSuper; - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_ObjIsPi(pObj) ); - vSuper = Vec_PtrAlloc( 4 ); - Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); - return vSuper; -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier ) -{ - assert( !Ivy_IsComplement(pObj) ); - if ( Ivy_ObjSatNum(pObj) ) - return; - assert( Ivy_ObjSatNum(pObj) == 0 ); - assert( Ivy_ObjFaninVec(pObj) == NULL ); - if ( Ivy_ObjIsConst1(pObj) ) - return; -//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); - Ivy_ObjSetSatNum( pObj, p->nSatVars++ ); - if ( Ivy_ObjIsNode(pObj) ) - Vec_PtrPush( vFrontier, pObj ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) -{ - Vec_Ptr_t * vFrontier, * vFanins; - Ivy_Obj_t * pNode, * pFanin; - int i, k, fUseMuxes = 1; - assert( pOld || pNew ); - // quit if CNF is ready - if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) ) - return; - // start the frontier - vFrontier = Vec_PtrAlloc( 100 ); - if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier ); - if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier ); - // explore nodes in the frontier - Vec_PtrForEachEntry( vFrontier, pNode, i ) - { - // create the supergate - assert( Ivy_ObjSatNum(pNode) ); - assert( Ivy_ObjFaninVec(pNode) == NULL ); - if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) ) - { - vFanins = Vec_PtrAlloc( 4 ); - Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) ); - Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) ); - Vec_PtrForEachEntry( vFanins, pFanin, k ) - Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); - Ivy_FraigAddClausesMux( p, pNode ); - } - else - { - vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes ); - Vec_PtrForEachEntry( vFanins, pFanin, k ) - Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); - Ivy_FraigAddClausesSuper( p, pNode, vFanins ); - } - assert( Vec_PtrSize(vFanins) > 1 ); - Ivy_ObjSetFaninVec( pNode, vFanins ); - } - Vec_PtrFree( vFrontier ); -} - -/**Function************************************************************* - - Synopsis [Sets variable activities in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax ) -{ - Vec_Ptr_t * vFanins; - Ivy_Obj_t * pFanin; - int i, Counter = 0; - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjSatNum(pObj) ); - // skip visited variables - if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) ) - return 0; - Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj); - // add the PI to the list - if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) ) - return 0; - // set the factor of this variable - // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump - p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); - veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj)); - // explore the fanins - vFanins = Ivy_ObjFaninVec( pObj ); - Vec_PtrForEachEntry( vFanins, pFanin, i ) - Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax ); - return 1 + Counter; -} - -/**Function************************************************************* - - Synopsis [Sets variable activities in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) -{ - int clk, LevelMin, LevelMax; - assert( pOld || pNew ); -clk = clock(); - // reset the active variables - veci_resize(&p->pSat->act_vars, 0); - // prepare for traversal - Ivy_ManIncrementTravId( p->pManFraig ); - // determine the min and max level to visit - assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 ); - LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); - LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio)); - // traverse - if ( pOld && !Ivy_ObjIsConst1(pOld) ) - Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); - if ( pNew && !Ivy_ObjIsConst1(pNew) ) - Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); -//Ivy_FraigPrintActivity( p ); -p->timeTrav += clock() - clk; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyHaig.c b/src/temp/ivy/ivyHaig.c deleted file mode 100644 index 87021600..00000000 --- a/src/temp/ivy/ivyHaig.c +++ /dev/null @@ -1,530 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyHaig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [HAIG management procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - HAIGing rules in working AIG: - - Each node in the working AIG has a pointer to the corresponding node in HAIG - (this node is not necessarily the representative of the equivalence class of HAIG nodes) - - This pointer is complemented if the AIG node and its corresponding HAIG node have different phase - - Choice node rules in HAIG: - - Equivalent nodes are linked into a ring - - Exactly one node in the ring has fanouts (this node is called the representative) - - The pointer going from a node to the next node in the ring is complemented - if the first node is complemented, compared to the representative node of the equivalence class - - (consequence of the above) The representative node always has non-complemented pointer to the next node - - New nodes are inserted into the ring immediately after the representative node -*/ - -// returns the representative node of the given HAIG node -static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pTemp; - assert( !Ivy_IsComplement(pObj) ); - // if the node has no equivalent node or has fanout, it is representative - if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 ) - return pObj; - // the node belongs to a class and is not a representative - // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr - for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - if ( Ivy_ObjRefs(pTemp) > 0 ) - break; - // return the representative node - assert( Ivy_ObjRefs(pTemp) > 0 ); - return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) ); -} - -// counts the number of nodes in the equivalence class -static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pTemp; - int Counter; - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjRefs(pObj) > 0 ); - if ( pObj->pEquiv == NULL ) - return 1; - assert( !Ivy_IsComplement(pObj->pEquiv) ); - Counter = 1; - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts HAIG for the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ) -{ - Vec_Int_t * vLatches; - Ivy_Obj_t * pObj; - int i; - assert( p->pHaig == NULL ); - p->pHaig = Ivy_ManDup( p ); - - if ( fVerbose ) - { - printf( "Starting : " ); - Ivy_ManPrintStats( p->pHaig ); - } - - // collect latches of design D and set their values to be DC - vLatches = Vec_IntAlloc( 100 ); - Ivy_ManForEachLatch( p->pHaig, pObj, i ) - { - pObj->Init = IVY_INIT_DC; - Vec_IntPush( vLatches, pObj->Id ); - } - p->pHaig->pData = vLatches; -/* - { - int x; - Ivy_ManShow( p, 0, NULL ); - Ivy_ManShow( p->pHaig, 1, NULL ); - x = 0; - } -*/ -} - -/**Function************************************************************* - - Synopsis [Transfers the HAIG to the newly created manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ) -{ - Ivy_Obj_t * pObj; - int i; - assert( p->pHaig != NULL ); - Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv; - Ivy_ManForEachPi( pNew, pObj, i ) - pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv; - pNew->pHaig = p->pHaig; -} - -/**Function************************************************************* - - Synopsis [Stops HAIG for the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigStop( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - assert( p->pHaig != NULL ); - Vec_IntFree( p->pHaig->pData ); - Ivy_ManStop( p->pHaig ); - p->pHaig = NULL; - // remove dangling pointers to the HAIG objects - Ivy_ManForEachObj( p, pObj, i ) - pObj->pEquiv = NULL; -} - -/**Function************************************************************* - - Synopsis [Creates a new node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pEquiv0, * pEquiv1; - assert( p->pHaig != NULL ); - assert( !Ivy_IsComplement(pObj) ); - if ( Ivy_ObjType(pObj) == IVY_BUF ) - pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); - else if ( Ivy_ObjType(pObj) == IVY_LATCH ) - { -// pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init ); - pEquiv0 = Ivy_ObjChild0Equiv(pObj); - pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); - pObj->pEquiv = Ivy_Latch( p->pHaig, pEquiv0, pObj->Init ); - } - else if ( Ivy_ObjType(pObj) == IVY_AND ) - { -// pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - pEquiv0 = Ivy_ObjChild0Equiv(pObj); - pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); - pEquiv1 = Ivy_ObjChild1Equiv(pObj); - pEquiv1 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv1)), Ivy_IsComplement(pEquiv1) ); - pObj->pEquiv = Ivy_And( p->pHaig, pEquiv0, pEquiv1 ); - } - else assert( 0 ); - // make sure the node points to the representative -// pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) ); -} - -/**Function************************************************************* - - Synopsis [Checks if the old node is in the TFI of the new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjIsInTfi_rec( Ivy_Obj_t * pObjNew, Ivy_Obj_t * pObjOld, int Levels ) -{ - if ( pObjNew == pObjOld ) - return 1; - if ( Levels == 0 || Ivy_ObjIsCi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) - return 0; - if ( Ivy_ObjIsInTfi_rec( Ivy_ObjFanin0(pObjNew), pObjOld, Levels - 1 ) ) - return 1; - if ( Ivy_ObjIsNode(pObjNew) && Ivy_ObjIsInTfi_rec( Ivy_ObjFanin1(pObjNew), pObjOld, Levels - 1 ) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sets the pair of equivalent nodes in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ) -{ - Ivy_Obj_t * pObjOldHaig, * pObjNewHaig; - Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR; - int fCompl; -//printf( "\nCreating choice for %d and %d in AIG\n", pObjOld->Id, Ivy_Regular(pObjNew)->Id ); - - assert( p->pHaig != NULL ); - assert( !Ivy_IsComplement(pObjOld) ); - // get pointers to the representatives of pObjOld and pObjNew - pObjOldHaig = pObjOld->pEquiv; - pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) ); - // get the classes - pObjOldHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjOldHaig)), Ivy_IsComplement(pObjOldHaig) ); - pObjNewHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjNewHaig)), Ivy_IsComplement(pObjNewHaig) ); - // get regular pointers - pObjOldHaigR = Ivy_Regular(pObjOldHaig); - pObjNewHaigR = Ivy_Regular(pObjNewHaig); - // check if there is phase difference between them - fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig)); - // if the class is the same, nothing to do - if ( pObjOldHaigR == pObjNewHaigR ) - return; - // if the second node belongs to a class, do not merge classes (for the time being) - if ( Ivy_ObjRefs(pObjOldHaigR) == 0 || pObjNewHaigR->pEquiv != NULL || - Ivy_ObjRefs(pObjNewHaigR) > 0 ) //|| Ivy_ObjIsInTfi_rec(pObjNewHaigR, pObjOldHaigR, 10) ) - { -/* - if ( pObjNewHaigR->pEquiv != NULL ) - printf( "c" ); - if ( Ivy_ObjRefs(pObjNewHaigR) > 0 ) - printf( "f" ); - printf( " " ); -*/ - p->pHaig->nClassesSkip++; - return; - } - - // add this node to the class of pObjOldHaig - assert( Ivy_ObjRefs(pObjOldHaigR) > 0 ); - assert( !Ivy_IsComplement(pObjOldHaigR->pEquiv) ); - if ( pObjOldHaigR->pEquiv == NULL ) - pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ); - else - pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl ); - pObjOldHaigR->pEquiv = pObjNewHaigR; -//printf( "Setting choice node %d -> %d.\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); - // update the class of the new node -// Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) ); -//printf( "Creating choice for %d and %d in HAIG\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); - -// if ( pObjOldHaigR->Id == 13 ) -// { -// Ivy_ManShow( p, 0 ); -// Ivy_ManShow( p->pHaig, 1 ); -// } -// if ( !Ivy_ManIsAcyclic( p->pHaig ) ) -// printf( "HAIG contains a cycle\n" ); -} - -/**Function************************************************************* - - Synopsis [Count the number of choices and choice nodes in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices ) -{ - Ivy_Obj_t * pObj; - int nChoices, nChoiceNodes, Counter, i; - assert( p->pHaig != NULL ); - nChoices = nChoiceNodes = 0; - Ivy_ManForEachObj( p->pHaig, pObj, i ) - { - if ( Ivy_ObjIsTerm(pObj) || i == 0 ) - continue; - if ( Ivy_ObjRefs(pObj) == 0 ) - continue; - Counter = Ivy_HaigObjCountClass( pObj ); - nChoiceNodes += (int)(Counter > 1); - nChoices += Counter - 1; -// if ( Counter > 1 ) -// printf( "Choice node %d %s\n", pObj->Id, Ivy_ObjIsLatch(pObj)? "(latch)": "" ); - } - *pnChoices = nChoices; - return nChoiceNodes; -} - -/**Function************************************************************* - - Synopsis [Prints statistics of the HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ) -{ - int nChoices, nChoiceNodes; - - assert( p->pHaig != NULL ); - - if ( fVerbose ) - { - printf( "Final : " ); - Ivy_ManPrintStats( p ); - printf( "HAIG : " ); - Ivy_ManPrintStats( p->pHaig ); - - // print choice node stats - nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices ); - printf( "Total choice nodes = %d. Total choices = %d. Skipped classes = %d.\n", - nChoiceNodes, nChoices, p->pHaig->nClassesSkip ); - } - - if ( Ivy_ManIsAcyclic( p->pHaig ) ) - { - if ( fVerbose ) - printf( "HAIG is acyclic\n" ); - } - else - printf( "HAIG contains a cycle\n" ); - -// if ( fVerbose ) -// Ivy_ManHaigSimulate( p ); -} - - -/**Function************************************************************* - - Synopsis [Applies the simulation rules.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 ) -{ - assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); - if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC ) - return IVY_INIT_DC; - if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 ) - return IVY_INIT_1; - return IVY_INIT_0; -} - -/**Function************************************************************* - - Synopsis [Applies the simulation rules.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_Init_t Ivy_ManHaigSimulateChoice( Ivy_Init_t In0, Ivy_Init_t In1 ) -{ - assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); - if ( (In0 == IVY_INIT_0 && In1 == IVY_INIT_1) || (In0 == IVY_INIT_1 && In1 == IVY_INIT_0) ) - { - printf( "Compatibility fails.\n" ); - return IVY_INIT_0; - } - if ( In0 == IVY_INIT_DC && In1 == IVY_INIT_DC ) - return IVY_INIT_DC; - if ( In0 != IVY_INIT_DC ) - return In0; - return In1; -} - -/**Function************************************************************* - - Synopsis [Simulate HAIG using modified 3-valued simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigSimulate( Ivy_Man_t * p ) -{ - Vec_Int_t * vNodes, * vLatches, * vLatchesD; - Ivy_Obj_t * pObj, * pTemp; - Ivy_Init_t In0, In1; - int i, k, Counter; - int fVerbose = 0; - - // check choices - Ivy_ManCheckChoices( p ); - - // switch to HAIG - assert( p->pHaig != NULL ); - p = p->pHaig; - -if ( fVerbose ) -Ivy_ManForEachPi( p, pObj, i ) -printf( "Setting PI %d\n", pObj->Id ); - - // collect latches and nodes in the DFS order - vNodes = Ivy_ManDfsSeq( p, &vLatches ); - -if ( fVerbose ) -Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) -printf( "Collected node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); - - // set the PI values - Ivy_ManConst1(p)->Init = IVY_INIT_1; - Ivy_ManForEachPi( p, pObj, i ) - pObj->Init = IVY_INIT_0; - - // set the latch values - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - pObj->Init = IVY_INIT_DC; - // set the latches of D to be determinate - vLatchesD = p->pData; - Ivy_ManForEachNodeVec( p, vLatchesD, pObj, i ) - pObj->Init = IVY_INIT_0; - - // perform several rounds of simulation - for ( k = 0; k < 10; k++ ) - { - // count the number of non-determinate values - Counter = 0; - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - Counter += ( pObj->Init == IVY_INIT_DC ); - printf( "Iter %d : Non-determinate = %d\n", k, Counter ); - - // simulate the internal nodes - Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) - { -if ( fVerbose ) -printf( "Processing node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); - In0 = Ivy_InitNotCond( Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) ); - In1 = Ivy_InitNotCond( Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) ); - pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 ); - // simulate the equivalence class if the node is a representative - if ( pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) - { -if ( fVerbose ) -printf( "Processing choice node %d\n", pObj->Id ); - In0 = pObj->Init; - assert( !Ivy_IsComplement(pObj->pEquiv) ); - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { -if ( fVerbose ) -printf( "Processing secondary node %d\n", pTemp->Id ); - In1 = Ivy_InitNotCond( pTemp->Init, Ivy_IsComplement(pTemp->pEquiv) ); - In0 = Ivy_ManHaigSimulateChoice( In0, In1 ); - } - pObj->Init = In0; - } - } - - // simulate the latches - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - { - pObj->Level = Ivy_ObjFanin0(pObj)->Init; -if ( fVerbose ) -printf( "Using latch %d with fanin %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id ); - } - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - pObj->Init = pObj->Level, pObj->Level = 0; - } - // free arrays - Vec_IntFree( vNodes ); - Vec_IntFree( vLatches ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyIsop.c b/src/temp/ivy/ivyIsop.c deleted file mode 100644 index 1887eb6a..00000000 --- a/src/temp/ivy/ivyIsop.c +++ /dev/null @@ -1,328 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyIsop.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Computing irredundant SOP using truth table.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyIsop.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" -#include "mem.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// ISOP computation fails if intermediate memory usage exceed this limit -#define IVY_ISOP_MEM_LIMIT 16*4096 - -// intermediate ISOP representation -typedef struct Ivy_Sop_t_ Ivy_Sop_t; -struct Ivy_Sop_t_ -{ - unsigned * pCubes; - int nCubes; -}; - -// static procedures to compute ISOP -static unsigned * Ivy_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Ivy_Sop_t * pcRes, Vec_Int_t * vStore ); -static unsigned Ivy_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Ivy_Sop_t * pcRes, Vec_Int_t * vStore ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes ISOP from TT.] - - Description [Returns the cover in vCover. Uses the rest of array in vCover - as an intermediate memory storage. Returns the cover with -1 cubes, if the - the computation exceeded the memory limit (IVY_ISOP_MEM_LIMIT words of - intermediate data).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vCover, int fTryBoth ) -{ - Ivy_Sop_t cRes, * pcRes = &cRes; - Ivy_Sop_t cRes2, * pcRes2 = &cRes2; - unsigned * pResult; - int RetValue = 0; - assert( nVars >= 0 && nVars < 16 ); - // if nVars < 5, make sure it does not depend on those vars -// for ( i = nVars; i < 5; i++ ) -// assert( !Extra_TruthVarInSupport(puTruth, 5, i) ); - // prepare memory manager - Vec_IntClear( vCover ); - Vec_IntGrow( vCover, IVY_ISOP_MEM_LIMIT ); - // compute ISOP for the direct polarity - pResult = Ivy_TruthIsop_rec( puTruth, puTruth, nVars, pcRes, vCover ); - if ( pcRes->nCubes == -1 ) - { - vCover->nSize = -1; - return 0; - } - assert( Extra_TruthIsEqual( puTruth, pResult, nVars ) ); - if ( fTryBoth ) - { - // compute ISOP for the complemented polarity - Extra_TruthNot( puTruth, puTruth, nVars ); - pResult = Ivy_TruthIsop_rec( puTruth, puTruth, nVars, pcRes2, vCover ); - if ( pcRes2->nCubes >= 0 ) - { - assert( Extra_TruthIsEqual( puTruth, pResult, nVars ) ); - if ( pcRes->nCubes > pcRes2->nCubes ) - { - RetValue = 1; - pcRes = pcRes2; - } - } - Extra_TruthNot( puTruth, puTruth, nVars ); - } -// printf( "%d ", vCover->nSize ); - // move the cover representation to the beginning of the memory buffer - memmove( vCover->pArray, pcRes->pCubes, pcRes->nCubes * sizeof(unsigned) ); - Vec_IntShrink( vCover, pcRes->nCubes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Computes ISOP 6 variables or more.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ivy_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Ivy_Sop_t * pcRes, Vec_Int_t * vStore ) -{ - Ivy_Sop_t cRes0, cRes1, cRes2; - Ivy_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; - unsigned * puRes0, * puRes1, * puRes2; - unsigned * puOn0, * puOn1, * puOnDc0, * puOnDc1, * pTemp, * pTemp0, * pTemp1; - int i, k, Var, nWords, nWordsAll; -// assert( Extra_TruthIsImply( puOn, puOnDc, nVars ) ); - // allocate room for the resulting truth table - nWordsAll = Extra_TruthWordNum( nVars ); - pTemp = Vec_IntFetch( vStore, nWordsAll ); - if ( pTemp == NULL ) - { - pcRes->nCubes = -1; - return NULL; - } - // check for constants - if ( Extra_TruthIsConst0( puOn, nVars ) ) - { - pcRes->nCubes = 0; - pcRes->pCubes = NULL; - Extra_TruthClear( pTemp, nVars ); - return pTemp; - } - if ( Extra_TruthIsConst1( puOnDc, nVars ) ) - { - pcRes->nCubes = 1; - pcRes->pCubes = Vec_IntFetch( vStore, 1 ); - if ( pcRes->pCubes == NULL ) - { - pcRes->nCubes = -1; - return NULL; - } - pcRes->pCubes[0] = 0; - Extra_TruthFill( pTemp, nVars ); - return pTemp; - } - assert( nVars > 0 ); - // find the topmost var - for ( Var = nVars-1; Var >= 0; Var-- ) - if ( Extra_TruthVarInSupport( puOn, nVars, Var ) || - Extra_TruthVarInSupport( puOnDc, nVars, Var ) ) - break; - assert( Var >= 0 ); - // consider a simple case when one-word computation can be used - if ( Var < 5 ) - { - unsigned uRes = Ivy_TruthIsop5_rec( puOn[0], puOnDc[0], Var+1, pcRes, vStore ); - for ( i = 0; i < nWordsAll; i++ ) - pTemp[i] = uRes; - return pTemp; - } - assert( Var >= 5 ); - nWords = Extra_TruthWordNum( Var ); - // cofactor - puOn0 = puOn; puOn1 = puOn + nWords; - puOnDc0 = puOnDc; puOnDc1 = puOnDc + nWords; - pTemp0 = pTemp; pTemp1 = pTemp + nWords; - // solve for cofactors - Extra_TruthSharp( pTemp0, puOn0, puOnDc1, Var ); - puRes0 = Ivy_TruthIsop_rec( pTemp0, puOnDc0, Var, pcRes0, vStore ); - if ( pcRes0->nCubes == -1 ) - { - pcRes->nCubes = -1; - return NULL; - } - Extra_TruthSharp( pTemp1, puOn1, puOnDc0, Var ); - puRes1 = Ivy_TruthIsop_rec( pTemp1, puOnDc1, Var, pcRes1, vStore ); - if ( pcRes1->nCubes == -1 ) - { - pcRes->nCubes = -1; - return NULL; - } - Extra_TruthSharp( pTemp0, puOn0, puRes0, Var ); - Extra_TruthSharp( pTemp1, puOn1, puRes1, Var ); - Extra_TruthOr( pTemp0, pTemp0, pTemp1, Var ); - Extra_TruthAnd( pTemp1, puOnDc0, puOnDc1, Var ); - puRes2 = Ivy_TruthIsop_rec( pTemp0, pTemp1, Var, pcRes2, vStore ); - if ( pcRes2->nCubes == -1 ) - { - pcRes->nCubes = -1; - return NULL; - } - // create the resulting cover - pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; - pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); - if ( pcRes->pCubes == NULL ) - { - pcRes->nCubes = -1; - return NULL; - } - k = 0; - for ( i = 0; i < pcRes0->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+1)); - for ( i = 0; i < pcRes1->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+0)); - for ( i = 0; i < pcRes2->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes2->pCubes[i]; - assert( k == pcRes->nCubes ); - // create the resulting truth table - Extra_TruthOr( pTemp0, puRes0, puRes2, Var ); - Extra_TruthOr( pTemp1, puRes1, puRes2, Var ); - // copy the table if needed - nWords <<= 1; - for ( i = 1; i < nWordsAll/nWords; i++ ) - for ( k = 0; k < nWords; k++ ) - pTemp[i*nWords + k] = pTemp[k]; - // verify in the end -// assert( Extra_TruthIsImply( puOn, pTemp, nVars ) ); -// assert( Extra_TruthIsImply( pTemp, puOnDc, nVars ) ); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [Computes ISOP for 5 variables or less.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Ivy_Sop_t * pcRes, Vec_Int_t * vStore ) -{ - unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - Ivy_Sop_t cRes0, cRes1, cRes2; - Ivy_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; - unsigned uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2; - int i, k, Var; - assert( nVars <= 5 ); - assert( (uOn & ~uOnDc) == 0 ); - if ( uOn == 0 ) - { - pcRes->nCubes = 0; - pcRes->pCubes = NULL; - return 0; - } - if ( uOnDc == 0xFFFFFFFF ) - { - pcRes->nCubes = 1; - pcRes->pCubes = Vec_IntFetch( vStore, 1 ); - if ( pcRes->pCubes == NULL ) - { - pcRes->nCubes = -1; - return 0; - } - pcRes->pCubes[0] = 0; - return 0xFFFFFFFF; - } - assert( nVars > 0 ); - // find the topmost var - for ( Var = nVars-1; Var >= 0; Var-- ) - if ( Extra_TruthVarInSupport( &uOn, 5, Var ) || - Extra_TruthVarInSupport( &uOnDc, 5, Var ) ) - break; - assert( Var >= 0 ); - // cofactor - uOn0 = uOn1 = uOn; - uOnDc0 = uOnDc1 = uOnDc; - Extra_TruthCofactor0( &uOn0, Var + 1, Var ); - Extra_TruthCofactor1( &uOn1, Var + 1, Var ); - Extra_TruthCofactor0( &uOnDc0, Var + 1, Var ); - Extra_TruthCofactor1( &uOnDc1, Var + 1, Var ); - // solve for cofactors - uRes0 = Ivy_TruthIsop5_rec( uOn0 & ~uOnDc1, uOnDc0, Var, pcRes0, vStore ); - if ( pcRes0->nCubes == -1 ) - { - pcRes->nCubes = -1; - return 0; - } - uRes1 = Ivy_TruthIsop5_rec( uOn1 & ~uOnDc0, uOnDc1, Var, pcRes1, vStore ); - if ( pcRes1->nCubes == -1 ) - { - pcRes->nCubes = -1; - return 0; - } - uRes2 = Ivy_TruthIsop5_rec( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pcRes2, vStore ); - if ( pcRes2->nCubes == -1 ) - { - pcRes->nCubes = -1; - return 0; - } - // create the resulting cover - pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; - pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); - if ( pcRes->pCubes == NULL ) - { - pcRes->nCubes = -1; - return 0; - } - k = 0; - for ( i = 0; i < pcRes0->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+1)); - for ( i = 0; i < pcRes1->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+0)); - for ( i = 0; i < pcRes2->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes2->pCubes[i]; - assert( k == pcRes->nCubes ); - // derive the final truth table - uRes2 |= (uRes0 & ~uMasks[Var]) | (uRes1 & uMasks[Var]); -// assert( (uOn & ~uRes2) == 0 ); -// assert( (uRes2 & ~uOnDc) == 0 ); - return uRes2; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyMan.c b/src/temp/ivy/ivyMan.c deleted file mode 100644 index ac58cb61..00000000 --- a/src/temp/ivy/ivyMan.c +++ /dev/null @@ -1,546 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [AIG manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManStart() -{ - Ivy_Man_t * p; - // start the manager - p = ALLOC( Ivy_Man_t, 1 ); - memset( p, 0, sizeof(Ivy_Man_t) ); - // perform initializations - p->Ghost.Id = -1; - p->nTravIds = 1; - p->fCatchExor = 1; - // allocate arrays for nodes - p->vPis = Vec_PtrAlloc( 100 ); - p->vPos = Vec_PtrAlloc( 100 ); - p->vBufs = Vec_PtrAlloc( 100 ); - p->vObjs = Vec_PtrAlloc( 100 ); - // prepare the internal memory manager - Ivy_ManStartMemory( p ); - // create the constant node - p->pConst1 = Ivy_ManFetchMemory( p ); - p->pConst1->fPhase = 1; - Vec_PtrPush( p->vObjs, p->pConst1 ); - p->nCreated = 1; - // start the table - p->nTableSize = 10007; - p->pTable = ALLOC( int, p->nTableSize ); - memset( p->pTable, 0, sizeof(int) * p->nTableSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ) -{ - Ivy_Man_t * pNew; - Ivy_Obj_t * pObj; - int i; - // create the new manager - pNew = Ivy_ManStart(); - // create the PIs - Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); - Ivy_ManForEachPi( p, pObj, i ) - pObj->pEquiv = Ivy_ObjCreatePi(pNew); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ) -{ - Vec_Int_t * vNodes, * vLatches; - Ivy_Man_t * pNew; - Ivy_Obj_t * pObj; - int i; - // collect latches and nodes in the DFS order - vNodes = Ivy_ManDfsSeq( p, &vLatches ); - // create the new manager - pNew = Ivy_ManStart(); - // create the PIs - Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); - Ivy_ManForEachPi( p, pObj, i ) - pObj->pEquiv = Ivy_ObjCreatePi(pNew); - // create the fake PIs for latches - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - pObj->pEquiv = Ivy_ObjCreatePi(pNew); - // duplicate internal nodes - Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) - if ( Ivy_ObjIsBuf(pObj) ) - pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); - else - pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - // add the POs - Ivy_ManForEachPo( p, pObj, i ) - Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) ); - // transform additional PI nodes into latches and connect them - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - { - assert( !Ivy_ObjFaninC0(pObj) ); - pObj->pEquiv->Type = IVY_LATCH; - pObj->pEquiv->Init = pObj->Init; - Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL ); - } - // shrink the arrays - Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) ); - // update the counters of different objects - pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p); - pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p); - // free arrays - Vec_IntFree( vNodes ); - Vec_IntFree( vLatches ); - // make sure structural hashing did not change anything - assert( Ivy_ManNodeNum(p) == Ivy_ManNodeNum(pNew) ); - assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) ); - // check the resulting network - if ( !Ivy_ManCheck(pNew) ) - printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ) -{ - Vec_Ptr_t * vMapping; - Ivy_Man_t * pNew; - Ivy_Obj_t * pObj; - int i, f, nPis, nPos, nIdMax; - assert( Ivy_ManLatchNum(pMan) == 0 ); - assert( nFrames > 0 ); - // prepare the mapping - nPis = Ivy_ManPiNum(pMan) - nLatches; - nPos = Ivy_ManPoNum(pMan) - nLatches; - nIdMax = Ivy_ManObjIdMax(pMan); - // create the new manager - pNew = Ivy_ManStart(); - // set the starting values of latch inputs - for ( i = 0; i < nLatches; i++ ) - Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew); - // add timeframes - vMapping = Vec_PtrStart( nIdMax * nFrames + 1 ); - for ( f = 0; f < nFrames; f++ ) - { - // create PIs - Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew); - for ( i = 0; i < nPis; i++ ) - Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew); - // transfer values to latch outputs - for ( i = 0; i < nLatches; i++ ) - Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv; - // perform strashing - Ivy_ManForEachNode( pMan, pObj, i ) - pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - // create POs - for ( i = 0; i < nPos; i++ ) - Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) ); - // set the results of latch inputs - for ( i = 0; i < nLatches; i++ ) - Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i)); - // save the pointers in this frame - Ivy_ManForEachObj( pMan, pObj, i ) - Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv ); - } - // connect latches - if ( !fInit ) - for ( i = 0; i < nLatches; i++ ) - Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv ); - // remove dangling nodes - Ivy_ManCleanup(pNew); - *pvMapping = vMapping; - // check the resulting network - if ( !Ivy_ManCheck(pNew) ) - printf( "Ivy_ManFrames(): The check has failed.\n" ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStop( Ivy_Man_t * p ) -{ - if ( p->time1 ) { PRT( "Update lev ", p->time1 ); } - if ( p->time2 ) { PRT( "Update levR ", p->time2 ); } -// Ivy_TableProfile( p ); -// if ( p->vFanouts ) Ivy_ManStopFanout( p ); - if ( p->vChunks ) Ivy_ManStopMemory( p ); - if ( p->vRequired ) Vec_IntFree( p->vRequired ); - if ( p->vPis ) Vec_PtrFree( p->vPis ); - if ( p->vPos ) Vec_PtrFree( p->vPos ); - if ( p->vBufs ) Vec_PtrFree( p->vBufs ); - if ( p->vObjs ) Vec_PtrFree( p->vObjs ); - free( p->pTable ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Removes nodes without fanout.] - - Description [Returns the number of dangling nodes removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCleanup( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pNode; - int i, nNodesOld; - nNodesOld = Ivy_ManNodeNum(p); - Ivy_ManForEachObj( p, pNode, i ) - if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) - if ( Ivy_ObjRefs(pNode) == 0 ) - Ivy_ObjDelete_rec( p, pNode, 1 ); -//printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) ); - return nNodesOld - Ivy_ManNodeNum(p); -} - -/**Function************************************************************* - - Synopsis [Marks nodes reachable from the given one.] - - Description [Returns the number of dangling nodes removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj ) -{ - if ( Ivy_ObjIsMarkA(pObj) ) - return; - Ivy_ObjSetMarkA(pObj); - if ( pObj->pFanin0 != NULL ) - Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) ); - if ( pObj->pFanin1 != NULL ) - Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Removes logic that does not feed into POs.] - - Description [Returns the number of dangling nodes removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCleanupSeq( Ivy_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Ivy_Obj_t * pObj; - int i, RetValue; - // mark the constant and PIs - Ivy_ObjSetMarkA( Ivy_ManConst1(p) ); - Ivy_ManForEachPi( p, pObj, i ) - Ivy_ObjSetMarkA( pObj ); - // mark nodes visited from POs - Ivy_ManForEachPo( p, pObj, i ) - Ivy_ManCleanupSeq_rec( pObj ); - // collect unmarked nodes - vNodes = Vec_PtrAlloc( 100 ); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( Ivy_ObjIsMarkA(pObj) ) - Ivy_ObjClearMarkA(pObj); - else - Vec_PtrPush( vNodes, pObj ); - } - if ( Vec_PtrSize(vNodes) == 0 ) - { - Vec_PtrFree( vNodes ); -//printf( "Sequential sweep cleaned out %d nodes.\n", 0 ); - return 0; - } - // disconnect the marked objects - Vec_PtrForEachEntry( vNodes, pObj, i ) - Ivy_ObjDisconnect( p, pObj ); - // remove the dangling objects - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) ); - assert( Ivy_ObjRefs(pObj) == 0 ); - // update node counters of the manager - p->nObjs[pObj->Type]--; - p->nDeleted++; - // delete buffer from the array of buffers - if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) - Vec_PtrRemove( p->vBufs, pObj ); - // free the node - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); - Ivy_ManRecycleMemory( p, pObj ); - } - // return the number of nodes freed - RetValue = Vec_PtrSize(vNodes); - Vec_PtrFree( vNodes ); -//printf( "Sequential sweep cleaned out %d nodes.\n", RetValue ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Checks if latches form self-loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot ) -{ - if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) ) - return 0; - if ( pLatch == pLatchRoot ) - return 1; - return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot ); -} - -/**Function************************************************************* - - Synopsis [Checks if latches form self-loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch ) -{ - if ( !Ivy_ObjIsLatch(pLatch) ) - return 0; - return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch ); -} - - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ) -{ - Ivy_Obj_t * pNode; - int LimitFactor = 5; - int NodeBeg = Ivy_ManNodeNum(p); - int nSteps; - for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) - { - pNode = Vec_PtrEntryLast(p->vBufs); - while ( Ivy_ObjIsBuf(pNode) ) - pNode = Ivy_ObjReadFirstFanout( p, pNode ); - // check if this buffer should remain - if ( Ivy_ManLatchIsSelfFeed(pNode) ) - { - Vec_PtrPop(p->vBufs); - continue; - } -//printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id ); -//printf( "Latch num %d\n", Ivy_ManLatchNum(p) ); - Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel ); - if ( nSteps > NodeBeg * LimitFactor ) - { - printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor ); - printf( "This circuit cannot be forward-retimed completely. Quitting.\n" ); - break; - } - } - printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) ); - return nSteps; -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManPrintStats( Ivy_Man_t * p ) -{ - printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) ); - printf( "A = %7d. ", Ivy_ManAndNum(p) ); - printf( "L = %5d. ", Ivy_ManLatchNum(p) ); -// printf( "X = %d. ", Ivy_ManExorNum(p) ); -// printf( "B = %3d. ", Ivy_ManBufNum(p) ); - printf( "MaxID = %7d. ", Ivy_ManObjIdMax(p) ); -// printf( "Cre = %d. ", p->nCreated ); -// printf( "Del = %d. ", p->nDeleted ); - printf( "Lev = %3d. ", Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Converts a combinational AIG manager into a sequential one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ) -{ - Ivy_Obj_t * pObj, * pLatch; - Ivy_Init_t Init; - int i; - if ( nLatches == 0 ) - return; - assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) ); - assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) ); - assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) ); - assert( Vec_PtrSize( p->vBufs ) == 0 ); - // create fanouts - if ( p->fFanout == 0 ) - Ivy_ManStartFanout( p ); - // collect the POs to be converted into latches - for ( i = 0; i < nLatches; i++ ) - { - // get the latch value - Init = pInits? pInits[i] : IVY_INIT_0; - // create latch - pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i ); - pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init ); - Ivy_ObjDisconnect( p, pObj ); - // recycle the old PO object - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); - Ivy_ManRecycleMemory( p, pObj ); - // convert the corresponding PI to a buffer and connect it to the latch - pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i ); - pObj->Type = IVY_BUF; - Ivy_ObjConnect( p, pObj, pLatch, NULL ); - // save the buffer - Vec_PtrPush( p->vBufs, pObj ); - } - // shrink the arrays - Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches ); - Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches ); - // update the counters of different objects - p->nObjs[IVY_PI] -= nLatches; - p->nObjs[IVY_PO] -= nLatches; - p->nObjs[IVY_BUF] += nLatches; - p->nDeleted -= 2 * nLatches; - // remove dangling nodes - Ivy_ManCleanup(p); - Ivy_ManCleanupSeq(p); -/* - // check for dangling nodes - Ivy_ManForEachObj( p, pObj, i ) - if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) ) - { - assert( Ivy_ObjRefs(pObj) > 0 ); - assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) ); - } -*/ - // perform hashing by propagating the buffers - Ivy_ManPropagateBuffers( p, 0 ); - if ( Ivy_ManBufNum(p) ) - printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) ); - // fix the levels - Ivy_ManResetLevels( p ); - // check the resulting network - if ( !Ivy_ManCheck(p) ) - printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyMem.c b/src/temp/ivy/ivyMem.c deleted file mode 100644 index 09c73c49..00000000 --- a/src/temp/ivy/ivyMem.c +++ /dev/null @@ -1,115 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyMem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Memory management for the AIG nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// memory management -#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes -#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStartMemory( Ivy_Man_t * p ) -{ - p->vChunks = Vec_PtrAlloc( 128 ); - p->vPages = Vec_PtrAlloc( 128 ); -} - -/**Function************************************************************* - - Synopsis [Stops the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStopMemory( Ivy_Man_t * p ) -{ - void * pMemory; - int i; - Vec_PtrForEachEntry( p->vChunks, pMemory, i ) - free( pMemory ); - Vec_PtrFree( p->vChunks ); - Vec_PtrFree( p->vPages ); - p->pListFree = NULL; -} - -/**Function************************************************************* - - Synopsis [Allocates additional memory for the nodes.] - - Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. - Records the pointer to the AIG manager in the -1 entry.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManAddMemory( Ivy_Man_t * p ) -{ - char * pMemory; - int i, nBytes; - assert( sizeof(Ivy_Obj_t) <= 64 ); - assert( p->pListFree == NULL ); -// assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); - // allocate new memory page - nBytes = sizeof(Ivy_Obj_t) * (1<vChunks, pMemory ); - // align memory at the 32-byte boundary - pMemory = pMemory + 64 - (((int)pMemory) & 63); - // remember the manager in the first entry - Vec_PtrPush( p->vPages, pMemory ); - // break the memory down into nodes - p->pListFree = (Ivy_Obj_t *)pMemory; - for ( i = 1; i <= IVY_PAGE_MASK; i++ ) - { - *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t); - pMemory += sizeof(Ivy_Obj_t); - } - *((char **)pMemory) = NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyMulti.c b/src/temp/ivy/ivyMulti.c deleted file mode 100644 index a7970156..00000000 --- a/src/temp/ivy/ivyMulti.c +++ /dev/null @@ -1,301 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyMulti.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Constructing multi-input AND/EXOR gates.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IVY_EVAL_LIMIT 128 - -typedef struct Ivy_Eva_t_ Ivy_Eva_t; -struct Ivy_Eva_t_ -{ - Ivy_Obj_t * pArg; // the argument node - unsigned Mask; // the mask of covered nodes - int Weight; // the number of covered nodes -}; - -static void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ); -static int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Constructs a balanced tree while taking sharing into account.] - - Description [Returns 1 if the implementation exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols ) -{ - static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT]; - Ivy_Eva_t * pEval, * pFan0, * pFan1; - Ivy_Obj_t * pObj, * pTemp; - int nEvals, nEvalsOld, i, k, x, nLeaves; - unsigned uMaskAll; - - // consider special cases - nLeaves = Vec_PtrSize(vLeaves); - assert( nLeaves > 2 ); - if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT ) - return 0; -// if ( nLeaves == 1 ) -// return Vec_PtrEntry( vLeaves, 0 ); -// if ( nLeaves == 2 ) -// return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type ); - - // set the leaf entries - uMaskAll = ((1 << nLeaves) - 1); - nEvals = 0; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - { - pEval = pEvals + nEvals; - pEval->pArg = pObj; - pEval->Mask = (1 << nEvals); - pEval->Weight = 1; - // mark the leaf - Ivy_Regular(pObj)->TravId = nEvals; - nEvals++; - } - - // propagate masks through the cone - Vec_PtrForEachEntry( vCone, pObj, i ) - { - pObj->TravId = nEvals + i; - if ( Ivy_ObjIsBuf(pObj) ) - pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask; - else - pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask; - } - - // set the internal entries - Vec_PtrForEachEntry( vCone, pObj, i ) - { - if ( i == Vec_PtrSize(vCone) - 1 ) - break; - // skip buffers - if ( Ivy_ObjIsBuf(pObj) ) - continue; - // skip nodes without external fanout - if ( Ivy_ObjRefs(pObj) == 0 ) - continue; - assert( !Ivy_IsComplement(pObj) ); - pEval = pEvals + nEvals; - pEval->pArg = pObj; - pEval->Mask = pEvals[pObj->TravId].Mask; - pEval->Weight = Extra_WordCountOnes(pEval->Mask); - // mark the node - pObj->TravId = nEvals; - nEvals++; - } - - // find the available nodes - nEvalsOld = nEvals; - for ( i = 1; i < nEvals; i++ ) - for ( k = 0; k < i; k++ ) - { - pFan0 = pEvals + i; - pFan1 = pEvals + k; - pTemp = Ivy_TableLookup(p, Ivy_ObjCreateGhost(p, pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE)); - // skip nodes in the cone - if ( pTemp == NULL || pTemp->fMarkB ) - continue; - // skip the leaves - for ( x = 0; x < nLeaves; x++ ) - if ( pTemp == Ivy_Regular(vLeaves->pArray[x]) ) - break; - if ( x < nLeaves ) - continue; - pEval = pEvals + nEvals; - pEval->pArg = pTemp; - pEval->Mask = pFan0->Mask | pFan1->Mask; - pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight; - // save the argument - pObj->TravId = nEvals; - nEvals++; - // quit if the number of entries exceeded the limit - if ( nEvals == IVY_EVAL_LIMIT ) - goto Outside; - // quit if we found an acceptable implementation - if ( pEval->Mask == uMaskAll ) - goto Outside; - } -Outside: - -// Ivy_MultiPrint( pEvals, nLeaves, nEvals ); - if ( !Ivy_MultiCover( p, pEvals, nLeaves, nEvals, nLimit, vSols ) ) - return 0; - assert( Vec_PtrSize( vSols ) > 0 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes how many uncovered ones this one covers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ) -{ - Ivy_Eva_t * pEval; - int i, k; - for ( i = nLeaves; i < nEvals; i++ ) - { - pEval = pEvals + i; - printf( "%2d (id = %5d) : |", i-nLeaves, Ivy_ObjId(pEval->pArg) ); - for ( k = 0; k < nLeaves; k++ ) - { - if ( pEval->Mask & (1 << k) ) - printf( "+" ); - else - printf( " " ); - } - printf( "| Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) ); - } -} - -/**Function************************************************************* - - Synopsis [Computes how many uncovered ones this one covers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound ) -{ - assert( uMask & ~uFound ); - if ( (uMask & uFound) == 0 ) - return nMaskOnes; - return Extra_WordCountOnes( uMask & ~uFound ); -} - -/**Function************************************************************* - - Synopsis [Finds the cover.] - - Description [Returns 1 if the cover is found.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ) -{ - int fVerbose = 0; - Ivy_Eva_t * pEval, * pEvalBest; - unsigned uMaskAll, uFound, uTemp; - int i, k, BestK, WeightBest, WeightCur, LevelBest, LevelCur; - uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1); - uFound = 0; - // solve the covering problem - if ( fVerbose ) - printf( "Solution: " ); - Vec_PtrClear( vSols ); - for ( i = 0; i < nLimit; i++ ) - { - BestK = -1; - for ( k = nEvals - 1; k >= 0; k-- ) - { - pEval = pEvals + k; - if ( (pEval->Mask & ~uFound) == 0 ) - continue; - if ( BestK == -1 ) - { - BestK = k; - pEvalBest = pEval; - WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound ); - LevelBest = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) ); - continue; - } - // compare BestK and the new one (k) - WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound ); - LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) ); - if ( WeightBest < WeightCur || - (WeightBest == WeightCur && LevelBest > LevelCur) ) - { - BestK = k; - pEvalBest = pEval; - WeightBest = WeightCur; - LevelBest = LevelCur; - } - } - assert( BestK != -1 ); - // if the cost is only 1, take the leaf - if ( WeightBest == 1 && BestK >= nLeaves ) - { - uTemp = (pEvalBest->Mask & ~uFound); - for ( k = 0; k < nLeaves; k++ ) - if ( uTemp & (1 << k) ) - break; - assert( k < nLeaves ); - BestK = k; - pEvalBest = pEvals + BestK; - } - if ( fVerbose ) - { - if ( BestK < nLeaves ) - printf( "L(%d) ", BestK ); - else - printf( "%d ", BestK - nLeaves ); - } - // update the found set - Vec_PtrPush( vSols, pEvalBest->pArg ); - uFound |= pEvalBest->Mask; - if ( uFound == uMaskAll ) - break; - } - if ( uFound == uMaskAll ) - { - if ( fVerbose ) - printf( " Found \n\n" ); - return 1; - } - else - { - if ( fVerbose ) - printf( " Not found \n\n" ); - return 0; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyMulti8.c b/src/temp/ivy/ivyMulti8.c deleted file mode 100644 index 059d1500..00000000 --- a/src/temp/ivy/ivyMulti8.c +++ /dev/null @@ -1,427 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyMulti.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Constructing multi-input AND/EXOR gates.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ivy_Eval_t_ Ivy_Eval_t; -struct Ivy_Eval_t_ -{ - unsigned Mask : 5; // the mask of covered nodes - unsigned Weight : 3; // the number of covered nodes - unsigned Cost : 4; // the number of overlapping nodes - unsigned Level : 12; // the level of this node - unsigned Fan0 : 4; // the first fanin - unsigned Fan1 : 4; // the second fanin -}; - -static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); -static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ); -static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ); -static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Constructs the well-balanced tree of gates.] - - Description [Disregards levels and possible logic sharing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type ); - pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type ); - return Ivy_Oper( pObj1, pObj2, Type ); -} - -/**Function************************************************************* - - Synopsis [Constructs a balanced tree while taking sharing into account.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type ) -{ - static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5}; - static Ivy_Eval_t pEvals[15+15*14/2]; - static Ivy_Obj_t * pArgs[16]; - Ivy_Eval_t * pEva, * pEvaBest; - int nArgsNew, nEvals, i, k; - Ivy_Obj_t * pTemp; - - // consider the case of one argument - assert( nArgs > 0 ); - if ( nArgs == 1 ) - return pArgsInit[0]; - // consider the case of two arguments - if ( nArgs == 2 ) - return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type ); - -//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" ); - - // set the initial ones - for ( i = 0; i < nArgs; i++ ) - { - pArgs[i] = pArgsInit[i]; - pEva = pEvals + i; - pEva->Mask = (1 << i); - pEva->Weight = 1; - pEva->Cost = 0; - pEva->Level = Ivy_Regular(pArgs[i])->Level; - pEva->Fan0 = 0; - pEva->Fan1 = 0; - } - - // find the available nodes - pEvaBest = pEvals; - nArgsNew = nArgs; - for ( i = 1; i < nArgsNew; i++ ) - for ( k = 0; k < i; k++ ) - if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) ) - { - pEva = pEvals + nArgsNew; - pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; - pEva->Weight = NumBits[pEva->Mask]; - pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; - pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); - pEva->Fan0 = k; - pEva->Fan1 = i; -// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) ); - // compare - if ( pEvaBest->Weight < pEva->Weight || - pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || - pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) - pEvaBest = pEva; - // save the argument - pArgs[nArgsNew++] = pTemp; - if ( nArgsNew == 15 ) - goto Outside; - } -Outside: - -// printf( "Best = %d.\n", pEvaBest - pEvals ); - - // the case of no common nodes - if ( nArgsNew == nArgs ) - { - Ivy_MultiSort( pArgs, nArgs ); - return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); - } - // the case of one common node - if ( nArgsNew == nArgs + 1 ) - { - assert( pEvaBest - pEvals == nArgs ); - k = 0; - for ( i = 0; i < nArgs; i++ ) - if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 ) - pArgs[k++] = pArgs[i]; - pArgs[k++] = pArgs[nArgs]; - assert( k == nArgs - 1 ); - nArgs = k; - Ivy_MultiSort( pArgs, nArgs ); - return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); - } - // the case when there is a node that covers everything - if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) ) - return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); - - // evaluate node pairs - nEvals = nArgsNew; - for ( i = 1; i < nArgsNew; i++ ) - for ( k = 0; k < i; k++ ) - { - pEva = pEvals + nEvals; - pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; - pEva->Weight = NumBits[pEva->Mask]; - pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; - pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); - pEva->Fan0 = k; - pEva->Fan1 = i; - // compare - if ( pEvaBest->Weight < pEva->Weight || - pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || - pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) - pEvaBest = pEva; - // save the argument - nEvals++; - } - assert( pEvaBest - pEvals >= nArgsNew ); - -// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 ); - - // get the best implementation - pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); - - // collect those not covered by EvaBest - k = 0; - for ( i = 0; i < nArgs; i++ ) - if ( (pEvaBest->Mask & (1 << i)) == 0 ) - pArgs[k++] = pArgs[i]; - pArgs[k++] = pTemp; - assert( k == nArgs - (int)pEvaBest->Weight + 1 ); - nArgs = k; - Ivy_MultiSort( pArgs, nArgs ); - return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements multi-input AND/EXOR operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pNode0, * pNode1; - if ( iNum < nArgs ) - return pArgs[iNum]; - pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type ); - pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type ); - return Ivy_Oper( pNode0, pNode1, Type ); -} - -/**Function************************************************************* - - Synopsis [Selection-sorts the nodes in the decreasing over of level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ) -{ - Ivy_Obj_t * pTemp; - int i, j, iBest; - - for ( i = 0; i < nArgs-1; i++ ) - { - iBest = i; - for ( j = i+1; j < nArgs; j++ ) - if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level ) - iBest = j; - pTemp = pArgs[i]; - pArgs[i] = pArgs[iBest]; - pArgs[iBest] = pTemp; - } -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ) -{ - Ivy_Obj_t * pNode1, * pNode2; - int i; - // try to find the node in the array - for ( i = 0; i < nArgs; i++ ) - if ( pArray[i] == pNode ) - return nArgs; - // put the node last - pArray[nArgs++] = pNode; - // find the place to put the new node - for ( i = nArgs-1; i > 0; i-- ) - { - pNode1 = pArray[i ]; - pNode2 = pArray[i-1]; - if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level ) - break; - pArray[i ] = pNode2; - pArray[i-1] = pNode1; - } - return nArgs; -} - -/**Function************************************************************* - - Synopsis [Balances the array recursively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pNodeNew; - // consider the case of one argument - assert( nArgs > 0 ); - if ( nArgs == 1 ) - return pArgs[0]; - // consider the case of two arguments - if ( nArgs == 2 ) - return Ivy_Oper( pArgs[0], pArgs[1], Type ); - // get the last two nodes - pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type ); - // add the new node - nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew ); - return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements multi-input AND/EXOR operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pTemp; - int i, k; - int nArgsOld = nArgs; - for ( i = 0; i < nArgs; i++ ) - printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level ); - for ( i = 1; i < nArgs; i++ ) - for ( k = 0; k < i; k++ ) - { - pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)); - if ( pTemp != NULL ) - { - printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i ); - pArgs[nArgs++] = pTemp; - } - } - printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld ); - return NULL; -} - - - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pArgsRef[5], * pTemp; - int i, k, m, nArgsNew, Counter = 0; - - -//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" ); - - - assert( Type == IVY_AND || Type == IVY_EXOR ); - assert( nArgs > 0 ); - if ( nArgs == 1 ) - return pArgs[0]; - - // find the nodes with more than one fanout - nArgsNew = 0; - for ( i = 0; i < nArgs; i++ ) - if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 ) - pArgsRef[nArgsNew++] = pArgs[i]; - - // go through pairs - if ( nArgsNew >= 2 ) - for ( i = 0; i < nArgsNew; i++ ) - for ( k = i + 1; k < nArgsNew; k++ ) - if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) - Counter++; -// printf( "%d", Counter ); - - // go through pairs - if ( nArgsNew >= 2 ) - for ( i = 0; i < nArgsNew; i++ ) - for ( k = i + 1; k < nArgsNew; k++ ) - if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) - { - nArgsNew = 0; - for ( m = 0; m < nArgs; m++ ) - if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] ) - pArgs[nArgsNew++] = pArgs[m]; - pArgs[nArgsNew++] = pTemp; - assert( nArgsNew == nArgs - 1 ); - return Ivy_Multi1( pArgs, nArgsNew, Type ); - } - return Ivy_Multi_rec( pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - assert( Type == IVY_AND || Type == IVY_EXOR ); - assert( nArgs > 0 ); - return Ivy_Multi_rec( pArgs, nArgs, Type ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyObj.c b/src/temp/ivy/ivyObj.c deleted file mode 100644 index 59dda19c..00000000 --- a/src/temp/ivy/ivyObj.c +++ /dev/null @@ -1,476 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyObj.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Adding/removing objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ) -{ - return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, NULL, NULL, IVY_PI, IVY_INIT_NONE) ); -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ) -{ - return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pDriver, NULL, IVY_PO, IVY_INIT_NONE) ); -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) -{ - Ivy_Obj_t * pObj; - assert( !Ivy_IsComplement(pGhost) ); - assert( Ivy_ObjIsGhost(pGhost) ); - assert( Ivy_TableLookup(p, pGhost) == NULL ); - // get memory for the new object - pObj = Ivy_ManFetchMemory( p ); - assert( Ivy_ObjIsNone(pObj) ); - pObj->Id = Vec_PtrSize(p->vObjs); - Vec_PtrPush( p->vObjs, pObj ); - // add basic info (fanins, compls, type, init) - pObj->Type = pGhost->Type; - pObj->Init = pGhost->Init; - // add connections - Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); - // compute level - if ( Ivy_ObjIsNode(pObj) ) - pObj->Level = Ivy_ObjLevelNew(pObj); - else if ( Ivy_ObjIsLatch(pObj) ) - pObj->Level = 0; - else if ( Ivy_ObjIsOneFanin(pObj) ) - pObj->Level = Ivy_ObjFanin0(pObj)->Level; - else if ( !Ivy_ObjIsPi(pObj) ) - assert( 0 ); - // create phase - if ( Ivy_ObjIsNode(pObj) ) - pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); - else if ( Ivy_ObjIsOneFanin(pObj) ) - pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); - // set the fail TFO flag - if ( Ivy_ObjIsNode(pObj) ) - pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo; - // mark the fanins in a special way if the node is EXOR - if ( Ivy_ObjIsExor(pObj) ) - { - Ivy_ObjFanin0(pObj)->fExFan = 1; - Ivy_ObjFanin1(pObj)->fExFan = 1; - } - // add PIs/POs to the arrays - if ( Ivy_ObjIsPi(pObj) ) - Vec_PtrPush( p->vPis, pObj ); - else if ( Ivy_ObjIsPo(pObj) ) - Vec_PtrPush( p->vPos, pObj ); -// else if ( Ivy_ObjIsBuf(pObj) ) -// Vec_PtrPush( p->vBufs, pObj ); - if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id ) - Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 ); - // update node counters of the manager - p->nObjs[Ivy_ObjType(pObj)]++; - p->nCreated++; - -// printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " ); -// Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL ); -// printf( "\n" ); - - // if HAIG is defined, create a corresponding node - if ( p->pHaig ) - Ivy_ManHaigCreateObj( p, pObj ); - return pObj; -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL ); - // add the first fanin - pObj->pFanin0 = pFan0; - pObj->pFanin1 = pFan1; - // increment references of the fanins and add their fanouts - if ( Ivy_ObjFanin0(pObj) != NULL ) - { - Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) ); - if ( p->fFanout ) - Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); - } - if ( Ivy_ObjFanin1(pObj) != NULL ) - { - Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) ); - if ( p->fFanout ) - Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); - } - // add the node to the structural hash table - Ivy_TableInsert( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL ); - // remove connections - if ( pObj->pFanin0 != NULL ) - { - Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj)); - if ( p->fFanout ) - Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj ); - } - if ( pObj->pFanin1 != NULL ) - { - Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj)); - if ( p->fFanout ) - Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj ); - } - assert( pObj->pNextFan0 == NULL ); - assert( pObj->pNextFan1 == NULL ); - assert( pObj->pPrevFan0 == NULL ); - assert( pObj->pPrevFan1 == NULL ); - // remove the node from the structural hash table - Ivy_TableDelete( p, pObj ); - // add the first fanin - pObj->pFanin0 = NULL; - pObj->pFanin1 = NULL; -} - -/**Function************************************************************* - - Synopsis [Replaces the first fanin of the node by the new fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ) -{ - Ivy_Obj_t * pFaninOld; - assert( !Ivy_IsComplement(pObj) ); - pFaninOld = Ivy_ObjFanin0(pObj); - // decrement ref and remove fanout - Ivy_ObjRefsDec( pFaninOld ); - if ( p->fFanout ) - Ivy_ObjDeleteFanout( p, pFaninOld, pObj ); - // update the fanin - pObj->pFanin0 = pFaninNew; - // increment ref and add fanout - Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) ); - if ( p->fFanout ) - Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj ); - // get rid of old fanin - if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 ) - Ivy_ObjDelete_rec( p, pFaninOld, 1 ); -} - -/**Function************************************************************* - - Synopsis [Deletes the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop ); - // update node counters of the manager - p->nObjs[pObj->Type]--; - p->nDeleted++; - // remove connections - Ivy_ObjDisconnect( p, pObj ); - // remove PIs/POs from the arrays - if ( Ivy_ObjIsPi(pObj) ) - Vec_PtrRemove( p->vPis, pObj ); - else if ( Ivy_ObjIsPo(pObj) ) - Vec_PtrRemove( p->vPos, pObj ); - else if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) - Vec_PtrRemove( p->vBufs, pObj ); - // clean and recycle the entry - if ( fFreeTop ) - { - // free the node - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); - Ivy_ManRecycleMemory( p, pObj ); - } - else - { - int nRefsOld = pObj->nRefs; - Ivy_Obj_t * pFanout = pObj->pFanout; - Ivy_ObjClean( pObj ); - pObj->pFanout = pFanout; - pObj->nRefs = nRefsOld; - } -} - -/**Function************************************************************* - - Synopsis [Deletes the MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) -{ - Ivy_Obj_t * pFanin0, * pFanin1; - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_ObjIsNone(pObj) ); - if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) ) - return; - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - Ivy_ObjDelete( p, pObj, fFreeTop ); - if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 ) - Ivy_ObjDelete_rec( p, pFanin0, 1 ); - if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 ) - Ivy_ObjDelete_rec( p, pFanin1, 1 ); -} - -/**Function************************************************************* - - Synopsis [Replaces one object by another.] - - Description [Both objects are currently in the manager. The new object - (pObjNew) should be used instead of the old object (pObjOld). If the - new object is complemented or used, the buffer is added.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ) -{ - int nRefsOld;//, clk; - // the object to be replaced cannot be complemented - assert( !Ivy_IsComplement(pObjOld) ); - // the object to be replaced cannot be a terminal - assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) ); - // the object to be used cannot be a PO or assert - assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) ); - // the object cannot be the same - assert( pObjOld != Ivy_Regular(pObjNew) ); -//printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id ); - - // if HAIG is defined, create the choice node - if ( p->pHaig ) - { -// if ( pObjOld->Id == 31 ) -// { -// Ivy_ManShow( p, 0 ); -// Ivy_ManShow( p->pHaig, 1 ); -// } - Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew ); - } - // if the new object is complemented or already used, add the buffer - if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) - pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) ); - assert( !Ivy_IsComplement(pObjNew) ); - if ( fUpdateLevel ) - { -//clk = clock(); - // if the new node's arrival time is different, recursively update arrival time of the fanouts - if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level ) - { - assert( Ivy_ObjIsNode(pObjOld) ); - pObjOld->Level = pObjNew->Level; - Ivy_ObjUpdateLevel_rec( p, pObjOld ); - } -//p->time1 += clock() - clk; - // if the new node's required time has changed, recursively update required time of the fanins -//clk = clock(); - if ( p->vRequired ) - { - int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id); - if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) ) - { - Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew ); - Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew ); - } - } -//p->time2 += clock() - clk; - } - // delete the old object - if ( fDeleteOld ) - Ivy_ObjDelete_rec( p, pObjOld, fFreeTop ); - // make sure object is not pointing to itself - assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) ); - assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) ); - // make sure the old node has no fanin fanout pointers - if ( p->fFanout ) - { - assert( pObjOld->pFanout != NULL ); - assert( pObjNew->pFanout == NULL ); - pObjNew->pFanout = pObjOld->pFanout; - } - // transfer the old object - assert( Ivy_ObjRefs(pObjNew) == 0 ); - nRefsOld = pObjOld->nRefs; - Ivy_ObjOverwrite( pObjOld, pObjNew ); - pObjOld->nRefs = nRefsOld; - // patch the fanout of the fanins - if ( p->fFanout ) - { - Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld ); - if ( Ivy_ObjFanin1(pObjOld) ) - Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld ); - } - // update the hash table - Ivy_TableUpdate( p, pObjNew, pObjOld->Id ); - // recycle the object that was taken over by pObjOld - Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL ); - Ivy_ManRecycleMemory( p, pObjNew ); - // if the new node is the buffer propagate it - if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) ) - Vec_PtrPush( p->vBufs, pObjOld ); -// Ivy_ManCheckFanouts( p ); -// printf( "\n" ); -/* - if ( p->pHaig ) - { - int x; - Ivy_ManShow( p, 0, NULL ); - Ivy_ManShow( p->pHaig, 1, NULL ); - x = 0; - } -*/ -// if ( Ivy_ManCheckFanoutNums(p) ) -// { -// int x = 0; -// } -} - -/**Function************************************************************* - - Synopsis [Fixes buffer fanins.] - - Description [This situation happens because NodeReplace is a lazy - procedure, which does not propagate the change to the fanouts but - instead records the change in the form of a buf/inv node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ) -{ - Ivy_Obj_t * pFanReal0, * pFanReal1, * pResult; - if ( Ivy_ObjIsPo(pNode) ) - { - if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ) - return; - pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); - Ivy_ObjPatchFanin0( p, pNode, pFanReal0 ); -// Ivy_ManCheckFanouts( p ); - return; - } - if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) && !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ) - return; - // get the real fanins - pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); - pFanReal1 = Ivy_ObjReal( Ivy_ObjChild1(pNode) ); - // get the new node - if ( Ivy_ObjIsNode(pNode) ) - pResult = Ivy_Oper( p, pFanReal0, pFanReal1, Ivy_ObjType(pNode) ); - else if ( Ivy_ObjIsLatch(pNode) ) - pResult = Ivy_Latch( p, pFanReal0, Ivy_ObjInit(pNode) ); - else - assert( 0 ); - -//printf( "===== Replacing %d by %d.\n", pNode->Id, pResult->Id ); -//Ivy_ObjPrintVerbose( p, pNode, 0 ); printf( "\n" ); -//Ivy_ObjPrintVerbose( p, pResult, 0 ); printf( "\n" ); - - // perform the replacement - Ivy_ObjReplace( p, pNode, pResult, 1, 0, fUpdateLevel ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyOper.c b/src/temp/ivy/ivyOper.c deleted file mode 100644 index 8115ce4f..00000000 --- a/src/temp/ivy/ivyOper.c +++ /dev/null @@ -1,293 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyOper.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [AIG operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// procedure to detect an EXOR gate -static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 ) -{ - if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) ) - return 0; - p0 = Ivy_Regular(p0); - p1 = Ivy_Regular(p1); - if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) ) - return 0; - if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) ) - return 0; - if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Ivy_ObjChild0(p0); - *ppFan1 = Ivy_ObjChild1(p0); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Perform one operation.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ) -{ - if ( Type == IVY_AND ) - return Ivy_And( p, p0, p1 ); - if ( Type == IVY_EXOR ) - return Ivy_Exor( p, p0, p1 ); - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) -{ -// Ivy_Obj_t * pFan0, * pFan1; - // check trivial cases - if ( p0 == p1 ) - return p0; - if ( p0 == Ivy_Not(p1) ) - return Ivy_Not(p->pConst1); - if ( Ivy_Regular(p0) == p->pConst1 ) - return p0 == p->pConst1 ? p1 : Ivy_Not(p->pConst1); - if ( Ivy_Regular(p1) == p->pConst1 ) - return p1 == p->pConst1 ? p0 : Ivy_Not(p->pConst1); - // check if it can be an EXOR gate -// if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) -// return Ivy_CanonExor( pFan0, pFan1 ); - return Ivy_CanonAnd( p, p0, p1 ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) -{ -/* - // check trivial cases - if ( p0 == p1 ) - return Ivy_Not(p->pConst1); - if ( p0 == Ivy_Not(p1) ) - return p->pConst1; - if ( Ivy_Regular(p0) == p->pConst1 ) - return Ivy_NotCond( p1, p0 == p->pConst1 ); - if ( Ivy_Regular(p1) == p->pConst1 ) - return Ivy_NotCond( p0, p1 == p->pConst1 ); - // check the table - return Ivy_CanonExor( p, p0, p1 ); -*/ - return Ivy_Or( p, Ivy_And(p, p0, Ivy_Not(p1)), Ivy_And(p, Ivy_Not(p0), p1) ); -} - -/**Function************************************************************* - - Synopsis [Implements Boolean OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) -{ - return Ivy_Not( Ivy_And( p, Ivy_Not(p0), Ivy_Not(p1) ) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ) -{ - Ivy_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; - int Count0, Count1; - // consider trivial cases - if ( p0 == Ivy_Not(p1) ) - return Ivy_Exor( p, pC, p0 ); - // other cases can be added - // implement the first MUX (F = C * x1 + C' * x0) - pTempA1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, p1, IVY_AND, IVY_INIT_NONE) ); - pTempA2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), p0, IVY_AND, IVY_INIT_NONE) ); - if ( pTempA1 && pTempA2 ) - { - pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempA1), Ivy_Not(pTempA2), IVY_AND, IVY_INIT_NONE) ); - if ( pTemp ) return Ivy_Not(pTemp); - } - Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); - // implement the second MUX (F' = C * x1' + C' * x0') - pTempB1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, Ivy_Not(p1), IVY_AND, IVY_INIT_NONE) ); - pTempB2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), Ivy_Not(p0), IVY_AND, IVY_INIT_NONE) ); - if ( pTempB1 && pTempB2 ) - { - pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempB1), Ivy_Not(pTempB2), IVY_AND, IVY_INIT_NONE) ); - if ( pTemp ) return pTemp; - } - Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); - // compare and decide which one to implement - if ( Count0 >= Count1 ) - { - pTempA1 = pTempA1? pTempA1 : Ivy_And(p, pC, p1); - pTempA2 = pTempA2? pTempA2 : Ivy_And(p, Ivy_Not(pC), p0); - return Ivy_Or( p, pTempA1, pTempA2 ); - } - pTempB1 = pTempB1? pTempB1 : Ivy_And(p, pC, Ivy_Not(p1)); - pTempB2 = pTempB2? pTempB2 : Ivy_And(p, Ivy_Not(pC), Ivy_Not(p0)); - return Ivy_Not( Ivy_Or( p, pTempB1, pTempB2 ) ); - -// return Ivy_Or( Ivy_And(pC, p1), Ivy_And(Ivy_Not(pC), p0) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ) -{ - return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) ); -} - -/**Function************************************************************* - - Synopsis [Constructs the well-balanced tree of gates.] - - Description [Disregards levels and possible logic sharing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Ivy_Multi_rec( p, ppObjs, nObjs/2, Type ); - pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); - return Ivy_Oper( p, pObj1, pObj2, Type ); -} - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - assert( Type == IVY_AND || Type == IVY_EXOR ); - assert( nArgs > 0 ); - return Ivy_Multi_rec( p, pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ) -{ - int i; - assert( vPairs->nSize > 0 ); - assert( vPairs->nSize % 2 == 0 ); - // go through the cubes of the node's SOP - for ( i = 0; i < vPairs->nSize; i += 2 ) - vPairs->pArray[i/2] = Ivy_Not( Ivy_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); - vPairs->nSize = vPairs->nSize/2; - return Ivy_Not( Ivy_Multi_rec( p, (Ivy_Obj_t **)vPairs->pArray, vPairs->nSize, IVY_AND ) ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) -{ - return Ivy_CanonLatch( p, pObj, Init ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyResyn.c b/src/temp/ivy/ivyResyn.c deleted file mode 100644 index f42d7464..00000000 --- a/src/temp/ivy/ivyResyn.c +++ /dev/null @@ -1,196 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyResyn.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [AIG rewriting script.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs several passes of rewriting on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) -{ - int clk; - Ivy_Man_t * pTemp; - -if ( fVerbose ) { printf( "Original:\n" ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pMan, fUpdateLevel ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); -clk = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Performs several passes of rewriting on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) -{ - int clk; - Ivy_Man_t * pTemp; - -if ( fVerbose ) { printf( "Original:\n" ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pMan, fUpdateLevel ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); -clk = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); -clk = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); -clk = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Performs several passes of rewriting on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ) -{ - int clk; - Ivy_Man_t * pTemp; - -if ( fVerbose ) { printf( "Original:\n" ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - Ivy_ManRewritePre( pMan, 0, 0, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, 0 ); -// pMan = Ivy_ManDup( pTemp = pMan ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -/* -clk = clock(); - Ivy_ManRewritePre( pMan, 0, 0, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, 0 ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); -*/ - return pMan; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyRwr.c b/src/temp/ivy/ivyRwr.c deleted file mode 100644 index 3f8720ba..00000000 --- a/src/temp/ivy/ivyRwr.c +++ /dev/null @@ -1,609 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyRwt.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Rewriting based on precomputation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyRwt.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" -#include "deco.h" -#include "rwt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ); -static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ); -static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, - Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ); - -static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); -static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs incremental rewriting of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ) -{ - Rwt_Man_t * pManRwt; - Ivy_Obj_t * pNode; - int i, nNodes, nGain; - int clk, clkStart = clock(); - // start the rewriting manager - pManRwt = Rwt_ManStart( 0 ); - p->pData = pManRwt; - if ( pManRwt == NULL ) - return 0; - // create fanouts - if ( fUpdateLevel && p->fFanout == 0 ) - Ivy_ManStartFanout( p ); - // compute the reverse levels if level update is requested - if ( fUpdateLevel ) - Ivy_ManRequiredLevels( p ); - // set the number of levels -// p->nLevelMax = Ivy_ManLevels( p ); - // resynthesize each node once - nNodes = Ivy_ManObjIdMax(p); - Ivy_ManForEachNode( p, pNode, i ) - { - // fix the fanin buffer problem - Ivy_NodeFixBufferFanins( p, pNode, 1 ); - if ( Ivy_ObjIsBuf(pNode) ) - continue; - // stop if all nodes have been tried once - if ( i > nNodes ) - break; - // for each cut, try to resynthesize it - nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost ); - if ( nGain > 0 || nGain == 0 && fUseZeroCost ) - { - Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt); - int fCompl = Rwt_ManReadCompl(pManRwt); -/* - { - Ivy_Obj_t * pObj; - int i; - printf( "USING: (" ); - Vec_PtrForEachEntry( Rwt_ManReadLeaves(pManRwt), pObj, i ) - printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) ); - printf( ") Gain = %d.\n", nGain ); - } - if ( nGain > 0 ) - { // print stats on the MFFC - extern void Ivy_NodeMffsConeSuppPrint( Ivy_Obj_t * pNode ); - printf( "Node %6d : Gain = %4d ", pNode->Id, nGain ); - Ivy_NodeMffsConeSuppPrint( pNode ); - } -*/ - // complement the FF if needed -clk = clock(); - if ( fCompl ) Dec_GraphComplement( pGraph ); - Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain ); - if ( fCompl ) Dec_GraphComplement( pGraph ); -Rwt_ManAddTimeUpdate( pManRwt, clock() - clk ); - } - } -Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart ); - // print stats - if ( fVerbose ) - Rwt_ManPrintStats( pManRwt ); - // delete the managers - Rwt_ManStop( pManRwt ); - p->pData = NULL; - // fix the levels - if ( fUpdateLevel ) - Vec_IntFree( p->vRequired ), p->vRequired = NULL; - else - Ivy_ManResetLevels( p ); - // check - if ( i = Ivy_ManCleanup(p) ) - printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); - if ( !Ivy_ManCheck(p) ) - printf( "Ivy_ManRewritePre(): The check has failed.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs rewriting for one node.] - - Description [This procedure considers all the cuts computed for the node - and tries to rewrite each of them using the "forest" of different AIG - structures precomputed and stored in the RWR manager. - Determines the best rewriting and computes the gain in the number of AIG - nodes in the final network. In the end, p->vFanins contains information - about the best cut that can be used for rewriting, while p->pGraph gives - the decomposition dag (represented using decomposition graph data structure). - Returns gain in the number of nodes or -1 if node cannot be rewritten.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ) -{ - int fVeryVerbose = 0; - Dec_Graph_t * pGraph; - Ivy_Store_t * pStore; - Ivy_Cut_t * pCut; - Ivy_Obj_t * pFanin; - unsigned uPhase, uTruthBest, uTruth; - char * pPerm; - int Required, nNodesSaved, nNodesSaveCur; - int i, c, GainCur, GainBest = -1; - int clk, clk2; - - p->nNodesConsidered++; - // get the required times - Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000; - // get the node's cuts -clk = clock(); - pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 ); -p->timeCut += clock() - clk; - - // go through the cuts -clk = clock(); - for ( c = 1; c < pStore->nCuts; c++ ) - { - pCut = pStore->pCuts + c; - // consider only 4-input cuts - if ( pCut->nSize != 4 ) - continue; - // skip the cuts with buffers - for ( i = 0; i < (int)pCut->nSize; i++ ) - if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) ) - break; - if ( i != pCut->nSize ) - { - p->nCutsBad++; - continue; - } - p->nCutsGood++; - // get the fanin permutation -clk2 = clock(); - uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize ); // truth table -p->timeTruth += clock() - clk2; - pPerm = p->pPerms4[ p->pPerms[uTruth] ]; - uPhase = p->pPhases[uTruth]; - // collect fanins with the corresponding permutation/phase - Vec_PtrClear( p->vFaninsCur ); - Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); - for ( i = 0; i < (int)pCut->nSize; i++ ) - { - pFanin = Ivy_ManObj( pMan, pCut->pArray[pPerm[i]] ); - assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) ); - pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); - Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); - } -clk2 = clock(); -/* - printf( "Considering: (" ); - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) ); - printf( ")\n" ); -*/ - // mark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); - // label MFFC with current ID - Ivy_ManIncrementTravId( pMan ); - nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); - // unmark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); -p->timeMffc += clock() - clk2; - - // evaluate the cut -clk2 = clock(); - pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth ); -p->timeEval += clock() - clk2; - - // check if the cut is better than the current best one - if ( pGraph != NULL && GainBest < GainCur ) - { - // save this form - nNodesSaveCur = nNodesSaved; - GainBest = GainCur; - p->pGraph = pGraph; - p->fCompl = ((uPhase & (1<<4)) > 0); - uTruthBest = uTruth; - // collect fanins in the - Vec_PtrClear( p->vFanins ); - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Vec_PtrPush( p->vFanins, pFanin ); - } - } -p->timeRes += clock() - clk; - - if ( GainBest == -1 ) - return -1; - -// printf( "%d", nNodesSaveCur - GainBest ); -/* - if ( GainBest > 0 ) - { - if ( Rwt_CutIsintean( pNode, p->vFanins ) ) - printf( "b" ); - else - { - printf( "Node %d : ", pNode->Id ); - Vec_PtrForEachEntry( p->vFanins, pFanin, i ) - printf( "%d ", Ivy_Regular(pFanin)->Id ); - printf( "a" ); - } - } -*/ -/* - if ( GainBest > 0 ) - if ( p->fCompl ) - printf( "c" ); - else - printf( "." ); -*/ - - // copy the leaves - Vec_PtrForEachEntry( p->vFanins, pFanin, i ) - Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; - - p->nScores[p->pMap[uTruthBest]]++; - p->nNodesGained += GainBest; - if ( fUseZeroCost || GainBest > 0 ) - p->nNodesRewritten++; - - // report the progress - if ( fVeryVerbose && GainBest > 0 ) - { - printf( "Node %6d : ", Ivy_ObjId(pNode) ); - printf( "Fanins = %d. ", p->vFanins->nSize ); - printf( "Save = %d. ", nNodesSaveCur ); - printf( "Add = %d. ", nNodesSaveCur-GainBest ); - printf( "GAIN = %d. ", GainBest ); - printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); - printf( "Class = %d. ", p->pMap[uTruthBest] ); - printf( "\n" ); - } - return GainBest; -} - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums ) -{ - static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - unsigned uTruth0, uTruth1; - int i; - for ( i = 0; i < nNums; i++ ) - if ( pObj->Id == pNums[i] ) - return uMasks[i]; - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); - uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums ); - if ( Ivy_ObjFaninC0(pObj) ) - uTruth0 = ~uTruth0; - if ( Ivy_ObjIsBuf(pObj) ) - return uTruth0; - uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums ); - if ( Ivy_ObjFaninC1(pObj) ) - uTruth1 = ~uTruth1; - return uTruth0 & uTruth1; -} - - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ) -{ - assert( nNums < 6 ); - return Ivy_NodeGetTruth_rec( pObj, pNums, nNums ); -} - -/**Function************************************************************* - - Synopsis [Evaluates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ) -{ - Vec_Ptr_t * vSubgraphs; - Dec_Graph_t * pGraphBest, * pGraphCur; - Rwt_Node_t * pNode, * pFanin; - int nNodesAdded, GainBest, i, k; - // find the matching class of subgraphs - vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); - p->nSubgraphs += vSubgraphs->nSize; - // determine the best subgraph - GainBest = -1; - Vec_PtrForEachEntry( vSubgraphs, pNode, i ) - { - // get the current graph - pGraphCur = (Dec_Graph_t *)pNode->pNext; - // copy the leaves - Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) - Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; - // detect how many unlabeled nodes will be reused - nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax ); - if ( nNodesAdded == -1 ) - continue; - assert( nNodesSaved >= nNodesAdded ); - // count the gain at this node - if ( GainBest < nNodesSaved - nNodesAdded ) - { - GainBest = nNodesSaved - nNodesAdded; - pGraphBest = pGraphCur; - } - } - if ( GainBest == -1 ) - return NULL; - *pGainBest = GainBest; - return pGraphBest; -} - - -/**Function************************************************************* - - Synopsis [Counts the number of new nodes added when using this graph.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure. - Returns -1 if the number of nodes and levels exceeded the given limit or - the number of levels exceeded the maximum allowed level.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) -{ - Dec_Node_t * pNode, * pNode0, * pNode1; - Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; - int i, Counter, LevelNew, LevelOld; - // check for constant function or a literal - if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) - return 0; - // set the levels of the leaves - Dec_GraphForEachLeaf( pGraph, pNode, i ) - pNode->Level = Ivy_Regular(pNode->pFunc)->Level; - // compute the AIG size after adding the internal nodes - Counter = 0; - Dec_GraphForEachNode( pGraph, pNode, i ) - { - // get the children of this node - pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); - pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); - // get the AIG nodes corresponding to the children - pAnd0 = pNode0->pFunc; - pAnd1 = pNode1->pFunc; - if ( pAnd0 && pAnd1 ) - { - // if they are both present, find the resulting node - pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); - pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); - // return -1 if the node is the same as the original root - if ( Ivy_Regular(pAnd) == pRoot ) - return -1; - } - else - pAnd = NULL; - // count the number of added nodes - if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) - { - if ( ++Counter > NodeMax ) - return -1; - } - // count the number of new levels - LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level ); - if ( pAnd ) - { - if ( Ivy_Regular(pAnd) == p->pConst1 ) - LevelNew = 0; - else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) ) - LevelNew = (int)Ivy_Regular(pAnd0)->Level; - else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) ) - LevelNew = (int)Ivy_Regular(pAnd1)->Level; - LevelOld = (int)Ivy_Regular(pAnd)->Level; -// assert( LevelNew == LevelOld ); - } - if ( LevelNew > LevelMax ) - return -1; - pNode->pFunc = pAnd; - pNode->Level = LevelNew; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph ) -{ - Ivy_Obj_t * pAnd0, * pAnd1; - Dec_Node_t * pNode; - int i; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph - Dec_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); - } - // complement the result if necessary - return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Replaces MFFC of the node by the new factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) -{ - Ivy_Obj_t * pRootNew; - int nNodesNew, nNodesOld, Required; - Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000; - nNodesOld = Ivy_ManNodeNum(p); - // create the new structure of nodes - pRootNew = Ivy_GraphToNetwork( p, pGraph ); - assert( (int)Ivy_Regular(pRootNew)->Level <= Required ); -// if ( Ivy_Regular(pRootNew)->Level == Required ) -// printf( "Difference %d.\n", Ivy_Regular(pRootNew)->Level - Required ); - // remove the old nodes -// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); -/* - if ( Ivy_IsComplement(pRootNew) ) - printf( "c" ); - else - printf( "d" ); - if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) - printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); - printf( " " ); -*/ - Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 ); - // compare the gains - nNodesNew = Ivy_ManNodeNum(p); - assert( nGain <= nNodesOld - nNodesNew ); - // propagate the buffer - Ivy_ManPropagateBuffers( p, 1 ); -} - -/**Function************************************************************* - - Synopsis [Replaces MFFC of the node by the new factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) -{ - Ivy_Obj_t * pRootNew, * pFanin; - int nNodesNew, nNodesOld, i, nRefsOld; - nNodesOld = Ivy_ManNodeNum(p); - -//printf( "Before = %d. ", Ivy_ManNodeNum(p) ); - // mark the cut - Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) - Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); - // deref the old cone - nRefsOld = pRoot->nRefs; - pRoot->nRefs = 0; - Ivy_ObjDelete_rec( p, pRoot, 0 ); - pRoot->nRefs = nRefsOld; - // unmark the cut - Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) - Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); -//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); - - // create the new structure of nodes - pRootNew = Ivy_GraphToNetwork( p, pGraph ); -//printf( "Create = %d. ", Ivy_ManNodeNum(p) ); - // remove the old nodes -// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); -/* - if ( Ivy_IsComplement(pRootNew) ) - printf( "c" ); - else - printf( "d" ); - if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) - printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); - printf( " " ); -*/ - Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 ); -//printf( "Replace = %d. ", Ivy_ManNodeNum(p) ); - - // delete remaining dangling nodes - Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) - { - pFanin = Ivy_Regular(pFanin); - if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 ) - Ivy_ObjDelete_rec( p, pFanin, 1 ); - } -//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); -//printf( "\n" ); - - // compare the gains - nNodesNew = Ivy_ManNodeNum(p); - assert( nGain <= nNodesOld - nNodesNew ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyRwrAlg.c b/src/temp/ivy/ivyRwrAlg.c deleted file mode 100644 index fc48deb0..00000000 --- a/src/temp/ivy/ivyRwrAlg.c +++ /dev/null @@ -1,408 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyRwrAlg.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Algebraic AIG rewriting.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); -static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ); -static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Algebraic AIG rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ) -{ - Vec_Int_t * vRequired; - Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol; - Ivy_Obj_t * pObj, * pResult; - int i, RetValue, LevelR, nNodesOld; - int CountUsed, CountUndo; - vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL; - vFront = Vec_PtrAlloc( 100 ); - vLeaves = Vec_PtrAlloc( 100 ); - vCone = Vec_PtrAlloc( 100 ); - vSol = Vec_PtrAlloc( 100 ); - // go through the nodes in the topological order - CountUsed = CountUndo = 0; - nNodesOld = Ivy_ManObjIdNext(p); - Ivy_ManForEachObj( p, pObj, i ) - { - assert( !Ivy_ObjIsBuf(pObj) ); - if ( i >= nNodesOld ) - break; - // skip no-nodes and MUX roots - if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) ) - continue; -// if ( pObj->Id > 297 ) // 296 --- 297 -// break; - if ( pObj->Id == 297 ) - { - int x = 0; - } - // get the largest algebraic cut - RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone ); - // the case of a trivial tree cut - if ( RetValue == 1 ) - continue; - // the case of constant 0 cone - if ( RetValue == -1 ) - { - Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0, 1 ); - continue; - } - assert( Vec_PtrSize(vLeaves) > 2 ); - // get the required level for this node - LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000; - // create a new cone - pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost ); - if ( pResult == NULL || pResult == pObj ) - continue; - assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) ); - if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 ) - Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++; - else - Ivy_ObjReplace( pObj, pResult, 1, 0, 1 ), CountUsed++; - } - printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo ); - Vec_PtrFree( vFront ); - Vec_PtrFree( vCone ); - Vec_PtrFree( vSol ); - if ( vRequired ) Vec_IntFree( vRequired ); - if ( i = Ivy_ManCleanup(p) ) - printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); - if ( !Ivy_ManCheck(p) ) - printf( "Ivy_ManRewriteAlg(): The check has failed.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Analizes one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ) -{ - int fVerbose = 0; - Ivy_Obj_t * pTemp; - int k, Counter, nMffc, RetValue; - - if ( fVerbose ) - { - if ( Ivy_ObjIsExor(pObj) ) - printf( "x " ); - else - printf( " " ); - } - -/* - printf( "%d ", Vec_PtrSize(vFront) ); - printf( "( " ); - Vec_PtrForEachEntry( vFront, pTemp, k ) - printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); - printf( ")\n" ); -*/ - // collect nodes in the cone - if ( Ivy_ObjIsExor(pObj) ) - Ivy_ManCollectCone( pObj, vFront, vCone ); - else - Ivy_ManCollectCone( pObj, vLeaves, vCone ); - - // deref nodes in the cone - Vec_PtrForEachEntry( vCone, pTemp, k ) - { - Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) ); - Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) ); - pTemp->fMarkB = 1; - } - - // count the MFFC size - Vec_PtrForEachEntry( vFront, pTemp, k ) - Ivy_Regular(pTemp)->fMarkA = 1; - nMffc = Ivy_NodeCountMffc( pObj ); - Vec_PtrForEachEntry( vFront, pTemp, k ) - Ivy_Regular(pTemp)->fMarkA = 0; - - if ( fVerbose ) - { - Counter = 0; - Vec_PtrForEachEntry( vCone, pTemp, k ) - Counter += (Ivy_ObjRefs(pTemp) > 0); - printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d. Mffc = %d. Lev = %d. LevR = %d.\n", - pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR ); - } -/* - printf( "Leaves:" ); - Vec_PtrForEachEntry( vLeaves, pTemp, k ) - printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" ); - printf( "\n" ); - printf( "Cone:\n" ); - Vec_PtrForEachEntry( vCone, pTemp, k ) - printf( " %5d = %d%s %d%s\n", pTemp->Id, - Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "", - Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" ); -*/ - - RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols ); - - // ref nodes in the cone - Vec_PtrForEachEntry( vCone, pTemp, k ) - { - Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) ); - Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) ); - pTemp->fMarkA = 0; - pTemp->fMarkB = 0; - } - - if ( !RetValue ) - return NULL; - - if ( Vec_PtrSize( vSols ) == 1 ) - return Vec_PtrEntry( vSols, 0 ); - return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 ); -} - -/**Function************************************************************* - - Synopsis [Comparison for node pointers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode ) -{ - if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA ) - return 0; - assert( pNode->fMarkB ); - pNode->fMarkA = 1; -// printf( "%d ", pNode->Id ); - if ( Ivy_ObjIsBuf(pNode) ) - return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ); - return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Comparison for node pointers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ) -{ - assert( pNode->fMarkB ); - return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Comparison for node pointers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) -{ - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Computing one algebraic cut.] - - Description [Returns 1 if the tree-leaves of this node where traversed - and found to have no external references (and have not been collected). - Returns 0 if the tree-leaves have external references and are collected.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) -{ - int RetValue0, RetValue1; - Ivy_Obj_t * pObjR = Ivy_Regular(pObj); - assert( !Ivy_ObjIsBuf(pObjR) ); - assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) ); - - // make sure the node is not visited twice in different polarities - if ( Ivy_IsComplement(pObj) ) - { // if complemented, mark B - if ( pObjR->fMarkA ) - return -1; - pObjR->fMarkB = 1; - } - else - { // if non-complicated, mark A - if ( pObjR->fMarkB ) - return -1; - pObjR->fMarkA = 1; - } - Vec_PtrPush( vCone, pObjR ); - - // if the node is the end of the tree, return - if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type ) - { - if ( Ivy_ObjRefs(pObjR) == 1 ) - return 1; - assert( Ivy_ObjRefs(pObjR) > 1 ); - Vec_PtrPush( vFront, pObj ); - return 0; - } - - // branch on the node - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsNode(pObj) ); - // what if buffer has more than one fanout??? - RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone ); - RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone ); - if ( RetValue0 == -1 || RetValue1 == -1 ) - return -1; - - // the case when both have no external references - if ( RetValue0 && RetValue1 ) - { - if ( Ivy_ObjRefs(pObj) == 1 ) - return 1; - assert( Ivy_ObjRefs(pObj) > 1 ); - Vec_PtrPush( vFront, pObj ); - return 0; - } - // the case when one of them has external references - if ( RetValue0 ) - Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) ); - if ( RetValue1 ) - Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Computing one algebraic cut.] - - Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge, - (c) boundary of different gates. Returns 1 if this is a pure tree. - Returns -1 if the contant 0 is detected. Return 0 if the array can be used.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) -{ - Ivy_Obj_t * pObj, * pPrev; - int RetValue, i; - assert( !Ivy_IsComplement(pRoot) ); - assert( Ivy_ObjIsNode(pRoot) ); - // clear the frontier and collect the nodes - Vec_PtrClear( vCone ); - Vec_PtrClear( vFront ); - Vec_PtrClear( vLeaves ); - RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone ); - // clean the marks - Vec_PtrForEachEntry( vCone, pObj, i ) - pObj->fMarkA = pObj->fMarkB = 0; - // quit if the same node is found in both polarities - if ( RetValue == -1 ) - return -1; - // return if the node is the root of a tree - if ( RetValue == 1 ) - return 1; - // return if the cut is composed of two nodes - if ( Vec_PtrSize(vFront) <= 2 ) - return 1; - // sort the entries in increasing order - Vec_PtrSort( vFront, Ivy_ManFindAlgCutCompare ); - // remove duplicates from vFront and save the nodes in vLeaves - pPrev = Vec_PtrEntry(vFront, 0); - Vec_PtrPush( vLeaves, pPrev ); - Vec_PtrForEachEntryStart( vFront, pObj, i, 1 ) - { - // compare current entry and the previous entry - if ( pObj == pPrev ) - { - if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0 - { - // vLeaves are no longer structural support of pRoot!!! - Vec_PtrPop(vLeaves); - pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves); - } - continue; - } - if ( pObj == Ivy_Not(pPrev) ) - { - assert( Ivy_ObjIsAnd(pRoot) ); - return -1; - } - pPrev = pObj; - Vec_PtrPush( vLeaves, pObj ); - } - if ( Vec_PtrSize(vLeaves) == 0 ) - return -1; - if ( Vec_PtrSize(vLeaves) <= 2 ) - return 1; - return 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivySeq.c b/src/temp/ivy/ivySeq.c deleted file mode 100644 index c1f3da2b..00000000 --- a/src/temp/ivy/ivySeq.c +++ /dev/null @@ -1,1130 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivySeq.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivySeq.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" -#include "deco.h" -#include "rwt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ); -static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ); -static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ); -static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ); -static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ); -static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ); -static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ); -static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); - -static inline int Ivy_CutHashValue( int NodeId ) { return 1 << (NodeId % 31); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs incremental rewriting of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ) -{ - Rwt_Man_t * pManRwt; - Ivy_Obj_t * pNode; - int i, nNodes, nGain; - int clk, clkStart = clock(); - // set the DC latch values - Ivy_ManForEachLatch( p, pNode, i ) - pNode->Init = IVY_INIT_DC; - // start the rewriting manager - pManRwt = Rwt_ManStart( 0 ); - p->pData = pManRwt; - if ( pManRwt == NULL ) - return 0; - // create fanouts - if ( p->fFanout == 0 ) - Ivy_ManStartFanout( p ); - // resynthesize each node once - nNodes = Ivy_ManObjIdMax(p); - Ivy_ManForEachNode( p, pNode, i ) - { - assert( !Ivy_ObjIsBuf(pNode) ); - assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ); - assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ); - // fix the fanin buffer problem -// Ivy_NodeFixBufferFanins( p, pNode ); -// if ( Ivy_ObjIsBuf(pNode) ) -// continue; - // stop if all nodes have been tried once - if ( i > nNodes ) - break; - // for each cut, try to resynthesize it - nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost ); - if ( nGain > 0 || nGain == 0 && fUseZeroCost ) - { - Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt); - int fCompl = Rwt_ManReadCompl(pManRwt); - // complement the FF if needed -clk = clock(); - if ( fCompl ) Dec_GraphComplement( pGraph ); - Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain ); - if ( fCompl ) Dec_GraphComplement( pGraph ); -Rwt_ManAddTimeUpdate( pManRwt, clock() - clk ); - } - } -Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart ); - // print stats - if ( fVerbose ) - Rwt_ManPrintStats( pManRwt ); - // delete the managers - Rwt_ManStop( pManRwt ); - p->pData = NULL; - // fix the levels - Ivy_ManResetLevels( p ); -// if ( Ivy_ManCheckFanoutNums(p) ) -// printf( "Ivy_ManRewritePre(): The check has failed.\n" ); - // check - if ( !Ivy_ManCheck(p) ) - printf( "Ivy_ManRewritePre(): The check has failed.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs rewriting for one node.] - - Description [This procedure considers all the cuts computed for the node - and tries to rewrite each of them using the "forest" of different AIG - structures precomputed and stored in the RWR manager. - Determines the best rewriting and computes the gain in the number of AIG - nodes in the final network. In the end, p->vFanins contains information - about the best cut that can be used for rewriting, while p->pGraph gives - the decomposition dag (represented using decomposition graph data structure). - Returns gain in the number of nodes or -1 if node cannot be rewritten.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ) -{ - int fVeryVerbose = 0; - Dec_Graph_t * pGraph; - Ivy_Store_t * pStore; - Ivy_Cut_t * pCut; - Ivy_Obj_t * pFanin;//, * pFanout; - Vec_Ptr_t * vFanout; - unsigned uPhase, uTruthBest, uTruth; - char * pPerm; - int nNodesSaved, nNodesSaveCur; - int i, c, GainCur, GainBest = -1; - int clk, clk2; - - p->nNodesConsidered++; - // get the node's cuts -clk = clock(); - pStore = Ivy_CutComputeForNode( pMan, pNode, 5 ); -p->timeCut += clock() - clk; - - // go through the cuts -clk = clock(); - vFanout = Vec_PtrAlloc( 100 ); - for ( c = 1; c < pStore->nCuts; c++ ) - { - pCut = pStore->pCuts + c; - // consider only 4-input cuts - if ( pCut->nSize != 4 ) - continue; - // skip the cuts with buffers - for ( i = 0; i < (int)pCut->nSize; i++ ) - if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) ) - break; - if ( i != pCut->nSize ) - { - p->nCutsBad++; - continue; - } - p->nCutsGood++; - // get the fanin permutation -clk2 = clock(); - uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize ); // truth table -p->timeTruth += clock() - clk2; - pPerm = p->pPerms4[ p->pPerms[uTruth] ]; - uPhase = p->pPhases[uTruth]; - // collect fanins with the corresponding permutation/phase - Vec_PtrClear( p->vFaninsCur ); - Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); - for ( i = 0; i < (int)pCut->nSize; i++ ) - { - pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[pPerm[i]] ) ); - assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) ); - pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); - Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); - } -clk2 = clock(); - // mark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); - // label MFFC with current ID - Ivy_ManIncrementTravId( pMan ); - nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); - // label fanouts with the current ID -// Ivy_ObjForEachFanout( pMan, pNode, vFanout, pFanout, i ) -// Ivy_ObjSetTravIdCurrent( pMan, pFanout ); - // unmark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); -p->timeMffc += clock() - clk2; -/* -if ( pNode->Id == 8648 ) -{ - int i; - printf( "Trying cut : {" ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); -// printf( " }\n" ); - printf( " } " ); - Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" ); -} -*/ - - // evaluate the cut -clk2 = clock(); - pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth ); -p->timeEval += clock() - clk2; - - - // check if the cut is better than the current best one - if ( pGraph != NULL && GainBest < GainCur ) - { - // save this form - nNodesSaveCur = nNodesSaved; - GainBest = GainCur; - p->pGraph = pGraph; - p->pCut = pCut; - p->pPerm = pPerm; - p->fCompl = ((uPhase & (1<<4)) > 0); - uTruthBest = uTruth; - // collect fanins in the - Vec_PtrClear( p->vFanins ); - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Vec_PtrPush( p->vFanins, pFanin ); - } - } - Vec_PtrFree( vFanout ); -p->timeRes += clock() - clk; - - if ( GainBest == -1 ) - return -1; -/* - { - Ivy_Cut_t * pCut = p->pCut; - printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); - printf( " }\n" ); - } -*/ - - // copy the leaves - Ivy_GraphPrepare( p->pGraph, p->pCut, p->vFanins, p->pPerm ); - - p->nScores[p->pMap[uTruthBest]]++; - p->nNodesGained += GainBest; - if ( fUseZeroCost || GainBest > 0 ) - p->nNodesRewritten++; - -/* - if ( GainBest > 0 ) - { - Ivy_Cut_t * pCut = p->pCut; - printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %5d(%2d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); - printf( " }\n" ); - } -*/ - - // report the progress - if ( fVeryVerbose && GainBest > 0 ) - { - printf( "Node %6d : ", Ivy_ObjId(pNode) ); - printf( "Fanins = %d. ", p->vFanins->nSize ); - printf( "Save = %d. ", nNodesSaveCur ); - printf( "Add = %d. ", nNodesSaveCur-GainBest ); - printf( "GAIN = %d. ", GainBest ); - printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); - printf( "Class = %d. ", p->pMap[uTruthBest] ); - printf( "\n" ); - } - return GainBest; -} - - -/**Function************************************************************* - - Synopsis [Evaluates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ) -{ - Vec_Ptr_t * vSubgraphs; - Dec_Graph_t * pGraphBest, * pGraphCur; - Rwt_Node_t * pNode; - int nNodesAdded, GainBest, i; - // find the matching class of subgraphs - vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); - p->nSubgraphs += vSubgraphs->nSize; - // determine the best subgraph - GainBest = -1; - Vec_PtrForEachEntry( vSubgraphs, pNode, i ) - { - // get the current graph - pGraphCur = (Dec_Graph_t *)pNode->pNext; - -// if ( pRoot->Id == 8648 ) -// Dec_GraphPrint( stdout, pGraphCur, NULL, NULL ); - // copy the leaves -// Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) -// Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; - Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm ); - - // detect how many unlabeled nodes will be reused - nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved ); - if ( nNodesAdded == -1 ) - continue; - assert( nNodesSaved >= nNodesAdded ); - // count the gain at this node - if ( GainBest < nNodesSaved - nNodesAdded ) - { - GainBest = nNodesSaved - nNodesAdded; - pGraphBest = pGraphCur; - } - } - if ( GainBest == -1 ) - return NULL; - *pGainBest = GainBest; - return pGraphBest; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ) -{ - Dec_Node_t * pNode, * pNode0, * pNode1; - int i; - assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize ); - assert( Vec_PtrSize(vFanins) == pCut->nSize ); - // label the leaves with latch numbers - Dec_GraphForEachLeaf( pGraph, pNode, i ) - { - pNode->pFunc = Vec_PtrEntry( vFanins, i ); - pNode->nLat2 = Ivy_LeafLat( pCut->pArray[pPerm[i]] ); - } - // propagate latches through the nodes - Dec_GraphForEachNode( pGraph, pNode, i ) - { - // get the children of this node - pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); - pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); - // distribute the latches - pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 ); - pNode->nLat0 = pNode0->nLat2 - pNode->nLat2; - pNode->nLat1 = pNode1->nLat2 - pNode->nLat2; - } -} - -/**Function************************************************************* - - Synopsis [Counts the number of new nodes added when using this graph.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure. - Returns -1 if the number of nodes and levels exceeded the given limit or - the number of levels exceeded the maximum allowed level.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ) -{ - Dec_Node_t * pNode, * pNode0, * pNode1; - Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; - int i, k, Counter, fCompl; - // check for constant function or a literal - if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) - return 0; - // compute the AIG size after adding the internal nodes - Counter = 0; - Dec_GraphForEachNode( pGraph, pNode, i ) - { - // get the children of this node - pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); - pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); - // get the AIG nodes corresponding to the children - pAnd0 = pNode0->pFunc; - pAnd1 = pNode1->pFunc; - // skip the latches - for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ ) - { - fCompl = Ivy_IsComplement(pAnd0); - pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) ); - if ( pAnd0 ) - pAnd0 = Ivy_NotCond( pAnd0, fCompl ); - } - for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ ) - { - fCompl = Ivy_IsComplement(pAnd1); - pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) ); - if ( pAnd1 ) - pAnd1 = Ivy_NotCond( pAnd1, fCompl ); - } - // get the new node - if ( pAnd0 && pAnd1 ) - { - // if they are both present, find the resulting node - pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); - assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) ); - if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) ) - pAnd = Ivy_And( p, pAnd0, pAnd1 ); - else - pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); - // return -1 if the node is the same as the original root - if ( Ivy_Regular(pAnd) == pRoot ) - return -1; - } - else - pAnd = NULL; - // count the number of added nodes - if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) - { - if ( ++Counter > NodeMax ) - return -1; - } - pNode->pFunc = pAnd; - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ) -{ - Ivy_Obj_t * pAnd0, * pAnd1; - Dec_Node_t * pNode; - int i, k; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - { - // get the variable node - pNode = Dec_GraphVar(pGraph); - // add the remaining latches - for ( k = 0; k < (int)pNode->nLat2; k++ ) - pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC ); - return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); - } - // build the AIG nodes corresponding to the AND gates of the graph - Dec_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - // add the latches - for ( k = 0; k < (int)pNode->nLat0; k++ ) - pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC ); - for ( k = 0; k < (int)pNode->nLat1; k++ ) - pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC ); - // create the node - pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); - } - // add the remaining latches - for ( k = 0; k < (int)pNode->nLat2; k++ ) - pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC ); - // complement the result if necessary - return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Replaces MFFC of the node by the new factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ) -{ - Ivy_Obj_t * pRootNew; - int nNodesNew, nNodesOld; - nNodesOld = Ivy_ManNodeNum(p); - // create the new structure of nodes - pRootNew = Ivy_GraphToNetworkSeq( p, pGraph ); - Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 ); - // compare the gains - nNodesNew = Ivy_ManNodeNum(p); - assert( nGain <= nNodesOld - nNodesNew ); - // propagate the buffer - Ivy_ManPropagateBuffers( p, 0 ); -} - - - - - - - - - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums ) -{ - static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - unsigned uTruth0, uTruth1; - Ivy_Obj_t * pObj; - int i; - for ( i = 0; i < nNums; i++ ) - if ( Leaf == pNums[i] ) - return uMasks[i]; - pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); - if ( Ivy_ObjIsLatch(pObj) ) - { - assert( !Ivy_ObjFaninC0(pObj) ); - Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 ); - return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); - } - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); - Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) ); - uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); - if ( Ivy_ObjFaninC0(pObj) ) - uTruth0 = ~uTruth0; - if ( Ivy_ObjIsBuf(pObj) ) - return uTruth0; - Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) ); - uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); - if ( Ivy_ObjFaninC1(pObj) ) - uTruth1 = ~uTruth1; - return uTruth0 & uTruth1; -} - - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ) -{ - assert( Ivy_ObjIsNode(pObj) ); - assert( nNums < 6 ); - return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums ); -} - - - - - -/**Function************************************************************* - - Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) -{ - int i; - if ( pCut->nSize < pCut->nSizeMax ) - return 1; - for ( i = 0; i < pCut->nSize; i++ ) - if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Derives new cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) -{ - unsigned uHash = 0; - int i, k; - assert( pCut->nSize > 0 ); - assert( IdNew0 < IdNew1 ); - for ( i = k = 0; i < pCut->nSize; i++ ) - { - if ( pCut->pArray[i] == IdOld ) - continue; - if ( IdNew0 >= 0 ) - { - if ( IdNew0 <= pCut->pArray[i] ) - { - if ( IdNew0 < pCut->pArray[i] ) - { - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_CutHashValue( IdNew0 ); - } - IdNew0 = -1; - } - } - if ( IdNew1 >= 0 ) - { - if ( IdNew1 <= pCut->pArray[i] ) - { - if ( IdNew1 < pCut->pArray[i] ) - { - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_CutHashValue( IdNew1 ); - } - IdNew1 = -1; - } - } - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = pCut->pArray[i]; - uHash |= Ivy_CutHashValue( pCut->pArray[i] ); - } - if ( IdNew0 >= 0 ) - { - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_CutHashValue( IdNew0 ); - } - if ( IdNew1 >= 0 ) - { - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_CutHashValue( IdNew1 ); - } - pCutNew->nSize = k; - pCutNew->uHash = uHash; - assert( pCutNew->nSize <= pCut->nSizeMax ); - for ( i = 1; i < pCutNew->nSize; i++ ) - assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Derives new cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) -{ - unsigned uHash = 0; - int i, k; - assert( pCut->nSize > 0 ); - assert( IdNew0 < IdNew1 ); - for ( i = k = 0; i < pCut->nSize; i++ ) - { - if ( pCut->pArray[i] == IdOld ) - continue; - if ( IdNew0 <= pCut->pArray[i] ) - { - if ( IdNew0 < pCut->pArray[i] ) - { - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_CutHashValue( IdNew0 ); - } - IdNew0 = 0x7FFFFFFF; - } - if ( IdNew1 <= pCut->pArray[i] ) - { - if ( IdNew1 < pCut->pArray[i] ) - { - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_CutHashValue( IdNew1 ); - } - IdNew1 = 0x7FFFFFFF; - } - pCutNew->pArray[ k++ ] = pCut->pArray[i]; - uHash |= Ivy_CutHashValue( pCut->pArray[i] ); - } - if ( IdNew0 < 0x7FFFFFFF ) - { - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_CutHashValue( IdNew0 ); - } - if ( IdNew1 < 0x7FFFFFFF ) - { - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_CutHashValue( IdNew1 ); - } - pCutNew->nSize = k; - pCutNew->uHash = uHash; - assert( pCutNew->nSize <= pCut->nSizeMax ); -// for ( i = 1; i < pCutNew->nSize; i++ ) -// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Find the hash value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) -{ - int i; - pCut->uHash = 0; - for ( i = 0; i < pCut->nSize; i++ ) - pCut->uHash |= (1 << (pCut->pArray[i] % 31)); - return pCut->uHash; -} - -/**Function************************************************************* - - Synopsis [Derives new cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) -{ - int i, k; - assert( pCut->nSize > 0 ); - assert( IdNew0 < IdNew1 ); - for ( i = k = 0; i < pCut->nSize; i++ ) - { - if ( pCut->pArray[i] == IdOld ) - continue; - if ( IdNew0 <= pCut->pArray[i] ) - { - if ( IdNew0 < pCut->pArray[i] ) - pCutNew->pArray[ k++ ] = IdNew0; - IdNew0 = 0x7FFFFFFF; - } - if ( IdNew1 <= pCut->pArray[i] ) - { - if ( IdNew1 < pCut->pArray[i] ) - pCutNew->pArray[ k++ ] = IdNew1; - IdNew1 = 0x7FFFFFFF; - } - pCutNew->pArray[ k++ ] = pCut->pArray[i]; - } - if ( IdNew0 < 0x7FFFFFFF ) - pCutNew->pArray[ k++ ] = IdNew0; - if ( IdNew1 < 0x7FFFFFFF ) - pCutNew->pArray[ k++ ] = IdNew1; - pCutNew->nSize = k; - assert( pCutNew->nSize <= pCut->nSizeMax ); - Ivy_NodeCutHash( pCutNew ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) -{ - int i, k; - for ( i = 0; i < pDom->nSize; i++ ) - { - assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] ); - for ( k = 0; k < pCut->nSize; k++ ) - if ( pDom->pArray[i] == pCut->pArray[k] ) - break; - if ( k == pCut->nSize ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Check if the cut exists.] - - Description [Returns 1 if the cut exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) -{ - Ivy_Cut_t * pCut; - int i, k; - assert( pCutNew->uHash ); - // try to find the cut - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - if ( pCut->nSize == pCutNew->nSize ) - { - if ( pCut->uHash == pCutNew->uHash ) - { - for ( k = 0; k < pCutNew->nSize; k++ ) - if ( pCut->pArray[k] != pCutNew->pArray[k] ) - break; - if ( k == pCutNew->nSize ) - return 1; - } - continue; - } - if ( pCut->nSize < pCutNew->nSize ) - { - // skip the non-contained cuts - if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) - continue; - // check containment seriously - if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) - return 1; - continue; - } - // check potential containment of other cut - - // skip the non-contained cuts - if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) - continue; - // check containment seriously - if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) - { - // remove the current cut - pCut->nSize = 0; - } - } - assert( pCutStore->nCuts < pCutStore->nCutsMax ); - // add the cut - pCut = pCutStore->pCuts + pCutStore->nCuts++; - *pCut = *pCutNew; - return 0; -} - -/**Function************************************************************* - - Synopsis [Compresses the cut representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_CutCompactAll( Ivy_Store_t * pCutStore ) -{ - Ivy_Cut_t * pCut; - int i, k; - pCutStore->nCutsM = 0; - for ( i = k = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - if ( pCut->nSize < pCut->nSizeMax ) - pCutStore->nCutsM++; - pCutStore->pCuts[k++] = *pCut; - } - pCutStore->nCuts = k; -} - -/**Function************************************************************* - - Synopsis [Print the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_CutPrintForNode( Ivy_Cut_t * pCut ) -{ - int i; - assert( pCut->nSize > 0 ); - printf( "%d : {", pCut->nSize ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %d", pCut->pArray[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore ) -{ - int i; - printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); - for ( i = 0; i < pCutStore->nCuts; i++ ) - Ivy_CutPrintForNode( pCutStore->pCuts + i ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin ) -{ - int nLats, iLeaf; - assert( !Ivy_IsComplement(pFanin) ); - if ( !Ivy_ObjIsLatch(pFanin) ) - return Ivy_LeafCreate( pFanin->Id, 0 ); - iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin)); - nLats = Ivy_LeafLat(iLeaf); - assert( nLats < IVY_LEAF_MASK ); - return 1 + iLeaf; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) -{ - static Ivy_Store_t CutStore, * pCutStore = &CutStore; - Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; - Ivy_Man_t * pMan = p; - Ivy_Obj_t * pLeaf; - int i, k, Temp, nLats, iLeaf0, iLeaf1; - - assert( nLeaves <= IVY_CUT_INPUT ); - - // start the structure - pCutStore->nCuts = 0; - pCutStore->nCutsMax = IVY_CUT_LIMIT; - // start the trivial cut - pCutNew->uHash = 0; - pCutNew->nSize = 1; - pCutNew->nSizeMax = nLeaves; - pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 ); - pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] ); - // add the trivial cut - pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew; - assert( pCutStore->nCuts == 1 ); - - // explore the cuts - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - // expand this cut - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - for ( k = 0; k < pCut->nSize; k++ ) - { - pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) ); - if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) ) - continue; - assert( Ivy_ObjIsNode(pLeaf) ); - nLats = Ivy_LeafLat(pCut->pArray[k]); - - // get the fanins fanins - iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) ); - iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) ); - assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK ); - iLeaf0 = nLats + iLeaf0; - iLeaf1 = nLats + iLeaf1; - if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) ) - continue; - // the given cut exist - if ( iLeaf0 > iLeaf1 ) - Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp; - // create the new cut - if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) ) - continue; - // add the cut - Ivy_CutFindOrAddFilter( pCutStore, pCutNew ); - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - break; - } - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - break; - } - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - pCutStore->fSatur = 1; - else - pCutStore->fSatur = 0; -// printf( "%d ", pCutStore->nCuts ); - Ivy_CutCompactAll( pCutStore ); -// printf( "%d \n", pCutStore->nCuts ); -// Ivy_CutPrintForNodes( pCutStore ); - return pCutStore; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ) -{ - Ivy_Store_t * pStore; - Ivy_Obj_t * pObj; - int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver; - int clk = clock(); - if ( nInputs > IVY_CUT_INPUT ) - { - printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT ); - return; - } - nNodeTotal = nNodeOver = 0; - nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( !Ivy_ObjIsNode(pObj) ) - continue; - pStore = Ivy_CutComputeForNode( p, pObj, nInputs ); - nCutsTotal += pStore->nCuts; - nCutsTotalM += pStore->nCutsM; - nNodeOver += pStore->fSatur; - nNodeTotal++; - } - printf( "All = %6d. Minus = %6d. Triv = %6d. Node = %6d. Satur = %6d. ", - nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); - PRT( "Time", clock() - clk ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyShow.c b/src/temp/ivy/ivyShow.c deleted file mode 100644 index cd726e43..00000000 --- a/src/temp/ivy/ivyShow.c +++ /dev/null @@ -1,338 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyShow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Visualization of HAIG.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) -{ - extern void Abc_ShowFile( char * FileNameDot ); - static Counter = 0; - char FileNameDot[200]; - FILE * pFile; - // create the file name -// Ivy_ShowGetFileName( pMan->pName, FileNameDot ); - sprintf( FileNameDot, "temp%02d.dot", Counter++ ); - // check that the file can be opened - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - fclose( pFile ); - // generate the file - Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); - // visualize the file - Abc_ShowFile( FileNameDot ); -} - -/**Function************************************************************* - - Synopsis [Writes the graph structure of AIG for DOT.] - - Description [Useful for graph visualization using tools such as GraphViz: - http://www.graphviz.org/] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) -{ - FILE * pFile; - Ivy_Obj_t * pNode, * pTemp, * pPrev; - int LevelMax, Level, i; - - if ( Ivy_ManNodeNum(pMan) > 200 ) - { - fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); - return; - } - if ( (pFile = fopen( pFileName, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); - return; - } - - // mark the nodes - if ( vBold ) - Vec_PtrForEachEntry( vBold, pNode, i ) - pNode->fMarkB = 1; - - // compute levels - LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig ); - - // write the DOT header - fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "digraph AIG {\n" ); - fprintf( pFile, "size = \"7.5,10\";\n" ); -// fprintf( pFile, "ranksep = 0.5;\n" ); -// fprintf( pFile, "nodesep = 0.5;\n" ); - fprintf( pFile, "center = true;\n" ); -// fprintf( pFile, "orientation = landscape;\n" ); -// fprintf( pFile, "edge [fontsize = 10];\n" ); -// fprintf( pFile, "edge [dir = none];\n" ); - fprintf( pFile, "edge [dir = back];\n" ); - fprintf( pFile, "\n" ); - - // labels on the left of the picture - fprintf( pFile, "{\n" ); - fprintf( pFile, " node [shape = plaintext];\n" ); - fprintf( pFile, " edge [style = invis];\n" ); - fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); - fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); - // generate node names with labels - for ( Level = LevelMax; Level >= 0; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - fprintf( pFile, " [label = " ); - // label name - fprintf( pFile, "\"" ); - fprintf( pFile, "\"" ); - fprintf( pFile, "];\n" ); - } - - // genetate the sequence of visible/invisible nodes to mark levels - fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); - for ( Level = LevelMax; Level >= 0; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - // the connector - if ( Level != 0 ) - fprintf( pFile, " ->" ); - else - fprintf( pFile, ";" ); - } - fprintf( pFile, "\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate title box on top - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle1;\n" ); - fprintf( pFile, " title1 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=20,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - fprintf( pFile, "%s", "AIG structure visualized by ABC" ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); - fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate statistics box - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle2;\n" ); - fprintf( pFile, " title2 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=18,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate the COs - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", LevelMax ); - // generate the CO nodes - Ivy_ManForEachCo( pMan, pNode, i ) - { - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, - (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); - else - fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, - (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), - Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); - fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate nodes of each rank - for ( Level = LevelMax - 1; Level > 0; Level-- ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", Level ); - Ivy_ManForEachObj( pMan, pNode, i ) - { - if ( (int)pNode->Level != Level ) - continue; - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - else - fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, - Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); - fprintf( pFile, ", shape = ellipse" ); - if ( vBold && pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - - // generate the CI nodes - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", 0 ); - // generate constant node - if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 ) - { - pNode = Ivy_ManConst1(pMan); - // check if the costant node is present - fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); - fprintf( pFile, ", shape = ellipse" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - // generate the CI nodes - Ivy_ManForEachCi( pMan, pNode, i ) - { - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, - (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") ); - else - fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, - (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), - Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); - fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate invisible edges from the square down - fprintf( pFile, "title1 -> title2 [style = invis];\n" ); - Ivy_ManForEachCo( pMan, pNode, i ) - fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); - - // generate edges - Ivy_ManForEachObj( pMan, pNode, i ) - { - if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) ) - continue; - // generate the edge from this node to the next - fprintf( pFile, "Node%d%s", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" ); -// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) -// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - if ( !Ivy_ObjIsNode(pNode) ) - continue; - // generate the edge from this node to the next - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" ); -// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) -// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - // generate the edges between the equivalent nodes - if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) - { - pPrev = pNode; - for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { - fprintf( pFile, "Node%d", pPrev->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pTemp->Id ); - fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); - fprintf( pFile, ";\n" ); - pPrev = pTemp; - } - // connect the last node with the first - fprintf( pFile, "Node%d", pPrev->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); - fprintf( pFile, ";\n" ); - } - } - - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - fclose( pFile ); - - // unmark nodes - if ( vBold ) - Vec_PtrForEachEntry( vBold, pNode, i ) - pNode->fMarkB = 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyTable.c b/src/temp/ivy/ivyTable.c deleted file mode 100644 index 2ac0ae49..00000000 --- a/src/temp/ivy/ivyTable.c +++ /dev/null @@ -1,301 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Structural hashing table.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006. ] - - Revision [$Id: ivyTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing the node -static unsigned Ivy_Hash( Ivy_Obj_t * pObj, int TableSize ) -{ - unsigned Key = Ivy_ObjIsExor(pObj) * 1699; - Key ^= Ivy_ObjFaninId0(pObj) * 7937; - Key ^= Ivy_ObjFaninId1(pObj) * 2971; - Key ^= Ivy_ObjFaninC0(pObj) * 911; - Key ^= Ivy_ObjFaninC1(pObj) * 353; - Key ^= Ivy_ObjInit(pObj) * 911; - return Key % TableSize; -} - -// returns the place where this node is stored (or should be stored) -static int * Ivy_TableFind( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - int i; - assert( Ivy_ObjIsHash(pObj) ); - for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) - if ( p->pTable[i] == pObj->Id ) - break; - return p->pTable + i; -} - -static void Ivy_TableResize( Ivy_Man_t * p ); -static unsigned int Cudd_PrimeAig( unsigned int p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks if node with the given attributes is in the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pEntry; - int i; - assert( !Ivy_IsComplement(pObj) ); - if ( !Ivy_ObjIsHash(pObj) ) - return NULL; - assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 ); - assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) ); - if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) ) - return NULL; - for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) - { - pEntry = Ivy_ManObj( p, p->pTable[i] ); - if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) && - Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) && - Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) && - Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) ) - return pEntry; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Adds the node to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - int * pPlace; - assert( !Ivy_IsComplement(pObj) ); - if ( !Ivy_ObjIsHash(pObj) ) - return; - if ( (pObj->Id & 63) == 0 ) - { - if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) ) - Ivy_TableResize( p ); - } - pPlace = Ivy_TableFind( p, pObj ); - assert( *pPlace == 0 ); - *pPlace = pObj->Id; -} - -/**Function************************************************************* - - Synopsis [Deletes the node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pEntry; - int i, * pPlace; - assert( !Ivy_IsComplement(pObj) ); - if ( !Ivy_ObjIsHash(pObj) ) - return; - pPlace = Ivy_TableFind( p, pObj ); - assert( *pPlace == pObj->Id ); // node should be in the table - *pPlace = 0; - // rehash the adjacent entries - i = pPlace - p->pTable; - for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) - { - pEntry = Ivy_ManObj( p, p->pTable[i] ); - p->pTable[i] = 0; - Ivy_TableInsert( p, pEntry ); - } -} - -/**Function************************************************************* - - Synopsis [Updates the table to point to the new node.] - - Description [If the old node (pObj) is in the table, updates the table - to point to an object with different ID (ObjIdNew). The table should - not contain an object with ObjIdNew (this is currently not checked).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ) -{ - int * pPlace; - assert( !Ivy_IsComplement(pObj) ); - if ( !Ivy_ObjIsHash(pObj) ) - return; - pPlace = Ivy_TableFind( p, pObj ); - assert( *pPlace == pObj->Id ); // node should be in the table - *pPlace = ObjIdNew; -} - -/**Function************************************************************* - - Synopsis [Count the number of nodes in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TableCountEntries( Ivy_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - Counter += (p->pTable[i] != 0); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [Typically this procedure should not be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TableResize( Ivy_Man_t * p ) -{ - int * pTableOld, * pPlace; - int nTableSizeOld, Counter, nEntries, e, clk; -clk = clock(); - // save the old table - pTableOld = p->pTable; - nTableSizeOld = p->nTableSize; - // get the new table - p->nTableSize = Cudd_PrimeAig( 5 * Ivy_ManHashObjNum(p) ); - p->pTable = ALLOC( int, p->nTableSize ); - memset( p->pTable, 0, sizeof(int) * p->nTableSize ); - // rehash the entries from the old table - Counter = 0; - for ( e = 0; e < nTableSizeOld; e++ ) - { - if ( pTableOld[e] == 0 ) - continue; - Counter++; - // get the place where this entry goes in the table table - pPlace = Ivy_TableFind( p, Ivy_ManObj(p, pTableOld[e]) ); - assert( *pPlace == 0 ); // should not be in the table - *pPlace = pTableOld[e]; - } - nEntries = Ivy_ManHashObjNum(p); -// assert( Counter == nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( pTableOld ); -} - -/**Function******************************************************************** - - Synopsis [Profiles the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Ivy_TableProfile( Ivy_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - { - if ( p->pTable[i] ) - Counter++; - else if ( Counter ) - { - printf( "%d ", Counter ); - Counter = 0; - } - } -} - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Cudd_PrimeAig( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivyUtil.c b/src/temp/ivy/ivyUtil.c deleted file mode 100644 index 0e44c216..00000000 --- a/src/temp/ivy/ivyUtil.c +++ /dev/null @@ -1,738 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Various procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Increments the current traversal ID of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManIncrementTravId( Ivy_Man_t * p ) -{ - if ( p->nTravIds >= (1<<30)-1 - 1000 ) - Ivy_ManCleanTravId( p ); - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Sets the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCleanTravId( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - p->nTravIds = 1; - Ivy_ManForEachObj( p, pObj, i ) - pObj->TravId = 0; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes ) -{ - if ( pNode->fMarkA ) - return; - pNode->fMarkA = 1; - assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) ); - Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes ); - Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes ); - Vec_IntPush( vNodes, pNode->Id ); -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [Does not modify the array of leaves. Uses array vTruth to store - temporary truth tables. The returned pointer should be used immediately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) -{ - int i, Leaf; - // collect and mark the leaves - Vec_IntClear( vNodes ); - Vec_IntForEachEntry( vLeaves, Leaf, i ) - { - Vec_IntPush( vNodes, Leaf ); - Ivy_ManObj(p, Leaf)->fMarkA = 1; - } - // collect and mark the nodes - Ivy_ManCollectCut_rec( p, pRoot, vNodes ); - // clean the nodes - Vec_IntForEachEntry( vNodes, Leaf, i ) - Ivy_ManObj(p, Leaf)->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth ) -{ - return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords ) -{ - unsigned * pTruth, * pTruth0, * pTruth1; - int i; - pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth ); - pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth ); - pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth ); - if ( Ivy_ObjIsExor(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] ^ pTruth1[i]; - else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & pTruth1[i]; - else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & ~pTruth1[i]; - else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & pTruth1[i]; - else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [Does not modify the array of leaves. Uses array vTruth to store - temporary truth tables. The returned pointer should be used immediately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ) -{ - static unsigned uTruths[8][8] = { // elementary truth tables - { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, - { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, - { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, - { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, - { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, - { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, - { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, - { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } - }; - int i, Leaf; - // collect the cut - Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes ); - // set the node numbers - Vec_IntForEachEntry( vNodes, Leaf, i ) - Ivy_ManObj(p, Leaf)->TravId = i; - // alloc enough memory - Vec_IntClear( vTruth ); - Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) ); - // set the elementary truth tables - Vec_IntForEachEntry( vLeaves, Leaf, i ) - memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) ); - // compute truths for other nodes - Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) ) - Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 ); - return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth ); -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ) -{ - Vec_Int_t * vLatches; - Ivy_Obj_t * pObj; - int i; - vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); - Ivy_ManForEachLatch( p, pObj, i ) - Vec_IntPush( vLatches, pObj->Id ); - return vLatches; -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManLevels( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i, LevelMax = 0; - Ivy_ManForEachPo( p, pObj, i ) - LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); - return LevelMax; -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj ) -{ - if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) - return pObj->Level; - if ( Ivy_ObjIsBuf(pObj) ) - return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); - assert( Ivy_ObjIsNode(pObj) ); - Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); - Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) ); - return pObj->Level = Ivy_ObjLevelNew( pObj ); -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManResetLevels( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - Ivy_ManForEachObj( p, pObj, i ) - pObj->Level = 0; - Ivy_ManForEachCo( p, pObj, i ) - Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [References/references the node and returns MFFC size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel ) -{ - Ivy_Obj_t * pNode0, * pNode1; - int Counter; - // label visited nodes - if ( fLabel ) - Ivy_ObjSetTravIdCurrent( p, pNode ); - // skip the CI - if ( Ivy_ObjIsPi(pNode) ) - return 0; - assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) ); - // process the internal node - pNode0 = Ivy_ObjFanin0(pNode); - pNode1 = Ivy_ObjFanin1(pNode); - Counter = Ivy_ObjIsNode(pNode); - if ( fReference ) - { - if ( pNode0->nRefs++ == 0 ) - Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); - if ( pNode1 && pNode1->nRefs++ == 0 ) - Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); - } - else - { - assert( pNode0->nRefs > 0 ); - assert( pNode1 == NULL || pNode1->nRefs > 0 ); - if ( --pNode0->nRefs == 0 ) - Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); - if ( pNode1 && --pNode1->nRefs == 0 ) - Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Labels MFFC with the current label.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode ) -{ - int nConeSize1, nConeSize2; - assert( !Ivy_IsComplement( pNode ) ); - assert( Ivy_ObjIsNode( pNode ) ); - nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference - nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference - assert( nConeSize1 == nConeSize2 ); - assert( nConeSize1 > 0 ); - return nConeSize1; -} - -/**Function************************************************************* - - Synopsis [Recursively updates fanout levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanout; - Vec_Ptr_t * vFanouts; - int i, LevelNew; - assert( p->fFanout ); - assert( Ivy_ObjIsNode(pObj) ); - vFanouts = Vec_PtrAlloc( 10 ); - Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) - { - if ( Ivy_ObjIsCo(pFanout) ) - { -// assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax ); - continue; - } - LevelNew = Ivy_ObjLevelNew( pFanout ); - if ( (int)pFanout->Level == LevelNew ) - continue; - pFanout->Level = LevelNew; - Ivy_ObjUpdateLevel_rec( p, pFanout ); - } - Vec_PtrFree( vFanouts ); -} - -/**Function************************************************************* - - Synopsis [Compute the new required level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanout; - Vec_Ptr_t * vFanouts; - int i, Required, LevelNew = 1000000; - assert( p->fFanout && p->vRequired ); - vFanouts = Vec_PtrAlloc( 10 ); - Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) - { - Required = Vec_IntEntry(p->vRequired, pFanout->Id); - LevelNew = IVY_MIN( LevelNew, Required ); - } - Vec_PtrFree( vFanouts ); - return LevelNew - 1; -} - -/**Function************************************************************* - - Synopsis [Recursively updates fanout levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ) -{ - Ivy_Obj_t * pFanin; - if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) - return; - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); - // process the first fanin - pFanin = Ivy_ObjFanin0(pObj); - if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) - { - Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); - Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); - } - if ( Ivy_ObjIsBuf(pObj) ) - return; - // process the second fanin - pFanin = Ivy_ObjFanin1(pObj); - if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) - { - Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); - Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); - } -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode ) -{ - Ivy_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Ivy_IsComplement(pNode) ); - // if the node is not AND, this is not MUX - if ( !Ivy_ObjIsAnd(pNode) ) - return 0; - // if the children are not complemented, this is not MUX - if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) ) - return 0; - // get children - pNode0 = Ivy_ObjFanin0(pNode); - pNode1 = Ivy_ObjFanin1(pNode); - // if the children are not ANDs, this is not MUX - if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) ) - return 0; - // otherwise the node is MUX iff it has a pair of equal grandchildren - return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || - (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) || - (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || - (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1))); -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE ) -{ - Ivy_Obj_t * pNode0, * pNode1; - assert( !Ivy_IsComplement(pNode) ); - assert( Ivy_ObjIsMuxType(pNode) ); - // get children - pNode0 = Ivy_ObjFanin0(pNode); - pNode1 = Ivy_ObjFanin1(pNode); - // find the control variable -// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) - if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Ivy_ObjFaninC0(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); - return Ivy_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); - return Ivy_ObjChild0(pNode0);//pNode1->p1; - } - } -// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) - else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Ivy_ObjFaninC0(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); - return Ivy_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); - return Ivy_ObjChild0(pNode0);//pNode1->p1; - } - } -// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) - else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Ivy_ObjFaninC1(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); - return Ivy_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); - return Ivy_ObjChild1(pNode0);//pNode1->p2; - } - } -// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) - else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Ivy_ObjFaninC1(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); - return Ivy_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); - return Ivy_ObjChild1(pNode0);//pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the real fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanin; - if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) ) - return pObj; - pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) ); - return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ) -{ - Ivy_Obj_t * pTemp; - int fShowFanouts = 0; - assert( !Ivy_IsComplement(pObj) ); - printf( "Node %5d : ", Ivy_ObjId(pObj) ); - if ( Ivy_ObjIsConst1(pObj) ) - printf( "constant 1" ); - else if ( Ivy_ObjIsPi(pObj) ) - printf( "PI" ); - else if ( Ivy_ObjIsPo(pObj) ) - printf( "PO" ); - else if ( Ivy_ObjIsLatch(pObj) ) - printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); - else if ( Ivy_ObjIsBuf(pObj) ) - printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); - else - printf( "AND( %5d%s, %5d%s )", - Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "), - Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") ); - printf( " (refs = %3d)", Ivy_ObjRefs(pObj) ); - if ( fShowFanouts ) - { - Vec_Ptr_t * vFanouts; - Ivy_Obj_t * pFanout; - int i; - vFanouts = Vec_PtrAlloc( 10 ); - printf( "\nFanouts:\n" ); - Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) - { - printf( " " ); - printf( "Node %5d : ", Ivy_ObjId(pFanout) ); - if ( Ivy_ObjIsPo(pFanout) ) - printf( "PO" ); - else if ( Ivy_ObjIsLatch(pFanout) ) - printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); - else if ( Ivy_ObjIsBuf(pFanout) ) - printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); - else - printf( "AND( %5d%s, %5d%s )", - Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "), - Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") ); - printf( "\n" ); - } - Vec_PtrFree( vFanouts ); - return; - } - if ( !fHaig ) - { - if ( pObj->pEquiv == NULL ) - printf( " HAIG node not given" ); - else - printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") ); - return; - } - if ( pObj->pEquiv == NULL ) - return; - // there are choices - if ( Ivy_ObjRefs(pObj) > 0 ) - { - // print equivalence class - printf( " { %5d ", pObj->Id ); - assert( !Ivy_IsComplement(pObj->pEquiv) ); - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") ); - printf( " }" ); - return; - } - // this is a secondary node - for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) ); - assert( Ivy_ObjRefs(pTemp) > 0 ); - printf( " class of %d", pTemp->Id ); -} - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ) -{ - Vec_Int_t * vNodes; - Ivy_Obj_t * pObj; - int i; - printf( "PIs: " ); - Ivy_ManForEachPi( p, pObj, i ) - printf( " %d", pObj->Id ); - printf( "\n" ); - printf( "POs: " ); - Ivy_ManForEachPo( p, pObj, i ) - printf( " %d", pObj->Id ); - printf( "\n" ); - printf( "Latches: " ); - Ivy_ManForEachLatch( p, pObj, i ) - printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); - printf( "\n" ); - vNodes = Ivy_ManDfsSeq( p, NULL ); - Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) - Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" ); - printf( "\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/ivy_.c b/src/temp/ivy/ivy_.c deleted file mode 100644 index 65689689..00000000 --- a/src/temp/ivy/ivy_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivy_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ivy/module.make b/src/temp/ivy/module.make deleted file mode 100644 index f5f34f27..00000000 --- a/src/temp/ivy/module.make +++ /dev/null @@ -1,23 +0,0 @@ -SRC += src/temp/ivy/ivyBalance.c \ - src/temp/ivy/ivyCanon.c \ - src/temp/ivy/ivyCheck.c \ - src/temp/ivy/ivyCut.c \ - src/temp/ivy/ivyCutTrav.c \ - src/temp/ivy/ivyDfs.c \ - src/temp/ivy/ivyDsd.c \ - src/temp/ivy/ivyFanout.c \ - src/temp/ivy/ivyFastMap.c \ - src/temp/ivy/ivyFraig.c \ - src/temp/ivy/ivyHaig.c \ - src/temp/ivy/ivyIsop.c \ - src/temp/ivy/ivyMan.c \ - src/temp/ivy/ivyMem.c \ - src/temp/ivy/ivyMulti.c \ - src/temp/ivy/ivyObj.c \ - src/temp/ivy/ivyOper.c \ - src/temp/ivy/ivyResyn.c \ - src/temp/ivy/ivyRwr.c \ - src/temp/ivy/ivySeq.c \ - src/temp/ivy/ivyShow.c \ - src/temp/ivy/ivyTable.c \ - src/temp/ivy/ivyUtil.c diff --git a/src/temp/mem/mem.c b/src/temp/mem/mem.c deleted file mode 100644 index 15199755..00000000 --- a/src/temp/mem/mem.c +++ /dev/null @@ -1,588 +0,0 @@ -/**CFile**************************************************************** - - FileName [esopMem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cover manipulation package.] - - Synopsis [Memory managers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: esopMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include "mem.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Mem_Fixed_t_ -{ - // information about individual entries - int nEntrySize; // the size of one entry - int nEntriesAlloc; // the total number of entries allocated - int nEntriesUsed; // the number of entries in use - int nEntriesMax; // the max number of entries in use - char * pEntriesFree; // the linked list of free entries - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Mem_Flex_t_ -{ - // information about individual entries - int nEntriesUsed; // the number of entries allocated - char * pCurrent; // the current pointer to free memory - char * pEnd; // the first entry outside the free memory - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Mem_Step_t_ -{ - int nMems; // the number of fixed memory managers employed - Mem_Fixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc - int nMapSize; // the size of the memory array - Mem_Fixed_t ** pMap; // maps the number of bytes into its memory manager -}; - -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates memory pieces of fixed size.] - - Description [The size of the chunk is computed as the minimum of - 1024 entries and 64K. Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mem_Fixed_t * Mem_FixedStart( int nEntrySize ) -{ - Mem_Fixed_t * p; - - p = ALLOC( Mem_Fixed_t, 1 ); - memset( p, 0, sizeof(Mem_Fixed_t) ); - - p->nEntrySize = nEntrySize; - p->nEntriesAlloc = 0; - p->nEntriesUsed = 0; - p->pEntriesFree = NULL; - - if ( nEntrySize * (1 << 10) < (1<<16) ) - p->nChunkSize = (1 << 10); - else - p->nChunkSize = (1<<16) / nEntrySize; - if ( p->nChunkSize < 8 ) - p->nChunkSize = 8; - - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", - p->nEntrySize, p->nChunkSize, p->nChunks ); - printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", - p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mem_FixedEntryFetch( Mem_Fixed_t * p ) -{ - char * pTemp; - int i; - - // check if there are still free entries - if ( p->nEntriesUsed == p->nEntriesAlloc ) - { // need to allocate more entries - assert( p->pEntriesFree == NULL ); - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); - p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; - // transform these entries into a linked list - pTemp = p->pEntriesFree; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pEntriesFree; - // add to the number of entries allocated - p->nEntriesAlloc += p->nChunkSize; - } - // incrememt the counter of used entries - p->nEntriesUsed++; - if ( p->nEntriesMax < p->nEntriesUsed ) - p->nEntriesMax = p->nEntriesUsed; - // return the first entry in the free entry list - pTemp = p->pEntriesFree; - p->pEntriesFree = *((char **)pTemp); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ) -{ - // decrement the counter of used entries - p->nEntriesUsed--; - // add the entry to the linked list of free entries - *((char **)pEntry) = p->pEntriesFree; - p->pEntriesFree = pEntry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FixedRestart( Mem_Fixed_t * p ) -{ - int i; - char * pTemp; - - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - // transform these entries into a linked list - pTemp = p->pChunks[0]; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // set the free entry list - p->pEntriesFree = p->pChunks[0]; - // set the correct statistics - p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; - p->nMemoryUsed = 0; - p->nEntriesAlloc = p->nChunkSize; - p->nEntriesUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mem_FixedReadMemUsage( Mem_Fixed_t * p ) -{ - return p->nMemoryAlloc; -} - - - -/**Function************************************************************* - - Synopsis [Allocates entries of flexible size.] - - Description [Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mem_Flex_t * Mem_FlexStart() -{ - Mem_Flex_t * p; - - p = ALLOC( Mem_Flex_t, 1 ); - memset( p, 0, sizeof(Mem_Flex_t) ); - - p->nEntriesUsed = 0; - p->pCurrent = NULL; - p->pEnd = NULL; - - p->nChunkSize = (1 << 14); - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", - p->nChunkSize, p->nChunks ); - printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", - p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ) -{ - char * pTemp; - // check if there are still free entries - if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) - { // need to allocate more entries - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - if ( nBytes > p->nChunkSize ) - { - // resize the chunk size if more memory is requested than it can give - // (ideally, this should never happen) - p->nChunkSize = 2 * nBytes; - } - p->pCurrent = ALLOC( char, p->nChunkSize ); - p->pEnd = p->pCurrent + p->nChunkSize; - p->nMemoryAlloc += p->nChunkSize; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pCurrent; - } - assert( p->pCurrent + nBytes <= p->pEnd ); - // increment the counter of used entries - p->nEntriesUsed++; - // keep track of the memory used - p->nMemoryUsed += nBytes; - // return the next entry - pTemp = p->pCurrent; - p->pCurrent += nBytes; - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FlexRestart( Mem_Flex_t * p ) -{ - int i; - if ( p->nChunks == 0 ) - return; - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - p->nMemoryAlloc = p->nChunkSize; - // transform these entries into a linked list - p->pCurrent = p->pChunks[0]; - p->pEnd = p->pCurrent + p->nChunkSize; - p->nEntriesUsed = 0; - p->nMemoryUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mem_FlexReadMemUsage( Mem_Flex_t * p ) -{ - return p->nMemoryUsed; -} - - - - - -/**Function************************************************************* - - Synopsis [Starts the hierarchical memory manager.] - - Description [This manager can allocate entries of any size. - Iternally they are mapped into the entries with the number of bytes - equal to the power of 2. The smallest entry size is 8 bytes. The - next one is 16 bytes etc. So, if the user requests 6 bytes, he gets - 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. - The input parameters "nSteps" says how many fixed memory managers - are employed internally. Calling this procedure with nSteps equal - to 10 results in 10 hierarchically arranged internal memory managers, - which can allocate up to 4096 (1Kb) entries. Requests for larger - entries are handed over to malloc() and then free()ed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mem_Step_t * Mem_StepStart( int nSteps ) -{ - Mem_Step_t * p; - int i, k; - p = ALLOC( Mem_Step_t, 1 ); - memset( p, 0, sizeof(Mem_Step_t) ); - p->nMems = nSteps; - // start the fixed memory managers - p->pMems = ALLOC( Mem_Fixed_t *, p->nMems ); - for ( i = 0; i < p->nMems; i++ ) - p->pMems[i] = Mem_FixedStart( (8<nMapSize = (4<nMems); - p->pMap = ALLOC( Mem_Fixed_t *, p->nMapSize+1 ); - p->pMap[0] = NULL; - for ( k = 1; k <= 4; k++ ) - p->pMap[k] = p->pMems[0]; - for ( i = 0; i < p->nMems; i++ ) - for ( k = (4<pMap[k] = p->pMems[i]; -//for ( i = 1; i < 100; i ++ ) -//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_StepStop( Mem_Step_t * p, int fVerbose ) -{ - int i; - for ( i = 0; i < p->nMems; i++ ) - Mem_FixedStop( p->pMems[i], fVerbose ); -// if ( p->pLargeChunks ) -// { -// for ( i = 0; i < p->nLargeChunks; i++ ) -// free( p->pLargeChunks[i] ); -// free( p->pLargeChunks ); -// } - free( p->pMems ); - free( p->pMap ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ) -{ - if ( nBytes == 0 ) - return NULL; - if ( nBytes > p->nMapSize ) - { -// printf( "Allocating %d bytes.\n", nBytes ); -/* - if ( p->nLargeChunks == p->nLargeChunksAlloc ) - { - if ( p->nLargeChunksAlloc == 0 ) - p->nLargeChunksAlloc = 5; - p->nLargeChunksAlloc *= 2; - p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); - } - p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes ); - return p->pLargeChunks[ p->nLargeChunks - 1 ]; -*/ - return ALLOC( char, nBytes ); - } - return Mem_FixedEntryFetch( p->pMap[nBytes] ); -} - - -/**Function************************************************************* - - Synopsis [Recycles the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ) -{ - if ( nBytes == 0 ) - return; - if ( nBytes > p->nMapSize ) - { - free( pEntry ); - return; - } - Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mem_StepReadMemUsage( Mem_Step_t * p ) -{ - int i, nMemTotal = 0; - for ( i = 0; i < p->nMems; i++ ) - nMemTotal += p->pMems[i]->nMemoryAlloc; - return nMemTotal; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/temp/mem/mem.h b/src/temp/mem/mem.h deleted file mode 100644 index 611c968d..00000000 --- a/src/temp/mem/mem.h +++ /dev/null @@ -1,71 +0,0 @@ -/**CFile**************************************************************** - - FileName [mem.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Memory management.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MEM_H__ -#define __MEM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Mem_Fixed_t_ Mem_Fixed_t; -typedef struct Mem_Flex_t_ Mem_Flex_t; -typedef struct Mem_Step_t_ Mem_Step_t; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mem.c ===========================================================*/ -// fixed-size-block memory manager -extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize ); -extern void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ); -extern char * Mem_FixedEntryFetch( Mem_Fixed_t * p ); -extern void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ); -extern void Mem_FixedRestart( Mem_Fixed_t * p ); -extern int Mem_FixedReadMemUsage( Mem_Fixed_t * p ); -// flexible-size-block memory manager -extern Mem_Flex_t * Mem_FlexStart(); -extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ); -extern char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ); -extern void Mem_FlexRestart( Mem_Flex_t * p ); -extern int Mem_FlexReadMemUsage( Mem_Flex_t * p ); -// hierarchical memory manager -extern Mem_Step_t * Mem_StepStart( int nSteps ); -extern void Mem_StepStop( Mem_Step_t * p, int fVerbose ); -extern char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ); -extern void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ); -extern int Mem_StepReadMemUsage( Mem_Step_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/mem/module.make b/src/temp/mem/module.make deleted file mode 100644 index 5e4d1d6a..00000000 --- a/src/temp/mem/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/temp/mem/mem.c diff --git a/src/temp/rwt/module.make b/src/temp/rwt/module.make deleted file mode 100644 index 8bbde36d..00000000 --- a/src/temp/rwt/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/temp/rwt/rwtDec.c \ - src/temp/rwt/rwtMan.c \ - src/temp/rwt/rwtUtil.c diff --git a/src/temp/rwt/rwt.h b/src/temp/rwt/rwt.h deleted file mode 100644 index 42a57ad6..00000000 --- a/src/temp/rwt/rwt.h +++ /dev/null @@ -1,155 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __RWT_H__ -#define __RWT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "mem.h" -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -#define RWT_LIMIT 1048576/4 // ((1 << 20) -#define RWT_MIN(a,b) (((a) < (b))? (a) : (b)) -#define RWT_MAX(a,b) (((a) > (b))? (a) : (b)) - -typedef struct Rwt_Man_t_ Rwt_Man_t; -typedef struct Rwt_Node_t_ Rwt_Node_t; - -struct Rwt_Man_t_ -{ - // internal lookups - int nFuncs; // number of four var functions - unsigned short * puCanons; // canonical forms - char * pPhases; // canonical phases - char * pPerms; // canonical permutations - unsigned char * pMap; // mapping of functions into class numbers - unsigned short * pMapInv; // mapping of classes into functions - char * pPractical; // practical NPN classes - char ** pPerms4; // four-var permutations - // node space - Vec_Ptr_t * vForest; // all the nodes - Rwt_Node_t ** pTable; // the hash table of nodes by their canonical form - Vec_Vec_t * vClasses; // the nodes of the equivalence classes - Mem_Fixed_t * pMmNode; // memory for nodes and cuts - // statistical variables - int nTravIds; // the counter of traversal IDs - int nConsidered; // the number of nodes considered - int nAdded; // the number of nodes added to lists - int nClasses; // the number of NN classes - // the result of resynthesis - int fCompl; // indicates if the output of FF should be complemented - void * pCut; // the decomposition tree (temporary) - void * pGraph; // the decomposition tree (temporary) - char * pPerm; // permutation used for the best cut - Vec_Ptr_t * vFanins; // the fanins array (temporary) - Vec_Ptr_t * vFaninsCur; // the fanins array (temporary) - Vec_Int_t * vLevNums; // the array of levels (temporary) - Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary) - // node statistics - int nNodesConsidered; - int nNodesRewritten; - int nNodesGained; - int nScores[222]; - int nCutsGood; - int nCutsBad; - int nSubgraphs; - // runtime statistics - int timeStart; - int timeTruth; - int timeCut; - int timeRes; - int timeEval; - int timeMffc; - int timeUpdate; - int timeTotal; -}; - -struct Rwt_Node_t_ // 24 bytes -{ - int Id; // ID - int TravId; // traversal ID - unsigned uTruth : 16; // truth table - unsigned Volume : 8; // volume - unsigned Level : 6; // level - unsigned fUsed : 1; // mark - unsigned fExor : 1; // mark - Rwt_Node_t * p0; // first child - Rwt_Node_t * p1; // second child - Rwt_Node_t * pNext; // next in the table -}; - -// manipulation of complemented attributes -static inline int Rwt_IsComplement( Rwt_Node_t * p ) { return (int)(((unsigned long)p) & 01); } -static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) & ~01); } -static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) ^ 01); } -static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((unsigned long)(p) ^ (c)); } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== rwrDec.c ========================================================*/ -extern void Rwt_ManPreprocess( Rwt_Man_t * p ); -/*=== rwrMan.c ========================================================*/ -extern Rwt_Man_t * Rwt_ManStart( int fPrecompute ); -extern void Rwt_ManStop( Rwt_Man_t * p ); -extern void Rwt_ManPrintStats( Rwt_Man_t * p ); -extern void Rwt_ManPrintStatsFile( Rwt_Man_t * p ); -extern void * Rwt_ManReadDecs( Rwt_Man_t * p ); -extern Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ); -extern int Rwt_ManReadCompl( Rwt_Man_t * p ); -extern void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time ); -extern void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time ); -extern void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time ); -/*=== rwrUtil.c ========================================================*/ -extern void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ); -extern char * Rwt_ManGetPractical( Rwt_Man_t * p ); -extern Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ); -extern void Rwt_ManIncTravId( Rwt_Man_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/rwt/rwtDec.c b/src/temp/rwt/rwtDec.c deleted file mode 100644 index 98019629..00000000 --- a/src/temp/rwt/rwtDec.c +++ /dev/null @@ -1,150 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwtDec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Evaluation and decomposition procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwtDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwt.h" -#include "deco.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ); -static Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Preprocesses computed library of subgraphs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManPreprocess( Rwt_Man_t * p ) -{ - Dec_Graph_t * pGraph; - Rwt_Node_t * pNode; - int i, k; - // put the nodes into the structure - p->pMapInv = ALLOC( unsigned short, 222 ); - memset( p->pMapInv, 0, sizeof(unsigned short) * 222 ); - p->vClasses = Vec_VecStart( 222 ); - for ( i = 0; i < p->nFuncs; i++ ) - { - if ( p->pTable[i] == NULL ) - continue; - // consider all implementations of this function - for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) - { - assert( pNode->uTruth == p->pTable[i]->uTruth ); - assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 ); - Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode ); - p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth]; - } - } - // compute decomposition forms for each node and verify them - Vec_VecForEachEntry( p->vClasses, pNode, i, k ) - { - pGraph = Rwt_NodePreprocess( p, pNode ); - pNode->pNext = (Rwt_Node_t *)pGraph; -// assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) ); - } -} - -/**Function************************************************************* - - Synopsis [Preprocesses subgraphs rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eRoot; - assert( !Rwt_IsComplement(pNode) ); - // consider constant - if ( pNode->uTruth == 0 ) - return Dec_GraphCreateConst0(); - // consider the case of elementary var - if ( pNode->uTruth == 0x00FF ) - return Dec_GraphCreateLeaf( 3, 4, 1 ); - // start the subgraphs - pGraph = Dec_GraphCreate( 4 ); - // collect the nodes - Rwt_ManIncTravId( p ); - eRoot = Rwt_TravCollect_rec( p, pNode, pGraph ); - Dec_GraphSetRoot( pGraph, eRoot ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - // elementary variable - if ( pNode->fUsed ) - return Dec_EdgeCreate( pNode->Id - 1, 0 ); - // previously visited node - if ( pNode->TravId == p->nTravIds ) - return Dec_IntToEdge( pNode->Volume ); - pNode->TravId = p->nTravIds; - // solve for children - eNode0 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p0), pGraph ); - if ( Rwt_IsComplement(pNode->p0) ) - eNode0.fCompl = !eNode0.fCompl; - eNode1 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p1), pGraph ); - if ( Rwt_IsComplement(pNode->p1) ) - eNode1.fCompl = !eNode1.fCompl; - // create the decomposition node(s) - if ( pNode->fExor ) - eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); - else - eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); - // save the result - pNode->Volume = Dec_EdgeToInt( eNode ); - return eNode; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/rwt/rwtMan.c b/src/temp/rwt/rwtMan.c deleted file mode 100644 index 869043a4..00000000 --- a/src/temp/rwt/rwtMan.c +++ /dev/null @@ -1,358 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwtMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Rewriting manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwt.h" -#include "deco.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned short * s_puCanons = NULL; -static char * s_pPhases = NULL; -static char * s_pPerms = NULL; -static unsigned char * s_pMap = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts residual rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManGlobalStart() -{ - if ( s_puCanons == NULL ) - Extra_Truth4VarNPN( &s_puCanons, &s_pPhases, &s_pPerms, &s_pMap ); -} - -/**Function************************************************************* - - Synopsis [Starts residual rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManGlobalStop() -{ - FREE( s_puCanons ); - FREE( s_pPhases ); - FREE( s_pPerms ); - FREE( s_pMap ); -} - -/**Function************************************************************* - - Synopsis [Starts rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwt_Man_t * Rwt_ManStart( int fPrecompute ) -{ - Rwt_Man_t * p; - int clk = clock(); -clk = clock(); - p = ALLOC( Rwt_Man_t, 1 ); - memset( p, 0, sizeof(Rwt_Man_t) ); - p->nFuncs = (1<<16); - // copy the global tables - Rwt_ManGlobalStart(); - p->puCanons = s_puCanons; - p->pPhases = s_pPhases; - p->pPerms = s_pPerms; - p->pMap = s_pMap; - // initialize practical NPN classes - p->pPractical = Rwt_ManGetPractical( p ); - // create the table - p->pTable = ALLOC( Rwt_Node_t *, p->nFuncs ); - memset( p->pTable, 0, sizeof(Rwt_Node_t *) * p->nFuncs ); - // create the elementary nodes - p->pMmNode = Mem_FixedStart( sizeof(Rwt_Node_t) ); - p->vForest = Vec_PtrAlloc( 100 ); - Rwt_ManAddVar( p, 0x0000, fPrecompute ); // constant 0 - Rwt_ManAddVar( p, 0xAAAA, fPrecompute ); // var A - Rwt_ManAddVar( p, 0xCCCC, fPrecompute ); // var B - Rwt_ManAddVar( p, 0xF0F0, fPrecompute ); // var C - Rwt_ManAddVar( p, 0xFF00, fPrecompute ); // var D - p->nClasses = 5; - // other stuff - p->nTravIds = 1; - p->pPerms4 = Extra_Permutations( 4 ); - p->vLevNums = Vec_IntAlloc( 50 ); - p->vFanins = Vec_PtrAlloc( 50 ); - p->vFaninsCur = Vec_PtrAlloc( 50 ); - p->vNodesTemp = Vec_PtrAlloc( 50 ); - if ( fPrecompute ) - { // precompute subgraphs -// Rwt_ManPrecompute( p ); -// Rwt_ManPrint( p ); -// Rwt_ManWriteToArray( p ); - } - else - { // load saved subgraphs - Rwt_ManLoadFromArray( p, 0 ); -// Rwt_ManPrint( p ); - Rwt_ManPreprocess( p ); - } -p->timeStart = clock() - clk; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManStop( Rwt_Man_t * p ) -{ - if ( p->vClasses ) - { - Rwt_Node_t * pNode; - int i, k; - Vec_VecForEachEntry( p->vClasses, pNode, i, k ) - Dec_GraphFree( (Dec_Graph_t *)pNode->pNext ); - } - if ( p->vClasses ) Vec_VecFree( p->vClasses ); - Vec_PtrFree( p->vNodesTemp ); - Vec_PtrFree( p->vForest ); - Vec_IntFree( p->vLevNums ); - Vec_PtrFree( p->vFanins ); - Vec_PtrFree( p->vFaninsCur ); - Mem_FixedStop( p->pMmNode, 0 ); - FREE( p->pMapInv ); - free( p->pTable ); - free( p->pPractical ); - free( p->pPerms4 ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManPrintStats( Rwt_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < 222; i++ ) - Counter += (p->nScores[i] > 0); - - printf( "Rewriting statistics:\n" ); - printf( "Total cuts tries = %8d.\n", p->nCutsGood ); - printf( "Bad cuts found = %8d.\n", p->nCutsBad ); - printf( "Total subgraphs = %8d.\n", p->nSubgraphs ); - printf( "Used NPN classes = %8d.\n", Counter ); - printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); - printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten ); - printf( "Calculated gain = %8d.\n", p->nNodesGained ); - PRT( "Start ", p->timeStart ); - PRT( "Cuts ", p->timeCut ); - PRT( "Truth ", p->timeTruth ); - PRT( "Resynthesis ", p->timeRes ); - PRT( " Mffc ", p->timeMffc ); - PRT( " Eval ", p->timeEval ); - PRT( "Update ", p->timeUpdate ); - PRT( "TOTAL ", p->timeTotal ); - -/* - printf( "The scores are:\n" ); - for ( i = 0; i < 222; i++ ) - if ( p->nScores[i] > 0 ) - { - extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); - printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] ); - Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) ); - } - printf( "\n" ); -*/ -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManPrintStatsFile( Rwt_Man_t * p ) -{ - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%d ", p->nCutsGood ); - fprintf( pTable, "%d ", p->nSubgraphs ); - fprintf( pTable, "%d ", p->nNodesRewritten ); - fprintf( pTable, "%d", p->nNodesGained ); - fprintf( pTable, "\n" ); - fclose( pTable ); -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Rwt_ManReadDecs( Rwt_Man_t * p ) -{ - return p->pGraph; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ) -{ - return p->vFanins; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwt_ManReadCompl( Rwt_Man_t * p ) -{ - return p->fCompl; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time ) -{ - p->timeCut += Time; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time ) -{ - p->timeUpdate += Time; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time ) -{ - p->timeTotal += Time; -} - - -/**Function************************************************************* - - Synopsis [Precomputes AIG subgraphs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Precompute() -{ - Rwt_Man_t * p; - p = Rwt_ManStart( 1 ); - Rwt_ManStop( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/rwt/rwtUtil.c b/src/temp/rwt/rwtUtil.c deleted file mode 100644 index af3e1893..00000000 --- a/src/temp/rwt/rwtUtil.c +++ /dev/null @@ -1,665 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwtUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwtUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// precomputed data -#ifdef _WIN32 -unsigned short s_RwtPracticalClasses[]; -unsigned short s_RwtAigSubgraphs[]; -#else -static unsigned short s_RwtPracticalClasses[]; -static unsigned short s_RwtAigSubgraphs[]; -#endif - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds the node to the end of the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ListAddToTail( Rwt_Node_t ** ppList, Rwt_Node_t * pNode ) -{ - Rwt_Node_t * pTemp; - // find the last one - for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext ) - ppList = &pTemp->pNext; - // attach at the end - *ppList = pNode; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ) -{ - Rwt_Node_t * pNew; - pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); - pNew->Id = p->vForest->nSize; - pNew->TravId = 0; - pNew->uTruth = uTruth; - pNew->Level = 0; - pNew->Volume = 0; - pNew->fUsed = 1; - pNew->fExor = 0; - pNew->p0 = NULL; - pNew->p1 = NULL; - pNew->pNext = NULL; - Vec_PtrPush( p->vForest, pNew ); - if ( fPrecompute ) - Rwt_ListAddToTail( p->pTable + uTruth, pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwt_Node_t * Rwt_ManAddNode( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1, int fExor, int Level, int Volume ) -{ - Rwt_Node_t * pNew; - unsigned uTruth; - // compute truth table, leve, volume - p->nConsidered++; - if ( fExor ) - uTruth = (p0->uTruth ^ p1->uTruth); - else - uTruth = (Rwt_IsComplement(p0)? ~Rwt_Regular(p0)->uTruth : Rwt_Regular(p0)->uTruth) & - (Rwt_IsComplement(p1)? ~Rwt_Regular(p1)->uTruth : Rwt_Regular(p1)->uTruth) & 0xFFFF; - // create the new node - pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); - pNew->Id = p->vForest->nSize; - pNew->TravId = 0; - pNew->uTruth = uTruth; - pNew->Level = Level; - pNew->Volume = Volume; - pNew->fUsed = 0; - pNew->fExor = fExor; - pNew->p0 = p0; - pNew->p1 = p1; - pNew->pNext = NULL; - Vec_PtrPush( p->vForest, pNew ); - // do not add if the node is not essential - if ( uTruth != p->puCanons[uTruth] ) - return pNew; - - // add to the list - p->nAdded++; - if ( p->pTable[uTruth] == NULL ) - p->nClasses++; - Rwt_ListAddToTail( p->pTable + uTruth, pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Trav_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, int * pVolume ) -{ - if ( pNode->fUsed || pNode->TravId == p->nTravIds ) - return; - pNode->TravId = p->nTravIds; - (*pVolume)++; - if ( pNode->fExor ) - (*pVolume)++; - Rwt_Trav_rec( p, Rwt_Regular(pNode->p0), pVolume ); - Rwt_Trav_rec( p, Rwt_Regular(pNode->p1), pVolume ); -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManIncTravId( Rwt_Man_t * p ) -{ - Rwt_Node_t * pNode; - int i; - if ( p->nTravIds++ < 0x8FFFFFFF ) - return; - Vec_PtrForEachEntry( p->vForest, pNode, i ) - pNode->TravId = 0; - p->nTravIds = 1; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwt_ManNodeVolume( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1 ) -{ - int Volume = 0; - Rwt_ManIncTravId( p ); - Rwt_Trav_rec( p, p0, &Volume ); - Rwt_Trav_rec( p, p1, &Volume ); - return Volume; -} - -/**Function************************************************************* - - Synopsis [Loads data.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ) -{ - unsigned short * pArray = s_RwtAigSubgraphs; - Rwt_Node_t * p0, * p1; - unsigned Entry0, Entry1; - int Level, Volume, nEntries, fExor; - int i, clk = clock(); - - // reconstruct the forest - for ( i = 0; ; i++ ) - { - Entry0 = pArray[2*i + 0]; - Entry1 = pArray[2*i + 1]; - if ( Entry0 == 0 && Entry1 == 0 ) - break; - // get EXOR flag - fExor = (Entry0 & 1); - Entry0 >>= 1; - // get the nodes - p0 = p->vForest->pArray[Entry0 >> 1]; - p1 = p->vForest->pArray[Entry1 >> 1]; - // compute the level and volume of the new nodes - Level = 1 + RWT_MAX( p0->Level, p1->Level ); - Volume = 1 + Rwt_ManNodeVolume( p, p0, p1 ); - // set the complemented attributes - p0 = Rwt_NotCond( p0, (Entry0 & 1) ); - p1 = Rwt_NotCond( p1, (Entry1 & 1) ); - // add the node -// Rwt_ManTryNode( p, p0, p1, Level, Volume ); - Rwt_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); - } - nEntries = i - 1; - if ( fVerbose ) - { - printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); - printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk ); - } -} - -/**Function************************************************************* - - Synopsis [Create practical classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Rwt_ManGetPractical( Rwt_Man_t * p ) -{ - char * pPractical; - int i; - pPractical = ALLOC( char, p->nFuncs ); - memset( pPractical, 0, sizeof(char) * p->nFuncs ); - pPractical[0] = 1; - for ( i = 1; ; i++ ) - { - if ( s_RwtPracticalClasses[i] == 0 ) - break; - pPractical[ s_RwtPracticalClasses[i] ] = 1; - } - return pPractical; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -// the following 135 practical NPN classes of 4-variable functions were computed -// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks -static unsigned short s_RwtPracticalClasses[] = -{ - 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, - 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, - 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, - 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, - 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab, - 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, - 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368, - 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5, - 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669, - 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2, - 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8, - 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4, - 0x1ee1, 0x3cc3, 0x6996, 0x0000 -}; - -static unsigned short s_RwtAigSubgraphs[] = -{ - 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, - 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, - 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, - 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, - 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, - 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, - 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, - 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, - 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, - 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, - 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, - 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, - 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, - 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, - 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, - 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, - 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, - 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, - 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, - 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, - 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, - 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, - 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, - 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, - 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, - 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, - 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, - 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, - 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, - 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, - 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, - 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, - 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, - 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, - 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, - 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, - 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, - 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, - 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, - 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, - 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, - 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, - 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, - 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, - 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, - 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, - 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, - 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, - 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, - 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, - 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, - 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, - 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, - 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, - 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, - 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, - 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, - 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, - 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, - 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, - 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, - 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, - 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, - 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, - 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, - 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, - 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, - 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, - 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, - 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, - 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, - 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, - 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, - 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, - 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, - 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, - 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, - 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, - 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, - 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, - 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, - 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, - 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, - 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, - 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, - 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, - 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, - 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, - 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, - 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, - 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, - 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, - 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, - 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, - 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, - 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, - 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, - 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, - 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, - 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, - 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, - 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, - 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, - 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, - 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, - 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, - 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, - 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, - 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, - 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, - 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, - 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, - 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, - 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, - 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, - 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, - 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, - 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, - 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, - 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, - 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, - 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, - 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, - 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, - 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, - 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, - 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, - 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, - 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, - 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, - 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, - 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, - 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, - 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, - 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, - 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, - 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, - 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, - 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, - 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, - 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, - 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, - 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, - 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, - 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, - 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, - 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, - 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, - 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, - 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, - 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, - 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, - 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, - 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, - 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, - 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, - 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, - 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, - 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, - 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, - 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, - 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, - 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, - 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, - 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, - 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, - 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, - 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, - 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, - 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, - 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, - 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, - 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, - 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, - 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, - 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, - 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, - 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, - 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, - 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, - 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, - 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, - 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, - 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, - 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, - 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, - 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, - 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, - 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, - 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, - 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, - 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, - 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, - 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, - 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, - 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, - 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, - 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, - 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, - 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, - 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, - 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, - 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, - 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, - 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, - 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, - 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, - 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, - 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, - 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, - 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, - 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, - 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, - 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, - 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, - 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, - 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, - 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, - 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, - 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, - 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, - 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, - 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, - 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, - 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, - 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, - 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, - 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, - 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, - 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, - 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, - 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, - 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, - 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, - 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, - 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, - 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, - 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, - 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, - 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, - 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, - 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, - 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, - 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, - 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, - 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, - 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, - 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, - 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, - 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, - 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, - 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, - 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, - 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, - 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, - 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, - 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, - 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, - 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, - 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, - 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, - 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, - 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, - 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, - 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, - 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, - 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, - 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, - 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, - 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, - 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, - 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, - 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, - 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, - 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, - 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, - 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, - 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, - 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, - 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, - 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, - 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, - 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, - 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, - 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, - 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, - 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, - 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, - 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, - 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, - 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, - 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, - 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, - 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, - 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, - 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, - 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, - 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, - 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, - 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, - 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, - 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, - 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, - 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, - 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, - 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, - 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, - 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, - 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, - 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, - 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, - 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, - 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, - 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, - 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, - 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, - 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, - 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, - 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, - 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, - 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, - 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, - 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, - 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, - 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, - 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, - 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, - 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, - 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, - 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, - 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, - 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, - 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, - 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, - 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, - 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, - 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, - 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, - 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, - 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, - 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, - 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, - 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, - 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, - 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, - 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, - 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, - 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, - 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, - 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, - 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, - 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, - 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, - 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, - 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, - 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, - 0x0000,0x0000 -}; - - diff --git a/src/temp/ver/module.make b/src/temp/ver/module.make deleted file mode 100644 index a58a2c60..00000000 --- a/src/temp/ver/module.make +++ /dev/null @@ -1,4 +0,0 @@ -SRC += src/temp/ver/verCore.c \ - src/temp/ver/verFormula.c \ - src/temp/ver/verParse.c \ - src/temp/ver/verStream.c diff --git a/src/temp/ver/ver.h b/src/temp/ver/ver.h deleted file mode 100644 index c7c18f79..00000000 --- a/src/temp/ver/ver.h +++ /dev/null @@ -1,114 +0,0 @@ -/**CFile**************************************************************** - - FileName [ver.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: ver.h,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VER_H__ -#define __VER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ver_Man_t_ Ver_Man_t; -typedef struct Ver_Stream_t_ Ver_Stream_t; - -struct Ver_Man_t_ -{ - // input file stream - char * pFileName; - Ver_Stream_t * pReader; - ProgressBar * pProgress; - // current network and library - Abc_Ntk_t * pNtkCur; // the network under construction - Abc_Lib_t * pDesign; // the current design - // parameters - int fUseMemMan; // allocate memory manager in the networks - int fCheck; // checks network for currectness - // error recovery - FILE * Output; - int fTopLevel; - int fError; - char sError[2000]; - // intermediate structures - Vec_Ptr_t * vNames; - Vec_Ptr_t * vStackFn; - Vec_Int_t * vStackOp; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== verCore.c ========================================================*/ -extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); -extern void Ver_ParsePrintErrorMessage( Ver_Man_t * p ); -/*=== verFormula.c ========================================================*/ -extern void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ); -extern void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ); -/*=== verParse.c ========================================================*/ -extern int Ver_ParseSkipComments( Ver_Man_t * p ); -extern char * Ver_ParseGetName( Ver_Man_t * p ); -/*=== verStream.c ========================================================*/ -extern Ver_Stream_t * Ver_StreamAlloc( char * pFileName ); -extern void Ver_StreamFree( Ver_Stream_t * p ); -extern char * Ver_StreamGetFileName( Ver_Stream_t * p ); -extern int Ver_StreamGetFileSize( Ver_Stream_t * p ); -extern int Ver_StreamGetCurPosition( Ver_Stream_t * p ); -extern int Ver_StreamGetLineNumber( Ver_Stream_t * p ); - -extern int Ver_StreamIsOkey( Ver_Stream_t * p ); -extern char Ver_StreamScanChar( Ver_Stream_t * p ); -extern char Ver_StreamPopChar( Ver_Stream_t * p ); -extern void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ); -extern void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ); -extern char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/temp/ver/verCore.c b/src/temp/ver/verCore.c deleted file mode 100644 index 352a4361..00000000 --- a/src/temp/ver/verCore.c +++ /dev/null @@ -1,1092 +0,0 @@ -/**CFile**************************************************************** - - FileName [verCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Parses several flavors of structural Verilog.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// types of verilog signals -typedef enum { - VER_SIG_NONE = 0, - VER_SIG_INPUT, - VER_SIG_OUTPUT, - VER_SIG_INOUT, - VER_SIG_REG, - VER_SIG_WIRE -} Ver_SignalType_t; - -// types of verilog gates -typedef enum { - VER_GATE_AND = 0, - VER_GATE_OR, - VER_GATE_XOR, - VER_GATE_BUF, - VER_GATE_NAND, - VER_GATE_NOR, - VER_GATE_XNOR, - VER_GATE_NOT -} Ver_GateType_t; - -static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ); -static void Ver_ParseStop( Ver_Man_t * p ); -static void Ver_ParseFreeData( Ver_Man_t * p ); -static void Ver_ParseInternal( Ver_Man_t * p ); -static int Ver_ParseModule( Ver_Man_t * p ); -static int Ver_ParseSignal( Ver_Man_t * p, Ver_SignalType_t SigType ); -static int Ver_ParseAssign( Ver_Man_t * p ); -static int Ver_ParseAlways( Ver_Man_t * p ); -static int Ver_ParseInitial( Ver_Man_t * p ); -static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtkGate ); -static int Ver_ParseGateStandard( Ver_Man_t * pMan, Ver_GateType_t GateType ); - -static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ); -static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ); -static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [File parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ) -{ - Ver_Man_t * p; - Abc_Lib_t * pDesign; - // start the parser - p = Ver_ParseStart( pFileName, pGateLib ); - p->fCheck = fCheck; - p->fUseMemMan = fUseMemMan; - // parse the file - Ver_ParseInternal( p ); - // save the result - pDesign = p->pDesign; - p->pDesign = NULL; - // stop the parser - Ver_ParseStop( p ); - return pDesign; -} - -/**Function************************************************************* - - Synopsis [Start parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ) -{ - Ver_Man_t * p; - p = ALLOC( Ver_Man_t, 1 ); - memset( p, 0, sizeof(Ver_Man_t) ); - p->pFileName = pFileName; - p->pReader = Ver_StreamAlloc( pFileName ); - p->Output = stdout; - p->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(p->pReader) ); - p->vNames = Vec_PtrAlloc( 100 ); - p->vStackFn = Vec_PtrAlloc( 100 ); - p->vStackOp = Vec_IntAlloc( 100 ); - // create the design library and assign the technology library - p->pDesign = Abc_LibCreate( pFileName ); - p->pDesign->pLibrary = pGateLib; - return p; -} - -/**Function************************************************************* - - Synopsis [Stop parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseStop( Ver_Man_t * p ) -{ - assert( p->pNtkCur == NULL ); - Ver_StreamFree( p->pReader ); - Extra_ProgressBarStop( p->pProgress ); - Vec_PtrFree( p->vNames ); - Vec_PtrFree( p->vStackFn ); - Vec_IntFree( p->vStackOp ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [File parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseInternal( Ver_Man_t * pMan ) -{ - char * pToken; - while ( 1 ) - { - // get the next token - pToken = Ver_ParseGetName( pMan ); - if ( pToken == NULL ) - break; - if ( strcmp( pToken, "module" ) ) - { - sprintf( pMan->sError, "Cannot read \"module\" directive." ); - Ver_ParsePrintErrorMessage( pMan ); - return; - } - - // parse the module - if ( !Ver_ParseModule( pMan ) ) - return; - - // check the network for correctness - if ( pMan->fCheck && !Abc_NtkCheckRead( pMan->pNtkCur ) ) - { - pMan->fTopLevel = 1; - sprintf( pMan->sError, "The network check has failed.", pMan->pNtkCur->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return; - } - // add the module to the hash table - if ( st_is_member( pMan->pDesign->tModules, pMan->pNtkCur->pName ) ) - { - pMan->fTopLevel = 1; - sprintf( pMan->sError, "Module \"%s\" is defined more than once.", pMan->pNtkCur->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return; - } - Vec_PtrPush( pMan->pDesign->vModules, pMan->pNtkCur ); - st_insert( pMan->pDesign->tModules, pMan->pNtkCur->pName, (char *)pMan->pNtkCur ); - pMan->pNtkCur = NULL; - } -} - -/**Function************************************************************* - - Synopsis [File parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseFreeData( Ver_Man_t * p ) -{ - if ( p->pNtkCur ) - { - p->pNtkCur->pManFunc = NULL; - Abc_NtkDelete( p->pNtkCur ); - p->pNtkCur = NULL; - } - if ( p->pDesign ) - { - Abc_LibFree( p->pDesign ); - p->pDesign = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Prints the error message including the file name and line number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParsePrintErrorMessage( Ver_Man_t * p ) -{ - p->fError = 1; - if ( p->fTopLevel ) // the line number is not given - fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); - else // print the error message with the line number - fprintf( p->Output, "%s (line %d): %s\n", - p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError ); - // free the data - Ver_ParseFreeData( p ); -} - - - -/**Function************************************************************* - - Synopsis [Parses one Verilog module.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseModule( Ver_Man_t * pMan ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Ntk_t * pNtk, * pNtkTemp; - Abc_Obj_t * pNet; - char * pWord, Symbol; - int RetValue; - - // start the current network - assert( pMan->pNtkCur == NULL ); - pNtk = pMan->pNtkCur = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan ); - pNtk->ntkFunc = ABC_FUNC_AIG; - pNtk->pManFunc = pMan->pDesign->pManFunc; - - // get the network name - pWord = Ver_ParseGetName( pMan ); - pNtk->pName = Extra_UtilStrsav( pWord ); - pNtk->pSpec = NULL; - - // create constant nets - Abc_NtkFindOrCreateNet( pNtk, "1'b0" ); - Abc_NtkFindOrCreateNet( pNtk, "1'b1" ); - - // make sure we stopped at the opening paranthesis - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot find \"(\" after \"module\".", pNtk->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // skip to the end of parantheses - do { - if ( Ver_ParseGetName( pMan ) == NULL ) - return 0; - Symbol = Ver_StreamPopChar(p); - } while ( Symbol == ',' ); - assert( Symbol == ')' ); - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - Symbol = Ver_StreamPopChar(p); - assert( Symbol == ';' ); - - // parse the inputs/outputs/registers/wires/inouts - while ( 1 ) - { - Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - if ( !strcmp( pWord, "input" ) ) - RetValue = Ver_ParseSignal( pMan, VER_SIG_INPUT ); - else if ( !strcmp( pWord, "output" ) ) - RetValue = Ver_ParseSignal( pMan, VER_SIG_OUTPUT ); - else if ( !strcmp( pWord, "reg" ) ) - RetValue = Ver_ParseSignal( pMan, VER_SIG_REG ); - else if ( !strcmp( pWord, "wire" ) ) - RetValue = Ver_ParseSignal( pMan, VER_SIG_WIRE ); - else if ( !strcmp( pWord, "inout" ) ) - RetValue = Ver_ParseSignal( pMan, VER_SIG_INOUT ); - else - break; - if ( RetValue == 0 ) - return 0; - } - - // parse the remaining statements - while ( 1 ) - { - Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); - - if ( !strcmp( pWord, "and" ) ) - RetValue = Ver_ParseGateStandard( pMan, VER_GATE_AND ); - else if ( !strcmp( pWord, "or" ) ) - RetValue = Ver_ParseGateStandard( pMan, VER_GATE_OR ); - else if ( !strcmp( pWord, "xor" ) ) - RetValue = Ver_ParseGateStandard( pMan, VER_GATE_XOR ); - else if ( !strcmp( pWord, "buf" ) ) - RetValue = Ver_ParseGateStandard( pMan, VER_GATE_BUF ); - else if ( !strcmp( pWord, "nand" ) ) - RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NAND ); - else if ( !strcmp( pWord, "nor" ) ) - RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NOR ); - else if ( !strcmp( pWord, "xnor" ) ) - RetValue = Ver_ParseGateStandard( pMan, VER_GATE_XNOR ); - else if ( !strcmp( pWord, "not" ) ) - RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NOT ); - - else if ( !strcmp( pWord, "assign" ) ) - RetValue = Ver_ParseAssign( pMan ); - else if ( !strcmp( pWord, "always" ) ) - RetValue = Ver_ParseAlways( pMan ); - else if ( !strcmp( pWord, "initial" ) ) - RetValue = Ver_ParseInitial( pMan ); - else if ( !strcmp( pWord, "endmodule" ) ) - break; - else if ( pMan->pDesign->pLibrary && st_lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library - RetValue = Ver_ParseGate( pMan, pNtkTemp ); - else if ( pMan->pDesign && st_lookup(pMan->pDesign->tModules, pWord, (char**)&pNtkTemp) ) // current design - RetValue = Ver_ParseGate( pMan, pNtkTemp ); - else - { - printf( "Cannot find \"%s\".\n", pWord ); - Ver_StreamSkipToChars( p, ";" ); - Ver_StreamPopChar(p); - -// sprintf( pMan->sError, "Cannot find \"%s\" in the library.", pWord ); -// Ver_ParsePrintErrorMessage( pMan ); -// return 0; - } - if ( RetValue == 0 ) - return 0; - // skip the comments - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - // get new word - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - } - - // check if constant 0 net is used - pNet = Abc_NtkFindOrCreateNet( pNtk, "1'b0" ); - if ( Abc_ObjFanoutNum(pNet) == 0 ) - Abc_NtkDeleteObj(pNet); - else - Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) ); - // check if constant 1 net is used - pNet = Abc_NtkFindOrCreateNet( pNtk, "1'b1" ); - if ( Abc_ObjFanoutNum(pNet) == 0 ) - Abc_NtkDeleteObj(pNet); - else - Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) ); - - // fix the dangling nets - Abc_NtkFinalizeRead( pNtk ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseSignal( Ver_Man_t * pMan, Ver_SignalType_t SigType ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Ntk_t * pNtk = pMan->pNtkCur; - char * pWord; - char Symbol; - while ( 1 ) - { - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) - Ver_ParseCreatePi( pNtk, pWord ); - if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) - Ver_ParseCreatePo( pNtk, pWord ); - if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) - Abc_NtkFindOrCreateNet( pNtk, pWord ); - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ',' ) - continue; - if ( Symbol == ';' ) - return 1; - break; - } - sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseAssign( Ver_Man_t * pMan ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Ntk_t * pNtk = pMan->pNtkCur; - Abc_Obj_t * pNode, * pNet; - char * pWord, * pName, * pEquation; - Aig_Obj_t * pFunc; - char Symbol; - int i, Length, fReduction; - - // convert from the mapped netlist into the BDD netlist - if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) - { - pNtk->ntkFunc = ABC_FUNC_AIG; - assert( pNtk->pManFunc == NULL ); - pNtk->pManFunc = pMan->pDesign->pManFunc; - } - else if ( pNtk->ntkFunc != ABC_FUNC_AIG ) - { - sprintf( pMan->sError, "The network %s appears to mapped gates and assign statements. Currently such network are not allowed. One way to fix this problem is to replace assigns by buffers from the library.", pMan->pNtkCur ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - while ( 1 ) - { - // get the name of the output signal - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // consider the case of reduction operations - fReduction = (pWord[0] == '{'); - if ( fReduction ) - { - pWord++; - pWord[strlen(pWord)-1] = 0; - assert( pWord[0] != '\\' ); - } - // get the fanout net - pNet = Abc_NtkFindNet( pNtk, pWord ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // get the equal sign - if ( Ver_StreamPopChar(p) != '=' ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // skip the comments - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - // get the second name - if ( fReduction ) - pEquation = Ver_StreamGetWord( p, ";" ); - else - pEquation = Ver_StreamGetWord( p, ",;" ); - if ( pEquation == NULL ) - return 0; - - // parse the formula - if ( fReduction ) - pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError ); - else - pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError ); - if ( pFunc == NULL ) - { - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // create the node with the given inputs - pNode = Abc_NtkCreateNode( pMan->pNtkCur ); - pNode->pData = pFunc; - Abc_ObjAddFanin( pNet, pNode ); - // connect to fanin nets - for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ ) - { - // get the name of this signal - Length = (int)Vec_PtrEntry( pMan->vNames, 2*i ); - pName = Vec_PtrEntry( pMan->vNames, 2*i + 1 ); - pName[Length] = 0; - // find the corresponding net - pNet = Abc_NtkFindNet( pNtk, pName ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %d is not defined).", pWord, pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Abc_ObjAddFanin( pNode, pNet ); - } - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ',' ) - continue; - if ( Symbol == ';' ) - return 1; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseAlways( Ver_Man_t * pMan ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Ntk_t * pNtk = pMan->pNtkCur; - Abc_Obj_t * pNet, * pNet2; - char * pWord, * pWord2; - char Symbol; - // parse the directive - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - if ( strcmp( pWord, "begin" ) ) - { - sprintf( pMan->sError, "Cannot parse the always statement (expected \"begin\")." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // iterate over the initial states - while ( 1 ) - { - // get the name of the output signal - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // look for the end of directive - if ( !strcmp( pWord, "end" ) ) - break; - // get the fanout net - pNet = Abc_NtkFindNet( pNtk, pWord ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // get the equal sign - if ( Ver_StreamPopChar(p) != '=' ) - { - sprintf( pMan->sError, "Cannot read the always statement for %s (expected equality sign).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // skip the comments - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - // get the second name - pWord2 = Ver_ParseGetName( pMan ); - if ( pWord2 == NULL ) - return 0; - // get the fanin net - pNet2 = Abc_NtkFindNet( pNtk, pWord2 ); - if ( pNet2 == NULL ) - { - sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // create the latch - Ver_ParseCreateLatch( pNtk, pNet2->pData, pNet->pData ); - // remove the last symbol - Symbol = Ver_StreamPopChar(p); - assert( Symbol == ';' ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseInitial( Ver_Man_t * pMan ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Ntk_t * pNtk = pMan->pNtkCur; - Abc_Obj_t * pNode, * pNet; - char * pWord, * pEquation; - char Symbol; - // parse the directive - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - if ( strcmp( pWord, "begin" ) ) - { - sprintf( pMan->sError, "Cannot parse the initial statement (expected \"begin\")." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // iterate over the initial states - while ( 1 ) - { - // get the name of the output signal - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // look for the end of directive - if ( !strcmp( pWord, "end" ) ) - break; - // get the fanout net - pNet = Abc_NtkFindNet( pNtk, pWord ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // get the equal sign - if ( Ver_StreamPopChar(p) != '=' ) - { - sprintf( pMan->sError, "Cannot read the initial statement for %s (expected equality sign).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // skip the comments - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - // get the second name - pEquation = Ver_StreamGetWord( p, ";" ); - if ( pEquation == NULL ) - return 0; - // find the corresponding latch - pNode = Abc_ObjFanin0(pNet); - assert( Abc_ObjIsLatch(pNode) ); - // set the initial state - if ( pEquation[0] == '2' ) - Abc_LatchSetInitDc( pNode ); - else if ( pEquation[0] == '1') - Abc_LatchSetInit1( pNode ); - else if ( pEquation[0] == '0' ) - Abc_LatchSetInit0( pNode ); - else - { - sprintf( pMan->sError, "Incorrect initial value of the latch %s (expected equality sign).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // remove the last symbol - Symbol = Ver_StreamPopChar(p); - assert( Symbol == ';' ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtkGate ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Ntk_t * pNtk = pMan->pNtkCur; - Abc_Obj_t * pNetFormal, * pNetActual; - Abc_Obj_t * pObj, * pNode; - char * pWord, Symbol, * pGateName; - int i, fCompl, fComplUsed = 0; - unsigned * pPolarity; - - // clean the PI/PO pointers - Abc_NtkForEachPi( pNtkGate, pObj, i ) - pObj->pCopy = NULL; - Abc_NtkForEachPo( pNtkGate, pObj, i ) - pObj->pCopy = NULL; - // parse the directive and set the pointers to the PIs/POs of the gate - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // this is gate name - throw it away - pGateName = pWord; - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot parse gate %s (expected opening paranthesis).", pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // parse pairs of formal/actural inputs - while ( 1 ) - { - // process one pair of formal/actual parameters - if ( Ver_StreamPopChar(p) != '.' ) - { - sprintf( pMan->sError, "Cannot parse gate %s (expected .).", pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // parse the formal name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // get the formal net - if ( Abc_NtkIsNetlist(pNtkGate) ) - pNetFormal = Abc_NtkFindNet( pNtkGate, pWord ); - else // if ( Abc_NtkIsStrash(pNtkGate) ) - assert( 0 ); - if ( pNetFormal == NULL ) - { - sprintf( pMan->sError, "Formal net is missing in gate %s.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // open the paranthesis - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // parse the actual name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // check if the name is complemented - fCompl = (pWord[0] == '~'); - if ( fCompl ) - { - fComplUsed = 1; - pWord++; - if ( pMan->pNtkCur->pData == NULL ) - pMan->pNtkCur->pData = Extra_MmFlexStart(); - } - // get the actual net - pNetActual = Abc_NtkFindNet( pMan->pNtkCur, pWord ); - if ( pNetActual == NULL ) - { - sprintf( pMan->sError, "Actual net is missing in gate %s.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // close the paranthesis - if ( Ver_StreamPopChar(p) != ')' ) - { - sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // process the pair - if ( Abc_ObjIsPi(Abc_ObjFanin0Ntk(pNetFormal)) ) // PI net (with polarity!) - Abc_ObjFanin0Ntk(pNetFormal)->pCopy = Abc_ObjNotCond( pNetActual, fCompl ); - else if ( Abc_ObjIsPo(Abc_ObjFanout0Ntk(pNetFormal)) ) // P0 net - { - assert( fCompl == 0 ); - Abc_ObjFanout0Ntk(pNetFormal)->pCopy = pNetActual; // Abc_ObjNotCond( pNetActual, fCompl ); - } - else - { - sprintf( pMan->sError, "Cannot match formal net %s with PI or PO of the gate %s.", pWord, pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ')' ) - break; - // skip comma - if ( Symbol != ',' ) - { - sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - if ( Ver_StreamPopChar(p) != ';' ) - { - sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // make sure each input net is driven - Abc_NtkForEachPi( pNtkGate, pObj, i ) - if ( pObj->pCopy == NULL ) - { - sprintf( pMan->sError, "Formal input %s of gate %s has no actual input.", Abc_ObjFanout0(pObj)->pData, pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } -/* - // make sure each output net is driving something - Abc_NtkForEachPo( pNtkGate, pObj, i ) - if ( pObj->pCopy == NULL ) - { - sprintf( pMan->sError, "Formal output %s of gate %s has no actual output.", Abc_ObjFanin0(pObj)->pData, pNtkGate->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } -*/ - - // allocate memory to remember the phase - pPolarity = NULL; - if ( fComplUsed ) - { - int nBytes = 4 * Abc_BitWordNum( Abc_NtkPiNum(pNtkGate) ); - pPolarity = (unsigned *)Extra_MmFlexEntryFetch( pMan->pNtkCur->pData, nBytes ); - memset( pPolarity, 0, nBytes ); - } - // create box to represent this gate - pNode = Abc_NtkCreateBlackbox( pMan->pNtkCur ); -/* - if ( pNode->Id == 57548 ) - { - int x = 0; - } -*/ - pNode->pNext = (Abc_Obj_t *)pPolarity; - pNode->pData = pNtkGate; - // connect to fanin nets - Abc_NtkForEachPi( pNtkGate, pObj, i ) - { - if ( pPolarity && Abc_ObjIsComplement(pObj->pCopy) ) - { - Abc_InfoSetBit( pPolarity, i ); - pObj->pCopy = Abc_ObjRegular( pObj->pCopy ); - } - assert( !Abc_ObjIsComplement(pObj->pCopy) ); - Abc_ObjAddFanin( pNode, pObj->pCopy ); - } - // connect to fanout nets - Abc_NtkForEachPo( pNtkGate, pObj, i ) - { - if ( pObj->pCopy ) - Abc_ObjAddFanin( pObj->pCopy, pNode ); - else - Abc_ObjAddFanin( Abc_NtkFindOrCreateNet(pNtk, NULL), pNode ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseGateStandard( Ver_Man_t * pMan, Ver_GateType_t GateType ) -{ - Ver_Stream_t * p = pMan->pReader; - Aig_Man_t * pAig = pMan->pNtkCur->pManFunc; - Abc_Obj_t * pNet, * pNode; - char * pWord, Symbol; - // this is gate name - throw it away - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - // create the node - pNode = Abc_NtkCreateNode( pMan->pNtkCur ); - // parse pairs of formal/actural inputs - while ( 1 ) - { - // parse the output name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // get the net corresponding to this output - pNet = Abc_NtkFindNet( pMan->pNtkCur, pWord ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // if this is the first net, add it as an output - if ( Abc_ObjFanoutNum(pNode) == 0 ) - Abc_ObjAddFanin( pNet, pNode ); - else - Abc_ObjAddFanin( pNode, pNet ); - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ')' ) - break; - // skip comma - if ( Symbol != ',' ) - { - sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing paranthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - } - if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 ) - { - sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - if ( Ver_StreamPopChar(p) != ';' ) - { - sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // add logic function - if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND ) - pNode->pData = Aig_CreateAnd( pAig, Abc_ObjFaninNum(pNode) ); - else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR ) - pNode->pData = Aig_CreateOr( pAig, Abc_ObjFaninNum(pNode) ); - else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR ) - pNode->pData = Aig_CreateExor( pAig, Abc_ObjFaninNum(pNode) ); - else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT ) - pNode->pData = Aig_CreateAnd( pAig, Abc_ObjFaninNum(pNode) ); - if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT ) - pNode->pData = Aig_Not( pNode->pData ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Creates PI terminal and net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet, * pTerm; - // get the PI net - pNet = Abc_NtkFindNet( pNtk, pName ); - if ( pNet ) - printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); - pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); - // add the PI node - pTerm = Abc_NtkCreatePi( pNtk ); - Abc_ObjAddFanin( pNet, pTerm ); - return pTerm; -} - -/**Function************************************************************* - - Synopsis [Creates PO terminal and net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet, * pTerm; - // get the PO net - pNet = Abc_NtkFindNet( pNtk, pName ); - if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) - printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); - pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); - // add the PO node - pTerm = Abc_NtkCreatePo( pNtk ); - Abc_ObjAddFanin( pTerm, pNet ); - return pTerm; -} - -/**Function************************************************************* - - Synopsis [Create a latch with the given input/output.] - - Description [By default, the latch value is unknown (ABC_INIT_NONE).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) -{ - Abc_Obj_t * pLatch, * pNet; - // create a new latch and add it to the network - pLatch = Abc_NtkCreateLatch( pNtk ); - // get the LI net - pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI ); - Abc_ObjAddFanin( pLatch, pNet ); - // get the LO net - pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); - Abc_ObjAddFanin( pNet, pLatch ); - return pLatch; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ver/verFormula.c b/src/temp/ver/verFormula.c deleted file mode 100644 index fd8777c3..00000000 --- a/src/temp/ver/verFormula.c +++ /dev/null @@ -1,469 +0,0 @@ -/**CFile**************************************************************** - - FileName [verFormula.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Formula parser to read Verilog assign statements.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verFormula.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the list of operation symbols to be used in expressions -#define VER_PARSE_SYM_OPEN '(' // opening paranthesis -#define VER_PARSE_SYM_CLOSE ')' // closing paranthesis -#define VER_PARSE_SYM_CONST0 '0' // constant 0 -#define VER_PARSE_SYM_CONST1 '1' // constant 1 -#define VER_PARSE_SYM_NEGBEF1 '!' // negation before the variable -#define VER_PARSE_SYM_NEGBEF2 '~' // negation before the variable -#define VER_PARSE_SYM_AND '&' // logic AND -#define VER_PARSE_SYM_OR '|' // logic OR -#define VER_PARSE_SYM_XOR '^' // logic XOR -#define VER_PARSE_SYM_MUX1 '?' // first symbol of MUX -#define VER_PARSE_SYM_MUX2 ':' // second symbol of MUX - -// the list of opcodes (also specifying operation precedence) -#define VER_PARSE_OPER_NEG 7 // negation (highest precedence) -#define VER_PARSE_OPER_AND 6 // logic AND -#define VER_PARSE_OPER_XOR 5 // logic EXOR (a'b | ab') -#define VER_PARSE_OPER_OR 4 // logic OR -#define VER_PARSE_OPER_EQU 3 // equvalence (a'b'| ab ) -#define VER_PARSE_OPER_MUX 2 // MUX(a,b,c) (ab | a'c ) -#define VER_PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis - -// these are values of the internal Flag -#define VER_PARSE_FLAG_START 1 // after the opening parenthesis -#define VER_PARSE_FLAG_VAR 2 // after operation is received -#define VER_PARSE_FLAG_OPER 3 // after operation symbol is received -#define VER_PARSE_FLAG_ERROR 4 // when error is detected - -static Aig_Obj_t * Ver_FormulaParserTopOper( Aig_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ); -static int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Parser of the formula encountered in assign statements.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ) -{ - Aig_Obj_t * bFunc, * bTemp; - char * pTemp; - int nParans, Flag; - int Oper, Oper1, Oper2; - int v; - - // clear the stacks and the names - Vec_PtrClear( vNames ); - Vec_PtrClear( vStackFn ); - Vec_IntClear( vStackOp ); - - // make sure that the number of opening and closing parantheses is the same - nParans = 0; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - if ( *pTemp == '(' ) - nParans++; - else if ( *pTemp == ')' ) - nParans--; - if ( nParans != 0 ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." ); - return NULL; - } - - // add parantheses - pTemp = pFormula + strlen(pFormula) + 2; - *pTemp-- = 0; *pTemp = ')'; - while ( --pTemp != pFormula ) - *pTemp = *(pTemp - 1); - *pTemp = '('; - - // perform parsing - Flag = VER_PARSE_FLAG_START; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - { - switch ( *pTemp ) - { - // skip all spaces, tabs, and end-of-lines - case ' ': - case '\t': - case '\r': - case '\n': - continue; - - // treat Constant 0 as a variable - case VER_PARSE_SYM_CONST0: - Vec_PtrPush( vStackFn, Aig_ManConst0(pMan) ); // Cudd_Ref( Aig_ManConst0(pMan) ); - if ( Flag == VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Flag = VER_PARSE_FLAG_VAR; - break; - - // the same for Constant 1 - case VER_PARSE_SYM_CONST1: - Vec_PtrPush( vStackFn, Aig_ManConst1(pMan) ); // Cudd_Ref( Aig_ManConst1(pMan) ); - if ( Flag == VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Flag = VER_PARSE_FLAG_VAR; - break; - - case VER_PARSE_SYM_NEGBEF1: - case VER_PARSE_SYM_NEGBEF2: - if ( Flag == VER_PARSE_FLAG_VAR ) - {// if NEGBEF follows a variable, AND is assumed - sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG ); - break; - - case VER_PARSE_SYM_AND: - case VER_PARSE_SYM_OR: - case VER_PARSE_SYM_XOR: - case VER_PARSE_SYM_MUX1: - case VER_PARSE_SYM_MUX2: - if ( Flag != VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - if ( *pTemp == VER_PARSE_SYM_AND ) - Vec_IntPush( vStackOp, VER_PARSE_OPER_AND ); - else if ( *pTemp == VER_PARSE_SYM_OR ) - Vec_IntPush( vStackOp, VER_PARSE_OPER_OR ); - else if ( *pTemp == VER_PARSE_SYM_XOR ) - Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR ); - else if ( *pTemp == VER_PARSE_SYM_MUX1 ) - Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); -// else if ( *pTemp == VER_PARSE_SYM_MUX2 ) -// Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); - Flag = VER_PARSE_FLAG_OPER; - break; - - case VER_PARSE_SYM_OPEN: - if ( Flag == VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK ); - // after an opening bracket, it feels like starting over again - Flag = VER_PARSE_FLAG_START; - break; - - case VER_PARSE_SYM_CLOSE: - if ( Vec_IntSize( vStackOp ) ) - { - while ( 1 ) - { - if ( !Vec_IntSize( vStackOp ) ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Oper = Vec_IntPop( vStackOp ); - if ( Oper == VER_PARSE_OPER_MARK ) - break; - // skip the second MUX operation -// if ( Oper == VER_PARSE_OPER_MUX2 ) -// { -// Oper = Vec_IntPop( vStackOp ); -// assert( Oper == VER_PARSE_OPER_MUX1 ); -// } - - // perform the given operation - if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper ) == NULL ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); - return NULL; - } - } - } - else - { - sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - if ( Flag != VER_PARSE_FLAG_ERROR ) - Flag = VER_PARSE_FLAG_VAR; - break; - - - default: - // scan the next name - v = Ver_FormulaParserFindVar( pTemp, vNames ); - if ( *pTemp == '\\' ) - pTemp++; - pTemp += (int)Vec_PtrEntry( vNames, 2*v ) - 1; - - // assume operation AND, if vars follow one another - if ( Flag == VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." ); - return NULL; - } - bTemp = Aig_IthVar( pMan, v ); - Vec_PtrPush( vStackFn, bTemp ); // Cudd_Ref( bTemp ); - Flag = VER_PARSE_FLAG_VAR; - break; - } - - if ( Flag == VER_PARSE_FLAG_ERROR ) - break; // error exit - else if ( Flag == VER_PARSE_FLAG_START ) - continue; // go on parsing - else if ( Flag == VER_PARSE_FLAG_VAR ) - while ( 1 ) - { // check if there are negations in the OpStack - if ( !Vec_IntSize(vStackOp) ) - break; - Oper = Vec_IntPop( vStackOp ); - if ( Oper != VER_PARSE_OPER_NEG ) - { - Vec_IntPush( vStackOp, Oper ); - break; - } - else - { -// Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) ); - Vec_PtrPush( vStackFn, Aig_Not(Vec_PtrPop(vStackFn)) ); - } - } - else // if ( Flag == VER_PARSE_FLAG_OPER ) - while ( 1 ) - { // execute all the operations in the OpStack - // with precedence higher or equal than the last one - Oper1 = Vec_IntPop( vStackOp ); // the last operation - if ( !Vec_IntSize(vStackOp) ) - { // if it is the only operation, push it back - Vec_IntPush( vStackOp, Oper1 ); - break; - } - Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one - if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) ) - { // if Oper2 precedence is higher or equal, execute it - if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper2 ) == NULL ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); - return NULL; - } - Vec_IntPush( vStackOp, Oper1 ); // push the last operation back - } - else - { // if Oper2 precedence is lower, push them back and done - Vec_IntPush( vStackOp, Oper2 ); - Vec_IntPush( vStackOp, Oper1 ); - break; - } - } - } - - if ( Flag != VER_PARSE_FLAG_ERROR ) - { - if ( Vec_PtrSize(vStackFn) ) - { - bFunc = Vec_PtrPop(vStackFn); - if ( !Vec_PtrSize(vStackFn) ) - if ( !Vec_IntSize(vStackOp) ) - { -// Cudd_Deref( bFunc ); - return bFunc; - } - else - sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" ); - else - sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" ); - } - else - sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" ); - } -// Cudd_Ref( bFunc ); -// Cudd_RecursiveDeref( dd, bFunc ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs the operation on the top entries in the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Ver_FormulaParserTopOper( Aig_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ) -{ - Aig_Obj_t * bArg0, * bArg1, * bArg2, * bFunc; - // perform the given operation - bArg2 = Vec_PtrPop( vStackFn ); - bArg1 = Vec_PtrPop( vStackFn ); - if ( Oper == VER_PARSE_OPER_AND ) - bFunc = Aig_And( pMan, bArg1, bArg2 ); - else if ( Oper == VER_PARSE_OPER_XOR ) - bFunc = Aig_Exor( pMan, bArg1, bArg2 ); - else if ( Oper == VER_PARSE_OPER_OR ) - bFunc = Aig_Or( pMan, bArg1, bArg2 ); - else if ( Oper == VER_PARSE_OPER_EQU ) - bFunc = Aig_Not( Aig_Exor( pMan, bArg1, bArg2 ) ); - else if ( Oper == VER_PARSE_OPER_MUX ) - { - bArg0 = Vec_PtrPop( vStackFn ); -// bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 ); Cudd_Ref( bFunc ); - bFunc = Aig_Mux( pMan, bArg0, bArg1, bArg2 ); -// Cudd_RecursiveDeref( dd, bArg0 ); -// Cudd_Deref( bFunc ); - } - else - return NULL; -// Cudd_Ref( bFunc ); -// Cudd_RecursiveDeref( dd, bArg1 ); -// Cudd_RecursiveDeref( dd, bArg2 ); - Vec_PtrPush( vStackFn, bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Returns the index of the new variable found.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ) -{ - char * pTemp, * pTemp2; - int nLength, nLength2, i; - // start the string - pTemp = pString; - // find the end of the string delimited by other characters - if ( *pTemp == '\\' ) - { - pString++; - while ( *pTemp && *pTemp != ' ' ) - pTemp++; - } - else - { - while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' && *pTemp != '\r' && *pTemp != '\n' && *pTemp != ',' && *pTemp != '}' && - *pTemp != VER_PARSE_SYM_OPEN && *pTemp != VER_PARSE_SYM_CLOSE && - *pTemp != VER_PARSE_SYM_NEGBEF1 && *pTemp != VER_PARSE_SYM_NEGBEF2 && - *pTemp != VER_PARSE_SYM_AND && *pTemp != VER_PARSE_SYM_OR && *pTemp != VER_PARSE_SYM_XOR && - *pTemp != VER_PARSE_SYM_MUX1 && *pTemp != VER_PARSE_SYM_MUX2 ) - pTemp++; - } - // look for this string in the array - nLength = pTemp - pString; - for ( i = 0; i < Vec_PtrSize(vNames)/2; i++ ) - { - nLength2 = (int)Vec_PtrEntry( vNames, 2*i + 0 ); - if ( nLength2 != nLength ) - continue; - pTemp2 = Vec_PtrEntry( vNames, 2*i + 1 ); - if ( strncmp( pString, pTemp2, nLength ) ) - continue; - return i; - } - // could not find - add and return the number - Vec_PtrPush( vNames, (void *)nLength ); - Vec_PtrPush( vNames, pString ); - return i; -} - -/**Function************************************************************* - - Synopsis [Returns the AIG representation of the reduction formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ) -{ - Aig_Obj_t * pRes; - int v, fCompl; - char Symbol; - - // get the operation - Symbol = *pFormula++; - fCompl = ( Symbol == '~' ); - if ( fCompl ) - Symbol = *pFormula++; - // check the operation - if ( Symbol != '&' && Symbol != '|' && Symbol != '^' ) - { - sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol ); - return NULL; - } - // skip the brace - while ( *pFormula++ != '{' ); - // parse the names - Vec_PtrClear( vNames ); - while ( *pFormula != '}' ) - { - v = Ver_FormulaParserFindVar( pFormula, vNames ); - pFormula += (int)Vec_PtrEntry( vNames, 2*v ); - while ( *pFormula == ' ' || *pFormula == ',' ) - pFormula++; - } - // compute the function - if ( Symbol == '&' ) - pRes = Aig_CreateAnd( pMan, Vec_PtrSize(vNames)/2 ); - else if ( Symbol == '|' ) - pRes = Aig_CreateOr( pMan, Vec_PtrSize(vNames)/2 ); - else if ( Symbol == '^' ) - pRes = Aig_CreateExor( pMan, Vec_PtrSize(vNames)/2 ); - return Aig_NotCond( pRes, fCompl ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ver/verParse.c b/src/temp/ver/verParse.c deleted file mode 100644 index 8a78e75b..00000000 --- a/src/temp/ver/verParse.c +++ /dev/null @@ -1,115 +0,0 @@ -/**CFile**************************************************************** - - FileName [verParse.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Performs some Verilog parsing tasks.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verParse.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Skips the comments of they are present.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseSkipComments( Ver_Man_t * pMan ) -{ - Ver_Stream_t * p = pMan->pReader; - char Symbol; - // skip spaces - Ver_StreamSkipChars( p, " \t\n\r" ); - if ( !Ver_StreamIsOkey(pMan->pReader) ) - return 1; - // read the first symbol - Symbol = Ver_StreamScanChar( p ); - if ( Symbol != '/' ) - return 1; - Ver_StreamPopChar( p ); - // read the second symbol - Symbol = Ver_StreamScanChar( p ); - if ( Symbol == '/' ) - { // skip till the end of line - Ver_StreamSkipToChars( p, "\n" ); - return Ver_ParseSkipComments( pMan ); - } - if ( Symbol == '*' ) - { // skip till the next occurance of */ - Ver_StreamPopChar( p ); - do { - Ver_StreamSkipToChars( p, "*" ); - Ver_StreamPopChar( p ); - } while ( Ver_StreamScanChar( p ) != '/' ); - Ver_StreamPopChar( p ); - return Ver_ParseSkipComments( pMan ); - } - sprintf( pMan->sError, "Cannot parse after symbol \"/\"." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Parses a Verilog name that can be being with a slash.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ver_ParseGetName( Ver_Man_t * pMan ) -{ - Ver_Stream_t * p = pMan->pReader; - char Symbol; - char * pWord; - if ( !Ver_StreamIsOkey(p) ) - return NULL; - if ( !Ver_ParseSkipComments( pMan ) ) - return NULL; - Symbol = Ver_StreamScanChar( p ); - if ( Symbol == '\\' ) - { - Ver_StreamPopChar( p ); - pWord = Ver_StreamGetWord( p, " " ); - } - else - pWord = Ver_StreamGetWord( p, " \t\n\r(),;" ); - if ( !Ver_ParseSkipComments( pMan ) ) - return NULL; - return pWord; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ver/verStream.c b/src/temp/ver/verStream.c deleted file mode 100644 index 7956b13c..00000000 --- a/src/temp/ver/verStream.c +++ /dev/null @@ -1,435 +0,0 @@ -/**CFile**************************************************************** - - FileName [verStream.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Input file stream, which knows nothing about Verilog.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define VER_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory -#define VER_OFFSET_SIZE 4096 // 4K - load new data when less than this is left -#define VER_WORD_SIZE 4096 // 4K - the largest token that can be returned - -#define VER_MINIMUM(a,b) (((a) < (b))? (a) : (b)) - -struct Ver_Stream_t_ -{ - // the input file - char * pFileName; // the input file name - FILE * pFile; // the input file pointer - int nFileSize; // the total number of bytes in the file - int nFileRead; // the number of bytes currently read from file - int nLineCounter; // the counter of lines processed - // temporary storage for data - char * pBuffer; // the buffer - int nBufferSize; // the size of the buffer - char * pBufferCur; // the current reading position - char * pBufferEnd; // the first position not used by currently loaded data - char * pBufferStop; // the position where loading new data will be done - // tokens given to the user - char pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parantheses) - int nChars; // the total number of characters in the word - // status of the parser - int fStop; // this flag goes high when the end of file is reached -}; - -static void Ver_StreamReload( Ver_Stream_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the file reader for the given file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ver_Stream_t * Ver_StreamAlloc( char * pFileName ) -{ - Ver_Stream_t * p; - FILE * pFile; - int nCharsToRead; - // check if the file can be opened - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName ); - return NULL; - } - // start the file reader - p = ALLOC( Ver_Stream_t, 1 ); - memset( p, 0, sizeof(Ver_Stream_t) ); - p->pFileName = pFileName; - p->pFile = pFile; - // get the file size, in bytes - fseek( pFile, 0, SEEK_END ); - p->nFileSize = ftell( pFile ); - rewind( pFile ); - // allocate the buffer - p->pBuffer = ALLOC( char, VER_BUFFER_SIZE+1 ); - p->nBufferSize = VER_BUFFER_SIZE; - p->pBufferCur = p->pBuffer; - // determine how many chars to read - nCharsToRead = VER_MINIMUM(p->nFileSize, VER_BUFFER_SIZE); - // load the first part into the buffer - fread( p->pBuffer, nCharsToRead, 1, p->pFile ); - p->nFileRead = nCharsToRead; - // set the ponters to the end and the stopping point - p->pBufferEnd = p->pBuffer + nCharsToRead; - p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; - // start the arrays - p->nLineCounter = 1; // 1-based line counting - return p; -} - -/**Function************************************************************* - - Synopsis [Loads new data into the file reader.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_StreamReload( Ver_Stream_t * p ) -{ - int nCharsUsed, nCharsToRead; - assert( !p->fStop ); - assert( p->pBufferCur > p->pBufferStop ); - assert( p->pBufferCur < p->pBufferEnd ); - // figure out how many chars are still not processed - nCharsUsed = p->pBufferEnd - p->pBufferCur; - // move the remaining data to the beginning of the buffer - memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); - p->pBufferCur = p->pBuffer; - // determine how many chars we will read - nCharsToRead = VER_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); - // read the chars - fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); - p->nFileRead += nCharsToRead; - // set the ponters to the end and the stopping point - p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; - p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; -} - -/**Function************************************************************* - - Synopsis [Stops the file reader.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_StreamFree( Ver_Stream_t * p ) -{ - if ( p->pFile ) - fclose( p->pFile ); - FREE( p->pBuffer ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the file size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ver_StreamGetFileName( Ver_Stream_t * p ) -{ - return p->pFileName; -} - -/**Function************************************************************* - - Synopsis [Returns the file size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_StreamGetFileSize( Ver_Stream_t * p ) -{ - return p->nFileSize; -} - -/**Function************************************************************* - - Synopsis [Returns the current reading position.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_StreamGetCurPosition( Ver_Stream_t * p ) -{ - return p->nFileRead - (p->pBufferEnd - p->pBufferCur); -} - -/**Function************************************************************* - - Synopsis [Returns the line number for the given token.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_StreamGetLineNumber( Ver_Stream_t * p ) -{ - return p->nLineCounter; -} - - - -/**Function************************************************************* - - Synopsis [Returns current symbol.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_StreamIsOkey( Ver_Stream_t * p ) -{ - return !p->fStop; -} - -/**Function************************************************************* - - Synopsis [Returns current symbol.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char Ver_StreamScanChar( Ver_Stream_t * p ) -{ - assert( !p->fStop ); - return *p->pBufferCur; -} - -/**Function************************************************************* - - Synopsis [Returns current symbol and moves to the next.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char Ver_StreamPopChar( Ver_Stream_t * p ) -{ - assert( !p->fStop ); - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Ver_StreamReload( p ); - // check if there are symbols left - if ( p->pBufferCur == p->pBufferEnd ) // end of file - { - p->fStop = 1; - return -1; - } - return *p->pBufferCur++; -} - -/**Function************************************************************* - - Synopsis [Skips the current symbol and all symbols from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ) -{ - char * pChar, * pTemp; - assert( !p->fStop ); - assert( pCharsToSkip != NULL ); - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Ver_StreamReload( p ); - // skip the symbols - for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) - { - // count the lines - if ( *pChar == '\n' ) - p->nLineCounter++; - // skip symbols as long as they are in the list - for ( pTemp = pCharsToSkip; *pTemp; pTemp++ ) - if ( *pChar == *pTemp ) - break; - if ( *pTemp == 0 ) // pChar is not found in the list - { - p->pBufferCur = pChar; - return; - } - } - // the file is finished or the last part continued - // through VER_OFFSET_SIZE chars till the end of the buffer - if ( p->pBufferStop == p->pBufferEnd ) // end of file - { - p->fStop = 1; - return; - } - printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName ); -} - -/**Function************************************************************* - - Synopsis [Skips all symbols until encountering one from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ) -{ - char * pChar, * pTemp; - assert( !p->fStop ); - assert( pCharsToStop != NULL ); - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Ver_StreamReload( p ); - // skip the symbols - for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) - { - // count the lines - if ( *pChar == '\n' ) - p->nLineCounter++; - // skip symbols as long as they are NOT in the list - for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) - if ( *pChar == *pTemp ) - break; - if ( *pTemp == 0 ) // pChar is not found in the list - continue; - // the symbol is found - move position and return - p->pBufferCur = pChar; - return; - } - // the file is finished or the last part continued - // through VER_OFFSET_SIZE chars till the end of the buffer - if ( p->pBufferStop == p->pBufferEnd ) // end of file - { - p->fStop = 1; - return; - } - printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName ); -} - -/**Function************************************************************* - - Synopsis [Returns current word delimited by the set of symbols.] - - Description [Modifies the stream by inserting 0 at the first encounter - of one of the symbols in the list.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ) -{ - char * pChar, * pTemp; - if ( p->fStop ) - return NULL; - assert( pCharsToStop != NULL ); - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Ver_StreamReload( p ); - // skip the symbols - p->nChars = 0; - for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) - { - // count the lines - if ( *pChar == '\n' ) - p->nLineCounter++; - // skip symbols as long as they are NOT in the list - for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) - if ( *pChar == *pTemp ) - break; - if ( *pTemp == 0 ) // pChar is not found in the list - { - p->pChars[p->nChars++] = *pChar; - if ( p->nChars == VER_WORD_SIZE ) - return NULL; - continue; - } - // the symbol is found - move the position, set the word end, return the word - p->pBufferCur = pChar; - p->pChars[p->nChars] = 0; - return p->pChars; - } - // the file is finished or the last part continued - // through VER_OFFSET_SIZE chars till the end of the buffer - if ( p->pBufferStop == p->pBufferEnd ) // end of file - { - p->fStop = 1; - p->pChars[p->nChars] = 0; - return p->pChars; - } - printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName ); - return NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ver/verWords.c b/src/temp/ver/verWords.c deleted file mode 100644 index f9d27010..00000000 --- a/src/temp/ver/verWords.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [verWords.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Handles keywords that are currently supported.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verWords.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/temp/ver/ver_.c b/src/temp/ver/ver_.c deleted file mode 100644 index 76599dac..00000000 --- a/src/temp/ver/ver_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [ver_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Parses several flavors of structural Verilog.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: ver_.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -- cgit v1.2.3