summaryrefslogtreecommitdiffstats
path: root/src/base/abci
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2007-10-01 08:01:00 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2007-10-01 08:01:00 -0700
commit4812c90424dfc40d26725244723887a2d16ddfd9 (patch)
treeb32ace96e7e2d84d586e09ba605463b6f49c3271 /src/base/abci
parente54d9691616b9a0326e2fdb3156bb4eeb8abfcd7 (diff)
downloadabc-4812c90424dfc40d26725244723887a2d16ddfd9.tar.gz
abc-4812c90424dfc40d26725244723887a2d16ddfd9.tar.bz2
abc-4812c90424dfc40d26725244723887a2d16ddfd9.zip
Version abc71001
Diffstat (limited to 'src/base/abci')
-rw-r--r--src/base/abci/abc.c12921
-rw-r--r--src/base/abci/abcAttach.c404
-rw-r--r--src/base/abci/abcAuto.c239
-rw-r--r--src/base/abci/abcBalance.c613
-rw-r--r--src/base/abci/abcBmc.c115
-rw-r--r--src/base/abci/abcCas.c111
-rw-r--r--src/base/abci/abcClpBdd.c162
-rw-r--r--src/base/abci/abcClpSop.c53
-rw-r--r--src/base/abci/abcCut.c620
-rw-r--r--src/base/abci/abcDar.c1245
-rw-r--r--src/base/abci/abcDebug.c208
-rw-r--r--src/base/abci/abcDress.c209
-rw-r--r--src/base/abci/abcDsd.c551
-rw-r--r--src/base/abci/abcEspresso.c250
-rw-r--r--src/base/abci/abcExtract.c51
-rw-r--r--src/base/abci/abcFpga.c278
-rw-r--r--src/base/abci/abcFpgaFast.c190
-rw-r--r--src/base/abci/abcFraig.c803
-rw-r--r--src/base/abci/abcFxu.c260
-rw-r--r--src/base/abci/abcGen.c511
-rw-r--r--src/base/abci/abcHaig.c726
-rw-r--r--src/base/abci/abcIf.c497
-rw-r--r--src/base/abci/abcIvy.c1105
-rw-r--r--src/base/abci/abcLut.c786
-rw-r--r--src/base/abci/abcMap.c657
-rw-r--r--src/base/abci/abcMeasure.c478
-rw-r--r--src/base/abci/abcMini.c153
-rw-r--r--src/base/abci/abcMiter.c1146
-rw-r--r--src/base/abci/abcMulti.c643
-rw-r--r--src/base/abci/abcMv.c369
-rw-r--r--src/base/abci/abcNtbdd.c582
-rw-r--r--src/base/abci/abcOdc.c1134
-rw-r--r--src/base/abci/abcOrder.c131
-rw-r--r--src/base/abci/abcPart.c1205
-rw-r--r--src/base/abci/abcPlace.c255
-rw-r--r--src/base/abci/abcPrint.c953
-rw-r--r--src/base/abci/abcProve.c341
-rw-r--r--src/base/abci/abcQbf.c260
-rw-r--r--src/base/abci/abcQuant.c419
-rw-r--r--src/base/abci/abcRec.c1173
-rw-r--r--src/base/abci/abcReconv.c762
-rw-r--r--src/base/abci/abcRefactor.c379
-rw-r--r--src/base/abci/abcRenode.c311
-rw-r--r--src/base/abci/abcReorder.c100
-rw-r--r--src/base/abci/abcRestruct.c1496
-rw-r--r--src/base/abci/abcResub.c1951
-rw-r--r--src/base/abci/abcRewrite.c414
-rw-r--r--src/base/abci/abcRr.c999
-rw-r--r--src/base/abci/abcSat.c884
-rw-r--r--src/base/abci/abcStrash.c478
-rw-r--r--src/base/abci/abcSweep.c948
-rw-r--r--src/base/abci/abcSymm.c229
-rw-r--r--src/base/abci/abcTiming.c905
-rw-r--r--src/base/abci/abcUnate.c155
-rw-r--r--src/base/abci/abcUnreach.c349
-rw-r--r--src/base/abci/abcVerify.c1018
-rw-r--r--src/base/abci/abcXsim.c227
-rw-r--r--src/base/abci/abc_.c48
-rw-r--r--src/base/abci/abc_new.h23
-rw-r--r--src/base/abci/module.make54
60 files changed, 44537 insertions, 0 deletions
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
new file mode 100644
index 00000000..7d9b8be2
--- /dev/null
+++ b/src/base/abci/abc.c
@@ -0,0 +1,12921 @@
+/**CFile****************************************************************
+
+ FileName [abc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Command file.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "mainInt.h"
+#include "fraig.h"
+#include "fxu.h"
+#include "cut.h"
+#include "fpga.h"
+#include "if.h"
+#include "res.h"
+#include "lpk.h"
+#include "aig.h"
+#include "dar.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_CommandPrintStats ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintExdc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintIo ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintLatch ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintXCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintDsd ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMulti ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandLutpack ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandResubstitute ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDemiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandOrPos ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAndPos ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAppend ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandReorder ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandOrder ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcFree ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcGet ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv );
+//static int Abc_CommandXyz ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandQuaVar ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQuaRel ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQuaReach ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandIStrash ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDCompress2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIRewriteSeq ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIResyn ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandISat ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMini ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigStore ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandHaigStart ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandHaigStop ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandHaigUse ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandRecStart ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecStop ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecAdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIf ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandScut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandInit ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandZero ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUndc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPipe ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandUnseq ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqFpga ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCycle ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandXsim ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDSat ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_Init( Abc_Frame_t * pAbc )
+{
+// Abc_NtkBddImplicationTest();
+
+ Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "print_dsd", Abc_CommandPrintDsd, 0 );
+
+ Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 );
+ Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 );
+
+ Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "renode", Abc_CommandRenode, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "sweep", Abc_CommandSweep, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "fx", Abc_CommandFastExtract, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "dsd", Abc_CommandDisjoint, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "imfs", Abc_CommandImfs, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "lutpack", Abc_CommandLutpack, 1 );
+
+ Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 );
+// Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "resub", Abc_CommandResubstitute, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 );
+
+ Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "demiter", Abc_CommandDemiter, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "orpos", Abc_CommandOrPos, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "andpos", Abc_CommandAndPos, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "append", Abc_CommandAppend, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "aig", Abc_CommandAig, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "reorder", Abc_CommandReorder, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "order", Abc_CommandOrder, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "exdc_free", Abc_CommandExdcFree, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "exdc_get", Abc_CommandExdcGet, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "exdc_set", Abc_CommandExdcSet, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 );
+ Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 );
+// Cmd_CommandAdd( pAbc, "Various", "xyz", Abc_CommandXyz, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 );
+
+ Cmd_CommandAdd( pAbc, "Various", "qvar", Abc_CommandQuaVar, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "qrel", Abc_CommandQuaRel, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "qreach", Abc_CommandQuaReach, 1 );
+
+ Cmd_CommandAdd( pAbc, "New AIG", "istrash", Abc_CommandIStrash, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "icut", Abc_CommandICut, 0 );
+ Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "dcompress2", Abc_CommandDCompress2, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "irws", Abc_CommandIRewriteSeq, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "iresyn", Abc_CommandIResyn, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "isat", Abc_CommandISat, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "ifraig", Abc_CommandIFraig, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "dfraig", Abc_CommandDFraig, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "csweep", Abc_CommandCSweep, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "iprove", Abc_CommandIProve, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "haig", Abc_CommandHaig, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "mini", Abc_CommandMini, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "_bmc", Abc_CommandBmc, 0 );
+ Cmd_CommandAdd( pAbc, "New AIG", "qbf", Abc_CommandQbf, 0 );
+
+ Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "fraig_store", Abc_CommandFraigStore, 0 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "fraig_restore", Abc_CommandFraigRestore, 1 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 );
+
+ Cmd_CommandAdd( pAbc, "Choicing", "haig_start", Abc_CommandHaigStart, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "haig_stop", Abc_CommandHaigStop, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "haig_use", Abc_CommandHaigUse, 1 );
+
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_start", Abc_CommandRecStart, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_stop", Abc_CommandRecStop, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_add", Abc_CommandRecAdd, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_ps", Abc_CommandRecPs, 0 );
+ Cmd_CommandAdd( pAbc, "Choicing", "rec_use", Abc_CommandRecUse, 1 );
+
+ Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "sc", Abc_CommandSuperChoice, 1 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "scl", Abc_CommandSuperChoiceLut, 1 );
+
+ Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 );
+ Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 );
+ Cmd_CommandAdd( pAbc, "FPGA mapping", "if", Abc_CommandIf, 1 );
+
+// Cmd_CommandAdd( pAbc, "Sequential", "scut", Abc_CommandScut, 0 );
+ Cmd_CommandAdd( pAbc, "Sequential", "init", Abc_CommandInit, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "zero", Abc_CommandZero, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "undc", Abc_CommandUndc, 1 );
+// Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 );
+// Cmd_CommandAdd( pAbc, "Sequential", "sfpga", Abc_CommandSeqFpga, 1 );
+// Cmd_CommandAdd( pAbc, "Sequential", "smap", Abc_CommandSeqMap, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "cycle", Abc_CommandCycle, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "xsim", Abc_CommandXsim, 0 );
+
+ Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 );
+ Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 );
+
+// Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 );
+// Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 );
+
+// Rwt_Man4ExploreStart();
+// Map_Var3Print();
+// Map_Var4Test();
+
+// Abc_NtkPrint256();
+// Kit_TruthCountMintermsPrecomp();
+// Kit_DsdPrecompute4Vars();
+
+ {
+ extern void Dar_LibStart();
+ Dar_LibStart();
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_End()
+{
+// Dar_LibDumpPriorities();
+
+ {
+ extern void Cnf_ClearMemory();
+ Cnf_ClearMemory();
+ }
+ {
+ extern void Dar_LibStop();
+ Dar_LibStop();
+ }
+
+ Abc_NtkFraigStoreClean();
+// Rwt_Man4ExplorePrint();
+
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ bool fShort;
+ int c;
+ int fFactor;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fShort = 1;
+ fFactor = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sfh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 's':
+ fShort ^= 1;
+ break;
+ case 'f':
+ fFactor ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" );
+ return 1;
+ }
+ Abc_NtkPrintStats( pOut, pNtk, fFactor );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_stats [-fh]\n" );
+ fprintf( pErr, "\t prints the network statistics\n" );
+ fprintf( pErr, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ double Percentage;
+ bool fShort;
+ int c;
+ int fPrintDc;
+
+ extern double Abc_NtkSpacePercentage( Abc_Obj_t * pNode );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fShort = 1;
+ fPrintDc = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 's':
+ fShort ^= 1;
+ break;
+ case 'd':
+ fPrintDc ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" );
+ return 1;
+ }
+ if ( pNtk->pExdc == NULL )
+ {
+ fprintf( Abc_FrameReadErr(pAbc), "Network has no EXDC.\n" );
+ return 1;
+ }
+
+ if ( fPrintDc )
+ {
+ if ( !Abc_NtkIsStrash(pNtk->pExdc) )
+ {
+ pNtkTemp = Abc_NtkStrash(pNtk->pExdc, 0, 0, 0);
+ Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtkTemp, 0) ) );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ else
+ Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtk->pExdc, 0) ) );
+
+ printf( "EXDC network statistics: " );
+ printf( "(" );
+ if ( Percentage > 0.05 && Percentage < 99.95 )
+ printf( "%.2f", Percentage );
+ else if ( Percentage > 0.000005 && Percentage < 99.999995 )
+ printf( "%.6f", Percentage );
+ else
+ printf( "%f", Percentage );
+ printf( " %% don't-cares)\n" );
+ }
+ else
+ printf( "EXDC network statistics: \n" );
+ Abc_NtkPrintStats( pOut, pNtk->pExdc, 0 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_exdc [-dh]\n" );
+ fprintf( pErr, "\t prints the EXDC network statistics\n" );
+ fprintf( pErr, "\t-d : toggles printing don't-care percentage [default = %s]\n", fPrintDc? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( argc > globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+
+ if ( argc == globalUtilOptind + 1 )
+ {
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ Abc_NodePrintFanio( pOut, pNode );
+ return 0;
+ }
+ // print the nodes
+ Abc_NtkPrintIo( pOut, pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_io [-h] <node>\n" );
+ fprintf( pErr, "\t prints the PIs/POs or fanins/fanouts of a node\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tnode : the node to print fanins/fanouts\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ // print the nodes
+ Abc_NtkPrintLatch( pOut, pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_latch [-h]\n" );
+ fprintf( pErr, "\t prints information about latches\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // print the nodes
+ Abc_NtkPrintFanio( pOut, pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_fanio [-h]\n" );
+ fprintf( pErr, "\t prints the statistics about fanins/fanouts of all nodes\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ extern void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // print the nodes
+ Abc_NtkPrintMffc( pOut, pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_mffc [-h]\n" );
+ fprintf( pErr, "\t prints the MFFC of each node in the network\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ int c;
+ int fUseRealNames;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseRealNames = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'n':
+ fUseRealNames ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsSopLogic(pNtk) )
+ {
+ fprintf( pErr, "Printing factored forms can be done for SOP networks.\n" );
+ return 1;
+ }
+
+ if ( argc > globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+
+ if ( argc == globalUtilOptind + 1 )
+ {
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ Abc_NodePrintFactor( pOut, pNode, fUseRealNames );
+ return 0;
+ }
+ // print the nodes
+ Abc_NtkPrintFactor( pOut, pNtk, fUseRealNames );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_factor [-nh] <node>\n" );
+ fprintf( pErr, "\t prints the factored forms of nodes\n" );
+ fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tnode : (optional) one node to consider\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ int c;
+ int fListNodes;
+ int fProfile;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fListNodes = 0;
+ fProfile = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'n':
+ fListNodes ^= 1;
+ break;
+ case 'p':
+ fProfile ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !fProfile && !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" );
+ return 1;
+ }
+
+ if ( argc > globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+
+ if ( argc == globalUtilOptind + 1 )
+ {
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ Abc_NodePrintLevel( pOut, pNode );
+ return 0;
+ }
+ // process all COs
+ Abc_NtkPrintLevel( pOut, pNtk, fProfile, fListNodes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_level [-nph] <node>\n" );
+ fprintf( pErr, "\t prints information about node level and cone size\n" );
+ fprintf( pErr, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" );
+ fprintf( pErr, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tnode : (optional) one node to consider\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Vec_Ptr_t * vSuppFun;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fStruct;
+ int fVerbose;
+ extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose );
+ extern void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fStruct = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 's':
+ fStruct ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // print support information
+ if ( fStruct )
+ {
+ Abc_NtkPrintStrSupports( pNtk );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" );
+ return 1;
+ }
+ vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose );
+ free( vSuppFun->pArray[0] );
+ Vec_PtrFree( vSuppFun );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_supp [-svh]\n" );
+ fprintf( pErr, "\t prints the supports of the CO nodes\n" );
+ fprintf( pErr, "\t-s : toggle printing structural support only [default = %s].\n", fStruct? "yes": "no" );
+ fprintf( pErr, "\t-v : enable 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_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseBdds;
+ int fNaive;
+ int fReorder;
+ int fVerbose;
+ extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseBdds = 0;
+ fNaive = 0;
+ fReorder = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fUseBdds ^= 1;
+ break;
+ case 'n':
+ fNaive ^= 1;
+ break;
+ case 'r':
+ fReorder ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_symm [-bnrvh]\n" );
+ fprintf( pErr, "\t computes symmetries of the PO functions\n" );
+ fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" );
+ fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" );
+ fprintf( pErr, "\t-r : enable dynamic BDD variable reordering [default = %s].\n", fReorder? "yes": "no" );
+ fprintf( pErr, "\t-v : enable 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_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseBdds;
+ int fUseNaive;
+ int fVerbose;
+ extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseBdds = 1;
+ fUseNaive = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fUseBdds ^= 1;
+ break;
+ case 'n':
+ fUseNaive ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" );
+ return 1;
+ }
+ Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_unate [-bnvh]\n" );
+ fprintf( pErr, "\t computes unate variables of the PO functions\n" );
+ fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" );
+ fprintf( pErr, "\t-n : toggle naive BDD-based computation [default = %s].\n", fUseNaive? "yes": "no" );
+ fprintf( pErr, "\t-v : enable 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_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int Output;
+ int fNaive;
+ int fVerbose;
+ extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Output = -1;
+ fNaive = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'O':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ Output = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Output < 0 )
+ goto usage;
+ break;
+ case 'n':
+ fNaive ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" );
+ return 1;
+ }
+
+
+ Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_auto [-O num] [-nvh]\n" );
+ fprintf( pErr, "\t computes autosymmetries of the PO functions\n" );
+ fprintf( pErr, "\t-O num : (optional) the 0-based number of the output [default = all]\n");
+ fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" );
+ fprintf( pErr, "\t-v : enable 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_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ int c;
+ int fUseRealNames;
+
+ extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseRealNames = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'n':
+ fUseRealNames ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Visualization of Karnaugh maps works for logic networks.\n" );
+ return 1;
+ }
+ if ( argc > globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+ if ( argc == globalUtilOptind )
+ {
+ pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+ if ( !Abc_ObjIsNode(pNode) )
+ {
+ fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) );
+ return 1;
+ }
+ }
+ else
+ {
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ }
+ Abc_NtkToBdd(pNtk);
+ Abc_NodePrintKMap( pNode, fUseRealNames );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_kmap [-nh] <node>\n" );
+ fprintf( pErr, " shows the truth table of the node\n" );
+ fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tnode : the node to consider (default = the driver of the first PO)\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseLibrary;
+
+ extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseLibrary = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUseLibrary ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkHasAig(pNtk) )
+ {
+ fprintf( pErr, "Printing gates does not work for AIGs and sequential AIGs.\n" );
+ return 1;
+ }
+
+ Abc_NtkPrintGates( pNtk, fUseLibrary );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_gates [-lh]\n" );
+ fprintf( pErr, "\t prints statistics about gates used in the network\n" );
+ fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseLibrary;
+
+ extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseLibrary = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUseLibrary ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ Abc_NtkPrintSharing( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_sharing [-h]\n" );
+ fprintf( pErr, "\t prints the number of shared nodes in the TFI cones of the COs\n" );
+// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseLibrary;
+
+ extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseLibrary = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUseLibrary ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ Abc_NtkCrossCut( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_xcut [-h]\n" );
+ fprintf( pErr, "\t prints the size of the cross cut of the current network\n" );
+// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fCofactor;
+ int nCofLevel;
+
+ extern void Kit_DsdTest( unsigned * pTruth, int nVars );
+ extern void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCofLevel = 1;
+ fCofactor = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCofLevel = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCofLevel < 0 )
+ goto usage;
+ break;
+ case 'c':
+ fCofactor ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ // get the truth table of the first output
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Currently works only for logic networks.\n" );
+ return 1;
+ }
+ Abc_NtkToAig( pNtk );
+ // convert it to truth table
+ {
+ Abc_Obj_t * pObj = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+ Vec_Int_t * vMemory = Vec_IntAlloc(0);
+ unsigned * pTruth;
+ if ( !Abc_ObjIsNode(pObj) )
+ {
+ fprintf( pErr, "The fanin of the first PO node does not have a logic function.\n" );
+ return 1;
+ }
+ if ( Abc_ObjFaninNum(pObj) > 16 )
+ {
+ fprintf( pErr, "Currently works only for up to 16 inputs.\n" );
+ return 1;
+ }
+ pTruth = Abc_ConvertAigToTruth( pNtk->pManFunc, Hop_Regular(pObj->pData), Abc_ObjFaninNum(pObj), vMemory, 0 );
+ if ( Hop_IsComplement(pObj->pData) )
+ Extra_TruthNot( pTruth, pTruth, Abc_ObjFaninNum(pObj) );
+ Extra_PrintBinary( stdout, pTruth, 1 << Abc_ObjFaninNum(pObj) );
+ printf( "\n" );
+ if ( fCofactor )
+ Kit_DsdPrintCofactors( pTruth, Abc_ObjFaninNum(pObj), nCofLevel, 1 );
+ else
+ Kit_DsdTest( pTruth, Abc_ObjFaninNum(pObj) );
+ Vec_IntFree( vMemory );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: print_dsd [-ch] [-N num]\n" );
+ fprintf( pErr, "\t print DSD formula for a single-output function with less than 16 variables\n" );
+ fprintf( pErr, "\t-c : toggle recursive cofactoring [default = %s]\n", fCofactor? "yes": "no" );
+ fprintf( pErr, "\t-N num : the number of levels to cofactor [default = %d]\n", nCofLevel );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ 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
+ fSeq = 0;
+ fGateNames = 0;
+ fUseReverse = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "rsgh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'r':
+ fUseReverse ^= 1;
+ break;
+ case 's':
+ fSeq ^= 1;
+ break;
+ case 'g':
+ fGateNames ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse );
+ return 0;
+
+usage:
+ 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;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ int c;
+ extern void Abc_NodeShowBdd( Abc_Obj_t * pNode );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsBddLogic(pNtk) )
+ {
+ fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" );
+ return 1;
+ }
+
+ if ( argc > globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+ if ( argc == globalUtilOptind )
+ {
+ pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
+ if ( !Abc_ObjIsNode(pNode) )
+ {
+ fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) );
+ return 1;
+ }
+ }
+ else
+ {
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ }
+ Abc_NodeShowBdd( pNode );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: show_bdd [-h] <node>\n" );
+ fprintf( pErr, " visualizes the BDD of a node 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, "\tnode : the node to consider [default = the driver of the first PO]\n");
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ int c;
+ int nNodeSizeMax;
+ int nConeSizeMax;
+ extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nNodeSizeMax = 10;
+ nConeSizeMax = ABC_INFINITY;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nNodeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nNodeSizeMax < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConeSizeMax < 0 )
+ goto usage;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" );
+ return 1;
+ }
+ if ( argc != globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: show_cut [-N num] [-C num] [-h] <node>\n" );
+ fprintf( pErr, " visualizes the cut of a node 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-N num : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax );
+ fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax );
+ fprintf( pErr, "\tnode : the node to consider\n");
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fVerbose;
+ int fBddSizeMax;
+ int fDualRail;
+ int fReorder;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 1;
+ fReorder = 1;
+ fDualRail = 0;
+ fBddSizeMax = 50000000;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'B':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ fBddSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( fBddSizeMax < 0 )
+ goto usage;
+ break;
+ case 'd':
+ fDualRail ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'r':
+ fReorder ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Can only collapse a logic network or an AIG.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Collapsing has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: collapse [-B num] [-rdvh]\n" );
+ fprintf( pErr, "\t collapses the network by constructing global BDDs\n" );
+ fprintf( pErr, "\t-B num : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax );
+ fprintf( pErr, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" );
+ fprintf( pErr, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" );
+ fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fAllNodes;
+ int fRecord;
+ int fCleanup;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fAllNodes = 0;
+ fCleanup = 1;
+ fRecord = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "acrh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'a':
+ fAllNodes ^= 1;
+ break;
+ case 'c':
+ fCleanup ^= 1;
+ break;
+ case 'r':
+ fRecord ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Strashing has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: strash [-acrh]\n" );
+ fprintf( pErr, "\t transforms combinational logic into an AIG\n" );
+ fprintf( pErr, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" );
+ fprintf( pErr, "\t-c : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" );
+ fprintf( pErr, "\t-r : enables using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp;
+ int c;
+ bool fDuplicate;
+ bool fSelective;
+ bool fUpdateLevel;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fDuplicate = 0;
+ fSelective = 0;
+ fUpdateLevel = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ldsh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'd':
+ fDuplicate ^= 1;
+ break;
+ case 's':
+ fSelective ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ // get the new network
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel );
+ }
+ else
+ {
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtkTemp == NULL )
+ {
+ fprintf( pErr, "Strashing before balancing has failed.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel );
+ Abc_NtkDelete( pNtkTemp );
+ }
+
+ // check if balancing worked
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Balancing has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: balance [-ldsh]\n" );
+ fprintf( pErr, "\t transforms the current network into a well-balanced AIG\n" );
+ fprintf( pErr, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int nThresh, nFaninMax, c;
+ int fCnf;
+ int fMulti;
+ int fSimple;
+ int fFactor;
+ extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nThresh = 1;
+ nFaninMax = 20;
+ fCnf = 0;
+ fMulti = 1;
+ fSimple = 0;
+ fFactor = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nThresh = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nThresh < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFaninMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFaninMax < 0 )
+ goto usage;
+ break;
+ case 'c':
+ fCnf ^= 1;
+ break;
+ case 'm':
+ fMulti ^= 1;
+ break;
+ case 's':
+ fSimple ^= 1;
+ break;
+ case 'f':
+ fFactor ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Renoding has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: multi [-T num] [-F num] [-msfch]\n" );
+ fprintf( pErr, "\t transforms an AIG into a logic network by creating larger nodes\n" );
+ fprintf( pErr, "\t-F num : the maximum fanin size after renoding [default = %d]\n", nFaninMax );
+ fprintf( pErr, "\t-T num : the threshold for AIG node duplication [default = %d]\n", nThresh );
+ fprintf( pErr, "\t (an AIG node is the root of a new node after renoding\n" );
+ fprintf( pErr, "\t if this leads to duplication of no more than %d AIG nodes,\n", nThresh );
+ fprintf( pErr, "\t that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] <= %d)\n", nThresh );
+ fprintf( pErr, "\t-m : creates multi-input AND graph [default = %s]\n", fMulti? "yes": "no" );
+ fprintf( pErr, "\t-s : creates a simple AIG (no renoding) [default = %s]\n", fSimple? "yes": "no" );
+ fprintf( pErr, "\t-f : creates a factor-cut network [default = %s]\n", fFactor? "yes": "no" );
+ fprintf( pErr, "\t-c : performs renoding to derive the CNF [default = %s]\n", fCnf? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int nLutSize, nCutsMax, c;
+ int nFlowIters, nAreaIters;
+ int fArea;
+ int fUseBdds;
+ int fUseSops;
+ int fUseCnfs;
+ int fUseMv;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLutSize = 8;
+ nCutsMax = 4;
+ nFlowIters = 1;
+ nAreaIters = 1;
+ fArea = 0;
+ fUseBdds = 0;
+ fUseSops = 0;
+ fUseCnfs = 0;
+ fUseMv = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nFlowIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFlowIters < 0 )
+ goto usage;
+ break;
+ case 'A':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nAreaIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nAreaIters < 0 )
+ goto usage;
+ break;
+ case 'a':
+ fArea ^= 1;
+ break;
+ case 'b':
+ fUseBdds ^= 1;
+ break;
+ case 's':
+ fUseSops ^= 1;
+ break;
+ case 'c':
+ fUseCnfs ^= 1;
+ break;
+ case 'i':
+ fUseMv ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 )
+ {
+ fprintf( pErr, "Cannot optimize two parameters at the same time.\n" );
+ return 1;
+ }
+
+ if ( nLutSize < 3 || nLutSize > IF_MAX_FUNC_LUTSIZE )
+ {
+ fprintf( pErr, "Incorrect LUT size (%d).\n", nLutSize );
+ return 1;
+ }
+
+ if ( nCutsMax < 1 || nCutsMax >= (1<<12) )
+ {
+ fprintf( pErr, "Incorrect number of cuts.\n" );
+ return 1;
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Renoding has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbciav]\n" );
+ fprintf( pErr, "\t transforms the AIG into a logic network with larger nodes\n" );
+ fprintf( pErr, "\t while minimizing the number of FF literals of the node SOPs\n" );
+ fprintf( pErr, "\t-K num : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize );
+ fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax );
+ fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters );
+ fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters );
+ fprintf( pErr, "\t-s : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" );
+ fprintf( pErr, "\t-b : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" );
+ fprintf( pErr, "\t-c : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" );
+ fprintf( pErr, "\t-i : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" );
+ fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" );
+ fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Cleanup cannot be performed on the AIG.\n" );
+ return 1;
+ }
+ // modify the current network
+ Abc_NtkCleanup( pNtk, 1 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: cleanup [-h]\n" );
+ fprintf( pErr, "\t removes dangling nodes\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "The classical (SIS-like) sweep can only be performed on a logic network.\n" );
+ return 1;
+ }
+ // modify the current network
+ Abc_NtkSweep( pNtk, 0 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sweep [-h]\n" );
+ fprintf( pErr, "\t removes dangling nodes; propagates constant, buffers, inverters\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ FILE * pOut, * pErr;
+ Fxu_Data_t * p = NULL;
+ int c;
+ extern bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
+ extern void Abc_NtkFxuFreeInfo( Fxu_Data_t * p );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // allocate the structure
+ p = ALLOC( Fxu_Data_t, 1 );
+ memset( p, 0, sizeof(Fxu_Data_t) );
+ // set the defaults
+ p->nSingleMax = 20000;
+ p->nPairsMax = 30000;
+ p->nNodesExt = 10000;
+ p->fOnlyS = 0;
+ p->fOnlyD = 0;
+ p->fUse0 = 0;
+ p->fUseCompl = 1;
+ p->fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "SDNsdzcvh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ p->nSingleMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( p->nSingleMax < 0 )
+ goto usage;
+ break;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ p->nPairsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( p->nPairsMax < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ p->nNodesExt = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( p->nNodesExt < 0 )
+ goto usage;
+ break;
+ case 's':
+ p->fOnlyS ^= 1;
+ break;
+ case 'd':
+ p->fOnlyD ^= 1;
+ break;
+ case 'z':
+ p->fUse0 ^= 1;
+ break;
+ case 'c':
+ p->fUseCompl ^= 1;
+ break;
+ case 'v':
+ p->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ Abc_NtkFxuFreeInfo( p );
+ return 1;
+ }
+
+ if ( Abc_NtkNodeNum(pNtk) == 0 )
+ {
+ fprintf( pErr, "The network does not have internal nodes.\n" );
+ Abc_NtkFxuFreeInfo( p );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Fast extract can only be applied to a logic network (run \"renode\").\n" );
+ Abc_NtkFxuFreeInfo( p );
+ return 1;
+ }
+
+
+ // the nodes to be merged are linked into the special linked list
+ Abc_NtkFastExtract( pNtk, p );
+ Abc_NtkFxuFreeInfo( p );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: fx [-S num] [-D num] [-N num] [-sdzcvh]\n");
+ fprintf( pErr, "\t performs unate fast extract on the current network\n");
+ fprintf( pErr, "\t-S num : max number of single-cube divisors to consider [default = %d]\n", p->nSingleMax );
+ fprintf( pErr, "\t-D num : max number of double-cube divisors to consider [default = %d]\n", p->nPairsMax );
+ fprintf( pErr, "\t-N num : the maximum number of divisors to extract [default = %d]\n", p->nNodesExt );
+ fprintf( pErr, "\t-s : use only single-cube divisors [default = %s]\n", p->fOnlyS? "yes": "no" );
+ fprintf( pErr, "\t-d : use only double-cube divisors [default = %s]\n", p->fOnlyD? "yes": "no" );
+ fprintf( pErr, "\t-z : use zero-weight divisors [default = %s]\n", p->fUse0? "yes": "no" );
+ fprintf( pErr, "\t-c : use complement in the binary case [default = %s]\n", p->fUseCompl? "yes": "no" );
+ fprintf( pErr, "\t-v : print verbose information [default = %s]\n", p->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ Abc_NtkFxuFreeInfo( p );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes, * pNtkNew;
+ int fGlobal, fRecursive, fVerbose, fPrint, fShort, c;
+
+ extern Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort );
+ extern int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fGlobal = 1;
+ fRecursive = 0;
+ fVerbose = 0;
+ fPrint = 0;
+ fShort = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'g':
+ fGlobal ^= 1;
+ break;
+ case 'r':
+ fRecursive ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'p':
+ fPrint ^= 1;
+ break;
+ case 's':
+ fShort ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( fGlobal )
+ {
+// fprintf( stdout, "Performing DSD of global functions of the network.\n" );
+ // get the new network
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort );
+ Abc_NtkDelete( pNtkNew );
+ }
+ else
+ {
+ pNtkRes = Abc_NtkDsdGlobal( pNtk, fVerbose, fPrint, fShort );
+ }
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Global DSD has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ }
+ else if ( fRecursive )
+ {
+ if ( !Abc_NtkIsBddLogic( pNtk ) )
+ {
+ fprintf( pErr, "This command is only applicable to logic BDD networks.\n" );
+ return 1;
+ }
+ fprintf( stdout, "Performing recursive DSD and MUX decomposition of local functions.\n" );
+ if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) )
+ fprintf( pErr, "Recursive DSD has failed.\n" );
+ }
+ else
+ {
+ if ( !Abc_NtkIsBddLogic( pNtk ) )
+ {
+ fprintf( pErr, "This command is only applicable to logic BDD networks (run \"bdd\").\n" );
+ return 1;
+ }
+ fprintf( stdout, "Performing simple non-recursive DSD of local functions.\n" );
+ if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) )
+ fprintf( pErr, "Simple DSD of local functions has failed.\n" );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dsd [-grvpsh]\n" );
+ fprintf( pErr, "\t decomposes the network using disjoint-support decomposition\n" );
+ fprintf( pErr, "\t-g : toggle DSD of global and local functions [default = %s]\n", fGlobal? "global": "local" );
+ fprintf( pErr, "\t-r : toggle recursive DSD/MUX and simple DSD [default = %s]\n", fRecursive? "recursive DSD/MUX": "simple DSD" );
+ fprintf( pErr, "\t-v : prints DSD statistics and runtime [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-p : prints DSD structure to the standard output [default = %s]\n", fPrint? "yes": "no" );
+ fprintf( pErr, "\t-s : use short PI names when printing DSD structure [default = %s]\n", fShort? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Res_Par_t Pars, * pPars = &Pars;
+ int c;
+
+// printf( "Implementation of this command is not finished.\n" );
+// return 1;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ pPars->nWindow = 62;
+ pPars->nGrowthLevel = 1;
+ pPars->nCands = 5;
+ pPars->nSimWords = 4;
+ pPars->fArea = 0;
+ pPars->fVerbose = 0;
+ pPars->fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'W':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nWindow = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nWindow < 1 || pPars->nWindow > 99 )
+ goto usage;
+ break;
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nSimWords = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nSimWords < 1 || pPars->nSimWords > 256 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nCands = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nCands < 0 || pPars->nCands > ABC_INFINITY )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY )
+ goto usage;
+ break;
+ case 'a':
+ pPars->fArea ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to a logic network.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkResynthesize( pNtk, pPars ) )
+ {
+ fprintf( pErr, "Resynthesis has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: imfs [-W <NM>] [-L <num>] [-C <num>] [-S <num>] [-avwh]\n" );
+ fprintf( pErr, "\t performs resubstitution-based resynthesis with interpolation\n" );
+ fprintf( pErr, "\t-W <NM> : fanin/fanout levels (NxM) of the window (00 <= NM <= 99) [default = %d%d]\n", pPars->nWindow/10, pPars->nWindow%10 );
+ fprintf( pErr, "\t-L <num> : the largest increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+ fprintf( pErr, "\t-C <num> : the max number of resub candidates (1 <= n) [default = %d]\n", pPars->nCands );
+ fprintf( pErr, "\t-S <num> : the number of simulation words (1 <= n <= 256) [default = %d]\n", pPars->nSimWords );
+ fprintf( pErr, "\t-a : toggle optimization for area only [default = %s]\n", pPars->fArea? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Lpk_Par_t Pars, * pPars = &Pars;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ memset( pPars, 0, sizeof(Lpk_Par_t) );
+ pPars->nLutsMax = 4; // (N) the maximum number of LUTs in the structure
+ pPars->nLutsOver = 3; // (Q) the maximum number of LUTs not in the MFFC
+ pPars->nVarsShared = 0; // (S) the maximum number of shared variables (crossbars)
+ pPars->nGrowthLevel = 0; // (L) the maximum number of increased levels
+ pPars->fSatur = 1;
+ pPars->fZeroCost = 0;
+ pPars->fFirst = 0;
+ pPars->fOldAlgo = 0;
+ pPars->fVerbose = 0;
+ pPars->fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NQSLszfovwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nLutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 8 )
+ goto usage;
+ break;
+ case 'Q':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-Q\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nLutsOver = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nLutsOver < 0 || pPars->nLutsOver > 8 )
+ goto usage;
+ break;
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nVarsShared = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 4 )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY )
+ goto usage;
+ break;
+ case 's':
+ pPars->fSatur ^= 1;
+ break;
+ case 'z':
+ pPars->fZeroCost ^= 1;
+ break;
+ case 'f':
+ pPars->fFirst ^= 1;
+ break;
+ case 'o':
+ pPars->fOldAlgo ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to a logic network.\n" );
+ return 1;
+ }
+ if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 )
+ {
+ fprintf( pErr, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Lpk_Resynthesize( pNtk, pPars ) )
+ {
+ fprintf( pErr, "Resynthesis has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: lutpack [-N <num>] [-Q <num>] [-S <num>] [-L <num>] [-szfovwh]\n" );
+ fprintf( pErr, "\t performs \"rewriting\" for LUT networks\n" );
+ fprintf( pErr, "\t-N <num> : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax );
+ fprintf( pErr, "\t-Q <num> : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver );
+ fprintf( pErr, "\t-S <num> : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared );
+ fprintf( pErr, "\t-L <num> : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+ fprintf( pErr, "\t-s : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" );
+ fprintf( pErr, "\t-f : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" );
+ fprintf( pErr, "\t-o : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle detailed printout of decomposed functions [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ bool fUpdateLevel;
+ bool fPrecompute;
+ bool fUseZeros;
+ bool fVerbose;
+ bool fVeryVerbose;
+ bool fPlaceEnable;
+ // external functions
+ extern void Rwr_Precompute();
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUpdateLevel = 1;
+ fPrecompute = 0;
+ fUseZeros = 0;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ fPlaceEnable = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'x':
+ fPrecompute ^= 1;
+ break;
+ case 'z':
+ fUseZeros ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'p':
+ fPlaceEnable ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( fPrecompute )
+ {
+ Rwr_Precompute();
+ return 0;
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) )
+ {
+ fprintf( pErr, "Rewriting has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rewrite [-lzvwh]\n" );
+ fprintf( pErr, "\t performs technology-independent rewriting of the AIG\n" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" );
+// fprintf( pErr, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nNodeSizeMax;
+ int nConeSizeMax;
+ bool fUpdateLevel;
+ bool fUseZeros;
+ bool fUseDcs;
+ bool fVerbose;
+ extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nNodeSizeMax = 10;
+ nConeSizeMax = 16;
+ fUpdateLevel = 1;
+ fUseZeros = 0;
+ fUseDcs = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nNodeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nNodeSizeMax < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConeSizeMax < 0 )
+ goto usage;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeros ^= 1;
+ break;
+ case 'd':
+ fUseDcs ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ if ( fUseDcs && nNodeSizeMax >= nConeSizeMax )
+ {
+ fprintf( pErr, "For don't-care to work, containing cone should be larger than collapsed node.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) )
+ {
+ fprintf( pErr, "Refactoring has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: refactor [-N num] [-C num] [-lzdvh]\n" );
+ fprintf( pErr, "\t performs technology-independent refactoring of the AIG\n" );
+ fprintf( pErr, "\t-N num : the max support of the collapsed node [default = %d]\n", nNodeSizeMax );
+ fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-d : toggle using don't-cares [default = %s]\n", fUseDcs? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nCutsMax;
+ bool fUpdateLevel;
+ bool fUseZeros;
+ bool fVerbose;
+ extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCutsMax = 5;
+ fUpdateLevel = 0;
+ fUseZeros = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeros ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( nCutsMax < 4 || nCutsMax > CUT_SIZE_MAX )
+ {
+ fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkRestructure( pNtk, nCutsMax, fUpdateLevel, fUseZeros, fVerbose ) )
+ {
+ fprintf( pErr, "Refactoring has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: restructure [-K num] [-lzvh]\n" );
+ fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" );
+ fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutsMax );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int RS_CUT_MIN = 4;
+ int RS_CUT_MAX = 16;
+ int c;
+ int nCutsMax;
+ int nNodesMax;
+ int nLevelsOdc;
+ bool fUpdateLevel;
+ bool fUseZeros;
+ bool fVerbose;
+ bool fVeryVerbose;
+ extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCutsMax = 8;
+ nNodesMax = 1;
+ nLevelsOdc = 0;
+ fUpdateLevel = 1;
+ fUseZeros = 0;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nNodesMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nNodesMax < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevelsOdc = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevelsOdc < 0 )
+ goto usage;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeros ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX )
+ {
+ fprintf( pErr, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX );
+ return 1;
+ }
+ if ( nNodesMax < 0 || nNodesMax > 3 )
+ {
+ fprintf( pErr, "Can only resubstitute at most 3 nodes.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) )
+ {
+ fprintf( pErr, "Refactoring has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: resub [-K num] [-N num] [-F num] [-lzvwh]\n" );
+ fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" );
+ fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax );
+ fprintf( pErr, "\t-N num : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax );
+ fprintf( pErr, "\t-F num : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle verbose printout of ODC computation [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c, Window;
+ int nFaninLevels;
+ int nFanoutLevels;
+ int fUseFanouts;
+ int fVerbose;
+ extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFaninLevels = 3;
+ nFanoutLevels = 3;
+ fUseFanouts = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'W':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ Window = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Window < 0 )
+ goto usage;
+ nFaninLevels = Window / 10;
+ nFanoutLevels = Window % 10;
+ break;
+ case 'f':
+ fUseFanouts ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) )
+ {
+ fprintf( pErr, "Redundancy removal has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rr [-W NM] [-fvh]\n" );
+ fprintf( pErr, "\t removes combinational redundancies in the current network\n" );
+ fprintf( pErr, "\t-W NM : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels );
+ fprintf( pErr, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nLutSize;
+ int fCheck;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLutSize = 12;
+ fCheck = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Kcvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ case 'c':
+ fCheck ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Can only collapse a logic network or an AIG.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Cascade synthesis has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: cascade [-K <num>] [-cvh]\n" );
+ fprintf( pErr, "\t performs LUT cascade synthesis for the current network\n" );
+ fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize );
+ fprintf( pErr, "\t-c : check equivalence after synthesis [default = %s]\n", fCheck? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t \n");
+ fprintf( pErr, " A lookup-table cascade is a programmable architecture developed by\n");
+ fprintf( pErr, " Professor Tsutomu Sasao (sasao@cse.kyutech.ac.jp) at Kyushu Institute\n");
+ fprintf( pErr, " of Technology. This work received Takeda Techno-Entrepreneurship Award:\n");
+ fprintf( pErr, " http://www.lsi-cad.com/sasao/photo/takeda.html\n");
+ fprintf( pErr, "\t \n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash( pNtk ) )
+ {
+ fprintf( pErr, "This command is only applicable to strashed networks.\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkToLogic( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Converting to a logic network has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: logic [-h]\n" );
+ fprintf( pErr, "\t transforms an AIG into a logic network with SOPs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The network is already combinational.\n" );
+ return 0;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkDup( pNtk );
+ Abc_NtkMakeComb( pNtkRes );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: comb [-h]\n" );
+ fprintf( pErr, "\t makes the current network combinational by replacing latches by PI/PO pairs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ char Buffer[32];
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c;
+ int fCheck;
+ int fComb;
+ int nPartSize;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fComb = 1;
+ fCheck = 1;
+ nPartSize = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Pch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPartSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPartSize < 0 )
+ goto usage;
+ break;
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+
+ // compute the miter
+ pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize );
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+
+ // get the new network
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Miter computation has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ if ( nPartSize == 0 )
+ strcpy( Buffer, "unused" );
+ else
+ sprintf( Buffer, "%d", nPartSize );
+ fprintf( pErr, "usage: miter [-P num] [-ch] <file1> <file2>\n" );
+ fprintf( pErr, "\t computes the miter of the two circuits\n" );
+ fprintf( pErr, "\t-P num : output partition size [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;//, * pNtkRes;
+ int fComb;
+ int c;
+ extern int Abc_NtkDemiter( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "The network is not strashed.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkPoNum(pNtk) != 1 )
+ {
+ fprintf( pErr, "The network is not a miter.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) )
+ {
+ fprintf( pErr, "The miter's PO is not an EXOR.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkDemiter( pNtk ) )
+ {
+ fprintf( pErr, "Demitering has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: demiter [-h]\n" );
+ fprintf( pErr, "\t removes topmost EXOR from the miter to create two POs\n" );
+// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;//, * pNtkRes;
+ int fComb;
+ int c;
+ extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "The network is not strashed.\n" );
+ return 1;
+ }
+/*
+ if ( Abc_NtkPoNum(pNtk) == 1 )
+ {
+ fprintf( pErr, "The network already has one PO.\n" );
+ return 1;
+ }
+*/
+/*
+ if ( Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "The miter has latches. ORing is not performed.\n" );
+ return 1;
+ }
+*/
+ // get the new network
+ if ( !Abc_NtkCombinePos( pNtk, 0 ) )
+ {
+ fprintf( pErr, "ORing the POs has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: orpos [-h]\n" );
+ fprintf( pErr, "\t creates single-output miter by ORing the POs of the current network\n" );
+// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;//, * pNtkRes;
+ int fComb;
+ int c;
+ extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "The network is not strashed.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkPoNum(pNtk) == 1 )
+ {
+ fprintf( pErr, "The network already has one PO.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "The miter has latches. ORing is not performed.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkCombinePos( pNtk, 1 ) )
+ {
+ fprintf( pErr, "ANDing the POs has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: andpos [-h]\n" );
+ fprintf( pErr, "\t creates single-output miter by ANDing the POs of the current network\n" );
+// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandAppend( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk2;
+ char * FileName;
+ int fComb;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'c':
+ fComb ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ // get the second network
+ if ( argc != globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "The network to append is not given.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "The base network should be strashed for the appending to work.\n" );
+ return 1;
+ }
+
+ // read the second network
+ FileName = argv[globalUtilOptind];
+ pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1 );
+ if ( pNtk2 == NULL )
+ return 1;
+
+ // check if the second network is combinational
+ if ( Abc_NtkLatchNum(pNtk2) )
+ {
+ fprintf( pErr, "The second network has latches. Appending does not work for such networks.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkAppend( pNtk, pNtk2, 1 ) )
+ {
+ Abc_NtkDelete( pNtk2 );
+ fprintf( pErr, "Appending the networks failed.\n" );
+ return 1;
+ }
+ Abc_NtkDelete( pNtk2 );
+ // sweep dangling logic
+ Abc_AigCleanup( pNtk->pManFunc );
+ // replace the current network
+// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: append [-h] <file>\n" );
+ fprintf( pErr, "\t appends a combinational network on top of the current network\n" );
+// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : file name with the second network\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes;
+ int fInitial;
+ int nFrames;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fInitial = 0;
+ nFrames = 5;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fih" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames <= 0 )
+ goto usage;
+ break;
+ case 'i':
+ fInitial ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ else
+ pNtkRes = Abc_NtkFrames( pNtk, nFrames, fInitial );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Unrolling the network has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: frames [-F num] [-ih]\n" );
+ fprintf( pErr, "\t unrolls the network for a number of time frames\n" );
+ fprintf( pErr, "\t-F num : the number of frames to unroll [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-i : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int fDirect;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fDirect = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'd':
+ fDirect ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Converting to SOP is possible only for logic networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkToSop(pNtk, fDirect) )
+ {
+ fprintf( pErr, "Converting to SOP has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sop [-dh]\n" );
+ fprintf( pErr, "\t converts node functions to SOP\n" );
+ fprintf( pErr, "\t-d : toggles using both phases or only positive [default = %s]\n", fDirect? "direct": "both" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Converting to BDD is possible only for logic networks.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsBddLogic(pNtk) )
+ {
+ fprintf( pOut, "The logic network is already in the BDD form.\n" );
+ return 0;
+ }
+ if ( !Abc_NtkToBdd(pNtk) )
+ {
+ fprintf( pErr, "Converting to BDD has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: bdd [-h]\n" );
+ fprintf( pErr, "\t converts node functions to BDD\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Converting to AIG is possible only for logic networks.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsAigLogic(pNtk) )
+ {
+ fprintf( pOut, "The logic network is already in the AIG form.\n" );
+ return 0;
+ }
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ fprintf( pErr, "Converting to AIG has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: aig [-h]\n" );
+ fprintf( pErr, "\t converts node functions to AIG\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fVerbose;
+ extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkIsBddLogic(pNtk) )
+ {
+ fprintf( pErr, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" );
+ return 1;
+ }
+ Abc_NtkBddReorder( pNtk, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: reorder [-vh]\n" );
+ fprintf( pErr, "\t reorders local functions of the nodes using sifting\n" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr, * pFile;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int c;
+ int fReverse;
+ int fVerbose;
+ extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose );
+ extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fReverse = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'r':
+ fReverse ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+// if ( Abc_NtkLatchNum(pNtk) > 0 )
+// {
+// printf( "Currently this procedure does not work for sequential networks.\n" );
+// return 1;
+// }
+
+ // if the var order file is given, implement this order
+ pFileName = NULL;
+ if ( argc == globalUtilOptind + 1 )
+ {
+ pFileName = argv[globalUtilOptind];
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName );
+ return 1;
+ }
+ fclose( pFile );
+ }
+ if ( pFileName )
+ Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose );
+ else
+ Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: order [-rvh] <file>\n" );
+ fprintf( pErr, "\t computes a good static CI variable order\n" );
+ fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : (optional) file with the given variable order\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsBddLogic(pNtk) )
+ {
+ fprintf( pErr, "Only a BDD logic network can be converted to MUXes.\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkBddToMuxes( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Converting to MUXes has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: muxes [-h]\n" );
+ fprintf( pErr, "\t converts the current network by a network derived by\n" );
+ fprintf( pErr, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fVerbose;
+ extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, bool fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkLatchNum(pNtk) == 0 )
+ {
+ fprintf( stdout, "The current network has no latches.\n" );
+ return 0;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" );
+ return 0;
+ }
+ if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) )
+ {
+ fprintf( stdout, "Extracting sequential don't-cares has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: ext_seq_dcs [-vh]\n" );
+ fprintf( pErr, "\t create EXDC network using unreachable states\n" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ Abc_Obj_t * pNode, * pNodeCo;
+ int c;
+ int fUseAllCis;
+ int fUseMffc;
+ int Output;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseAllCis = 0;
+ fUseMffc = 0;
+ Output = -1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Omah" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'O':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ Output = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Output < 0 )
+ goto usage;
+ break;
+ case 'm':
+ fUseMffc ^= 1;
+ case 'a':
+ fUseAllCis ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Currently can only be applied to the logic network or an AIG.\n" );
+ return 1;
+ }
+
+ if ( argc > globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+
+ pNodeCo = NULL;
+ if ( argc == globalUtilOptind + 1 )
+ {
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+ if ( fUseMffc )
+ pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] );
+ else
+ pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis );
+ }
+ else
+ {
+ if ( Output == -1 )
+ {
+ fprintf( pErr, "The node is not specified.\n" );
+ return 1;
+ }
+ if ( Output >= Abc_NtkCoNum(pNtk) )
+ {
+ fprintf( pErr, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) );
+ return 1;
+ }
+ pNodeCo = Abc_NtkCo( pNtk, Output );
+ if ( fUseMffc )
+ pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) );
+ else
+ pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis );
+ }
+ if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) )
+ printf( "The extracted cone represents the complement function of the CO.\n" );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Writing the logic cone of one node has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: cone [-O num] [-amh] <name>\n" );
+ fprintf( pErr, "\t replaces the current network by one logic cone\n" );
+ fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" );
+ fprintf( pErr, "\t-m : toggle writing only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t-O num : (optional) the 0-based number of the CO to extract\n");
+ fprintf( pErr, "\tname : (optional) the name of the node to extract\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ Abc_Obj_t * pNode;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Currently can only be applied to a logic network.\n" );
+ return 1;
+ }
+
+ if ( argc != globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Wrong number of auguments.\n" );
+ goto usage;
+ }
+
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
+ if ( pNode == NULL )
+ {
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode );
+// pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Splitting one node has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: node [-h] <name>\n" );
+ fprintf( pErr, "\t replaces the current network by the network composed of one node\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tname : the node name\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nLevels;
+ extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLevels = 10;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only works for combinational circuits.\n" );
+ return 0;
+ }
+ if ( Abc_NtkPoNum(pNtk) != 1 )
+ {
+ fprintf( stdout, "Currently expects a single-output miter.\n" );
+ return 0;
+ }
+
+ pNtkRes = Abc_NtkTopmost( pNtk, nLevels );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "The command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: topmost [-N num] [-h]\n" );
+ fprintf( pErr, "\t replaces the current network by several of its topmost levels\n" );
+ fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tname : the node name\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nLevels;
+ extern Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLevels = 10;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+/*
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+*/
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for logic circuits.\n" );
+ return 0;
+ }
+
+ pNtkRes = Abc_NtkTrim( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "The command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: trim [-h]\n" );
+ fprintf( pErr, "\t removes POs fed by PIs and constants, and PIs w/o fanout\n" );
+// fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ Abc_NtkShortNames( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: short_names [-h]\n" );
+ fprintf( pErr, "\t replaces PI/PO/latch names by short char strings\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( pNtk->pExdc == NULL )
+ {
+ fprintf( pErr, "The network has no EXDC.\n" );
+ return 1;
+ }
+
+ Abc_NtkDelete( pNtk->pExdc );
+ pNtk->pExdc = NULL;
+
+ // replace the current network
+ pNtkRes = Abc_NtkDup( pNtk );
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: exdc_free [-h]\n" );
+ fprintf( pErr, "\t frees the EXDC network of the current network\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( pNtk->pExdc == NULL )
+ {
+ fprintf( pErr, "The network has no EXDC.\n" );
+ return 1;
+ }
+
+ // replace the current network
+ pNtkRes = Abc_NtkDup( pNtk->pExdc );
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: exdc_get [-h]\n" );
+ fprintf( pErr, "\t replaces the current network by the EXDC of the current network\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr, * pFile;
+ Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+ char * FileName;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( argc != globalUtilOptind + 1 )
+ {
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[globalUtilOptind];
+ if ( (pFile = fopen( FileName, "r" )) == NULL )
+ {
+ fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
+ if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) )
+ fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName );
+ fprintf( pAbc->Err, "\n" );
+ return 1;
+ }
+ fclose( pFile );
+
+ // set the new network
+ pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1 );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pAbc->Err, "Reading network from file has failed.\n" );
+ return 1;
+ }
+
+ // replace the EXDC
+ if ( pNtk->pExdc )
+ {
+ Abc_NtkDelete( pNtk->pExdc );
+ pNtk->pExdc = NULL;
+ }
+ pNtkRes = Abc_NtkDup( pNtk );
+ pNtkRes->pExdc = pNtkNew;
+
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: exdc_set [-h] <file>\n" );
+ fprintf( pErr, "\t sets the network from file as EXDC for the current network\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : file with the new EXDC network\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pCutMan;
+ Cut_Oracle_t * pCutOracle;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fOracle;
+ extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+ extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fOracle = 0;
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 1000; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fDrop = 0; // drop cuts on the fly
+ pParams->fDag = 0; // compute DAG cuts
+ pParams->fTree = 0; // compute tree cuts
+ pParams->fGlobal = 0; // compute global cuts
+ pParams->fLocal = 0; // compute local cuts
+ pParams->fFancy = 0; // compute something fancy
+ pParams->fMap = 0; // compute mapping delay
+ pParams->fVerbose = 0; // the verbosiness flag
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzmvoh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nVarsMax < 0 )
+ goto usage;
+ break;
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nKeepMax < 0 )
+ goto usage;
+ break;
+ case 't':
+ pParams->fTruth ^= 1;
+ break;
+ case 'f':
+ pParams->fFilter ^= 1;
+ break;
+ case 'd':
+ pParams->fDrop ^= 1;
+ break;
+ case 'x':
+ pParams->fDag ^= 1;
+ break;
+ case 'y':
+ pParams->fTree ^= 1;
+ break;
+ case 'g':
+ pParams->fGlobal ^= 1;
+ break;
+ case 'l':
+ pParams->fLocal ^= 1;
+ break;
+ case 'z':
+ pParams->fFancy ^= 1;
+ break;
+ case 'm':
+ pParams->fMap ^= 1;
+ break;
+ case 'v':
+ pParams->fVerbose ^= 1;
+ break;
+ case 'o':
+ fOracle ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Cut computation is available only for AIGs (run \"strash\").\n" );
+ return 1;
+ }
+ if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX )
+ {
+ fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX );
+ return 1;
+ }
+ if ( pParams->fDag && pParams->fTree )
+ {
+ fprintf( pErr, "Cannot compute both DAG cuts and tree cuts at the same time.\n" );
+ return 1;
+ }
+
+ if ( fOracle )
+ pParams->fRecord = 1;
+ pCutMan = Abc_NtkCuts( pNtk, pParams );
+ if ( fOracle )
+ pCutOracle = Cut_OracleStart( pCutMan );
+ Cut_ManStop( pCutMan );
+ if ( fOracle )
+ {
+ Abc_NtkCutsOracle( pNtk, pCutOracle );
+ Cut_OracleStop( pCutOracle );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzmvh]\n" );
+ fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" );
+ fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax );
+ fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax );
+ fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" );
+ fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" );
+ fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" );
+ fprintf( pErr, "\t-x : toggle computing only DAG cuts [default = %s]\n", pParams->fDag? "yes": "no" );
+ fprintf( pErr, "\t-y : toggle computing only tree cuts [default = %s]\n", pParams->fTree? "yes": "no" );
+ fprintf( pErr, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" );
+ fprintf( pErr, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pCutMan;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 1000; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 1; // compute sequential cuts
+ pParams->fVerbose = 0; // the verbosiness flag
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nVarsMax < 0 )
+ goto usage;
+ break;
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nKeepMax < 0 )
+ goto usage;
+ break;
+ case 't':
+ pParams->fTruth ^= 1;
+ break;
+ case 'v':
+ pParams->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+/*
+ if ( !Abc_NtkIsSeq(pNtk) )
+ {
+ fprintf( pErr, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" );
+ return 1;
+ }
+*/
+ if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX )
+ {
+ fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX );
+ return 1;
+ }
+
+ pCutMan = Abc_NtkSeqCuts( pNtk, pParams );
+ Cut_ManStop( pCutMan );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: scut [-K num] [-M num] [-tvh]\n" );
+ fprintf( pErr, "\t computes k-feasible cuts for the sequential AIG\n" );
+ fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax );
+ fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax );
+ fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fVerbose;
+ extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "SOP minimization is possible for logic networks (run \"renode\").\n" );
+ return 1;
+ }
+ Abc_NtkEspresso( pNtk, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: espresso [-vh]\n" );
+ fprintf( pErr, "\t minimizes SOPs of the local functions using Espresso\n" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nVars;
+ int fAdder;
+ int fSorter;
+ int fMesh;
+ int fFpga;
+ int fVerbose;
+ char * FileName;
+ extern void Abc_GenAdder( char * pFileName, int nVars );
+ extern void Abc_GenSorter( char * pFileName, int nVars );
+ extern void Abc_GenMesh( char * pFileName, int nVars );
+ extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars );
+
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nVars = 8;
+ fAdder = 0;
+ fSorter = 0;
+ fMesh = 0;
+ fFpga = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nasmfvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nVars = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nVars < 0 )
+ goto usage;
+ break;
+ case 'a':
+ fAdder ^= 1;
+ break;
+ case 's':
+ fSorter ^= 1;
+ break;
+ case 'm':
+ fMesh ^= 1;
+ break;
+ case 'f':
+ fFpga ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( argc != globalUtilOptind + 1 )
+ {
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[globalUtilOptind];
+ if ( fAdder )
+ Abc_GenAdder( FileName, nVars );
+ else if ( fSorter )
+ Abc_GenSorter( FileName, nVars );
+ else if ( fMesh )
+ Abc_GenMesh( FileName, nVars );
+ else if ( fFpga )
+ Abc_GenFpga( FileName, 4, 3, 10 );
+// Abc_GenFpga( FileName, 2, 2, 3 );
+// Abc_GenFpga( FileName, 3, 2, 5 );
+ else
+ printf( "Type of circuit is not specified.\n" );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: gen [-N] [-asmfvh] <file>\n" );
+ fprintf( pErr, "\t generates simple circuits\n" );
+ fprintf( pErr, "\t-N num : the number of variables [default = %d]\n", nVars );
+ fprintf( pErr, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" );
+ fprintf( pErr, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" );
+ fprintf( pErr, "\t-m : generate a mesh [default = %s]\n", fMesh? "yes": "no" );
+ fprintf( pErr, "\t-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t<file> : output file name\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandXyz( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;//, * pNtkTemp;
+ int c;
+ int nLutMax;
+ int nPlaMax;
+ int RankCost;
+ int fFastMode;
+ int fRewriting;
+ int fSynthesis;
+ int fVerbose;
+// extern Abc_Ntk_t * Abc_NtkXyz( Abc_Ntk_t * pNtk, int nPlaMax, bool fEsop, bool fSop, bool fInvs, bool fVerbose );
+ extern void * Abc_NtkPlayer( void * pNtk, int nLutMax, int nPlaMax, int RankCost, int fFastMode, int fRewriting, int fSynthesis, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLutMax = 8;
+ nPlaMax = 128;
+ RankCost = 96000;
+ fFastMode = 1;
+ fRewriting = 0;
+ fSynthesis = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "LPRfrsvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLutMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutMax < 0 )
+ goto usage;
+ break;
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPlaMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPlaMax < 0 )
+ goto usage;
+ break;
+ case 'R':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ RankCost = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( RankCost < 0 )
+ goto usage;
+ break;
+ case 'f':
+ fFastMode ^= 1;
+ break;
+ case 'r':
+ fRewriting ^= 1;
+ break;
+ case 's':
+ fSynthesis ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for strashed networks.\n" );
+ return 1;
+ }
+/*
+ if ( nLutMax < 2 || nLutMax > 12 || nPlaMax < 8 || nPlaMax > 128 )
+ {
+ fprintf( pErr, "Incorrect LUT/PLA parameters.\n" );
+ return 1;
+ }
+*/
+ // run the command
+// pNtkRes = Abc_NtkXyz( pNtk, nPlaMax, 1, 0, fInvs, fVerbose );
+/*
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ pNtkRes = Abc_NtkPlayer( pNtkTemp, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ else
+ pNtkRes = Abc_NtkPlayer( pNtk, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose );
+*/
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: xyz [-L num] [-P num] [-R num] [-frsvh]\n" );
+ fprintf( pErr, "\t specilized LUT/PLA decomposition\n" );
+ fprintf( pErr, "\t-L num : maximum number of LUT inputs (2<=num<=8) [default = %d]\n", nLutMax );
+ fprintf( pErr, "\t-P num : maximum number of PLA inputs/cubes (8<=num<=128) [default = %d]\n", nPlaMax );
+ fprintf( pErr, "\t-R num : maximum are of one decomposition rank [default = %d]\n", RankCost );
+ fprintf( pErr, "\t-f : toggle using fast LUT mapping mode [default = %s]\n", fFastMode? "yes": "no" );
+ fprintf( pErr, "\t-r : toggle using one pass of AIG rewriting [default = %s]\n", fRewriting? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle using synthesis by AIG rewriting [default = %s]\n", fSynthesis? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDouble( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int nFrames;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 50;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsSopLogic(pNtk) )
+ {
+ fprintf( pErr, "Only works for logic SOP networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkDouble( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: double [-vh]\n" );
+ fprintf( pErr, "\t puts together two parallel copies of the current network\n" );
+// fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int nLevels;
+ int fVerbose;
+// extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk );
+// extern Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk );
+// extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk );
+// extern int Pr_ManProofTest( char * pFileName );
+ extern void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk );
+ extern void Abc_NtkCompareCones( Abc_Ntk_t * pNtk );
+ extern Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk );
+ extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName );
+ extern Abc_Ntk_t * Abc_NtkFilter( Abc_Ntk_t * pNtk );
+ extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose );
+ extern Abc_Ntk_t * Abc_NtkPcmTest( Abc_Ntk_t * pNtk, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ nLevels = 1000;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+/*
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsSeq(pNtk) )
+ {
+ fprintf( pErr, "Only works for non-sequential networks.\n" );
+ return 1;
+ }
+*/
+
+// Abc_NtkTestEsop( pNtk );
+// Abc_NtkTestSop( pNtk );
+// printf( "This command is currently not used.\n" );
+ // run the command
+// pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 );
+// pNtkRes = Abc_NtkNewAig( pNtk );
+
+/*
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+*/
+
+// if ( Cut_CellIsRunning() )
+// Cut_CellDumpToFile();
+// else
+// Cut_CellPrecompute();
+// Cut_CellLoad();
+/*
+ {
+ Abc_Ntk_t * pNtkRes;
+ extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels );
+ pNtkRes = Abc_NtkTopmost( pNtk, nLevels );
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ }
+*/
+// Abc_NtkSimulteBuggyMiter( pNtk );
+
+// Rwr_Temp();
+// Abc_MvExperiment();
+// Ivy_TruthTest();
+
+
+// Ivy_TruthEstimateNodesTest();
+/*
+ pNtkRes = Abc_NtkIvy( pNtk );
+// pNtkRes = Abc_NtkPlayer( pNtk, nLevels, 0 );
+// pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+*/
+// Abc_NtkMaxFlowTest( pNtk );
+// Pr_ManProofTest( "trace.cnf" );
+
+// Abc_NtkCompareSupports( pNtk );
+// Abc_NtkCompareCones( pNtk );
+/*
+ {
+ extern Vec_Vec_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int fVerbose );
+ Vec_Vec_t * vParts;
+ vParts = Abc_NtkPartitionSmart( pNtk, 1 );
+ Vec_VecFree( vParts );
+ }
+*/
+// Abc_Ntk4VarTable( pNtk );
+// Dar_NtkGenerateArrays( pNtk );
+// Dar_ManDeriveCnfTest2();
+/*
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Network should be strashed. Command has failed.\n" );
+ return 1;
+ }
+*/
+/*
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+*/
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for logic circuits.\n" );
+ return 0;
+ }
+
+// pNtkRes = Abc_NtkDar( pNtk );
+// pNtkRes = Abc_NtkDarRetime( pNtk, nLevels, 1 );
+ pNtkRes = Abc_NtkPcmTest( pNtk, fVerbose );
+// pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+usage:
+ fprintf( pErr, "usage: test [-h]\n" );
+ fprintf( pErr, "\t testbench for new procedures\n" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandQuaVar( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, iVar, fUniv, fVerbose, RetValue;
+ extern int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ iVar = 0;
+ fUniv = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Iuvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ iVar = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( iVar < 0 )
+ goto usage;
+ break;
+ case 'u':
+ fUniv ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" );
+ return 1;
+ }
+
+ // get the strashed network
+ pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ RetValue = Abc_NtkQuantify( pNtkRes, fUniv, iVar, fVerbose );
+ // clean temporary storage for the cofactors
+ Abc_NtkCleanData( pNtkRes );
+ Abc_AigCleanup( pNtkRes->pManFunc );
+ // check the result
+ if ( !RetValue )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: qvar [-I num] [-uvh]\n" );
+ fprintf( pErr, "\t quantifies one variable using the AIG\n" );
+ fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar );
+ fprintf( pErr, "\t-u : toggle universal quantification [default = %s]\n", fUniv? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandQuaRel( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, iVar, fInputs, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ iVar = 0;
+ fInputs = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Iqvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ iVar = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( iVar < 0 )
+ goto usage;
+ break;
+ case 'q':
+ fInputs ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "This command works only for sequential circuits.\n" );
+ return 1;
+ }
+
+ // get the strashed network
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose );
+ // check if the result is available
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: qrel [-qvh]\n" );
+ fprintf( pErr, "\t computes transition relation of the sequential network\n" );
+// fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar );
+ fprintf( pErr, "\t-q : perform quantification of inputs [default = %s]\n", fInputs? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandQuaReach( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nIters, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtk, int nIters, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nIters = 256;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nIters < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "This command works only for combinational transition relations.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ if ( Abc_NtkPoNum(pNtk) > 1 )
+ {
+ fprintf( pErr, "The transition relation should have one output.\n" );
+ return 1;
+ }
+ if ( Abc_NtkPiNum(pNtk) % 2 != 0 )
+ {
+ fprintf( pErr, "The transition relation should have an even number of inputs.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkReachability( pNtk, nIters, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: qreach [-I num] [-vh]\n" );
+ fprintf( pErr, "\t computes unreachable states using AIG-based quantification\n" );
+ fprintf( pErr, "\t assumes that the current network is a transition relation\n" );
+ fprintf( pErr, "\t assumes that the initial state is composed of all zeros\n" );
+ fprintf( pErr, "\t-I num : the number of image computations to perform [default = %d]\n", nIters );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ pNtkRes = Abc_NtkIvyStrash( pNtkTemp );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ else
+ pNtkRes = Abc_NtkIvyStrash( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: istrash [-h]\n" );
+ fprintf( pErr, "\t perform sequential structural hashing\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandICut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c, nInputs;
+ extern void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nInputs = 5;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Kh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInputs = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInputs < 0 )
+ goto usage;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ Abc_NtkIvyCuts( pNtk, nInputs );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: icut [-K num] [-h]\n" );
+ fprintf( pErr, "\t computes sequential cuts of the given size\n" );
+ fprintf( pErr, "\t-K num : the number of cut inputs (2 <= num <= 6) [default = %d]\n", nInputs );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUpdateLevel, fUseZeroCost, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUpdateLevel = 1;
+ fUseZeroCost = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeroCost ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyRewrite( pNtk, fUpdateLevel, fUseZeroCost, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: irw [-lzvh]\n" );
+ fprintf( pErr, "\t perform combinational AIG rewriting\n" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ Dar_RwrPar_t Pars, * pPars = &Pars;
+ int c;
+
+ extern Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Dar_ManDefaultRwrParams( pPars );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CNflzvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nSubgMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nSubgMax < 0 )
+ goto usage;
+ break;
+ case 'f':
+ pPars->fFanout ^= 1;
+ break;
+ case 'l':
+ pPars->fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ pPars->fUseZeros ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDRewrite( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: drw [-C num] [-N num] [-flzvwh]\n" );
+ fprintf( pErr, "\t performs combinational AIG rewriting\n" );
+ fprintf( pErr, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax );
+ fprintf( pErr, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax );
+ fprintf( pErr, "\t-f : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ Dar_RefPar_t Pars, * pPars = &Pars;
+ int c;
+
+ extern Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Dar_ManDefaultRefParams( pPars );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "MKCelzvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nMffcMin = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nMffcMin < 0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nLeafMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nLeafMax < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'e':
+ pPars->fExtend ^= 1;
+ break;
+ case 'l':
+ pPars->fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ pPars->fUseZeros ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ if ( pPars->nLeafMax < 4 || pPars->nLeafMax > 15 )
+ {
+ fprintf( pErr, "This command only works for cut sizes 4 <= K <= 15.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDRefactor( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: drf [-M num] [-K num] [-C num] [-elzvwh]\n" );
+ fprintf( pErr, "\t performs combinational AIG refactoring\n" );
+ fprintf( pErr, "\t-M num : the min MFFC size to attempt refactoring [default = %d]\n", pPars->nMffcMin );
+ fprintf( pErr, "\t-K num : the max number of cuts leaves [default = %d]\n", pPars->nLeafMax );
+ fprintf( pErr, "\t-C num : the max number of cuts to try at a node [default = %d]\n", pPars->nCutsMax );
+ fprintf( pErr, "\t-e : toggle extending tbe cut below MFFC [default = %s]\n", pPars->fExtend? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fBalance, fVerbose, fUpdateLevel, c;
+
+ extern Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fBalance = 0;
+ fVerbose = 0;
+ fUpdateLevel = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fBalance ^= 1;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDCompress2( pNtk, fBalance, fUpdateLevel, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dcompress2 [-blvh]\n" );
+ fprintf( pErr, "\t performs combinational AIG optimization\n" );
+ fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fBalance, fVerbose, fUpdateLevel, c;
+
+ extern Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fBalance = 1;
+ fUpdateLevel = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fBalance ^= 1;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDChoice( pNtk, fBalance, fUpdateLevel, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dchoice [-blvh]\n" );
+ fprintf( pErr, "\t performs partitioned choicing using a new AIG package\n" );
+ fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDrwsat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fBalance, fVerbose, c;
+
+ extern Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fBalance = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'b':
+ fBalance ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+ pNtkRes = Abc_NtkDrwsat( pNtk, fBalance, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: drwsat [-bvh]\n" );
+ fprintf( pErr, "\t performs combinational AIG optimization for SAT\n" );
+ fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUpdateLevel, fUseZeroCost, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUpdateLevel = 0;
+ fUseZeroCost = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeroCost ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyRewriteSeq( pNtk, fUseZeroCost, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: irws [-zvh]\n" );
+ fprintf( pErr, "\t perform sequential AIG rewriting\n" );
+// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIResyn( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUpdateLevel, fVerbose;
+ extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUpdateLevel = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyResyn( pNtk, fUpdateLevel, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: iresyn [-lvh]\n" );
+ fprintf( pErr, "\t performs combinational resynthesis\n" );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandISat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUpdateLevel, fVerbose;
+ int nConfLimit;
+
+ extern Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nConfLimit = 100000;
+ fUpdateLevel = 1;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Clzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvySat( pNtk, nConfLimit, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: isat [-C num] [-vh]\n" );
+ fprintf( pErr, "\t tries to prove the miter constant 0\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fProve, fVerbose, fDoSparse;
+ int nConfLimit;
+
+ extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nConfLimit = 100;
+ fDoSparse = 0;
+ fProve = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Cspvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 's':
+ fDoSparse ^= 1;
+ break;
+ case 'p':
+ fProve ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: ifraig [-C num] [-spvh]\n" );
+ fprintf( pErr, "\t performs fraiging using a new method\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nConfLimit, fDoSparse, fProve, fSpeculate, fChoicing, fVerbose;
+
+ extern Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nConfLimit = 100;
+ fDoSparse = 1;
+ fProve = 0;
+ fSpeculate = 0;
+ fChoicing = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Csprcvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 's':
+ fDoSparse ^= 1;
+ break;
+ case 'p':
+ fProve ^= 1;
+ break;
+ case 'r':
+ fSpeculate ^= 1;
+ break;
+ case 'c':
+ fChoicing ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkDarFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fSpeculate, fChoicing, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dfraig [-C num] [-sprcvh]\n" );
+ fprintf( pErr, "\t performs fraiging using a new method\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" );
+ fprintf( pErr, "\t-r : toggle speculative reduction [default = %s]\n", fSpeculate? "yes": "no" );
+ fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", fChoicing? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nCutsMax, nLeafMax, fVerbose;
+
+ extern Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCutsMax = 8;
+ nLeafMax = 6;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CKvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLeafMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLeafMax < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( nCutsMax < 2 )
+ {
+ fprintf( pErr, "The number of cuts cannot be less than 2.\n" );
+ return 1;
+ }
+
+ if ( nLeafMax < 3 || nLeafMax > 16 )
+ {
+ fprintf( pErr, "The number of leaves is infeasible.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkCSweep( pNtk, nCutsMax, nLeafMax, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: csweep [-C num] [-K num] [-vh]\n" );
+ fprintf( pErr, "\t performs cut sweeping using a new method\n" );
+ fprintf( pErr, "\t-C num : limit on the number of cuts (C >= 2) [default = %d]\n", nCutsMax );
+ fprintf( pErr, "\t-K num : limit on the cut size (3 <= K <= 16) [default = %d]\n", nLeafMax );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Prove_Params_t Params, * pParams = &Params;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ int c, clk, RetValue;
+
+ extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Prove_ParamsSetDefault( pParams );
+ pParams->fUseRewriting = 1;
+ pParams->fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'r':
+ pParams->fUseRewriting ^= 1;
+ break;
+ case 'v':
+ pParams->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ clk = clock();
+
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkTemp = Abc_NtkDup( pNtk );
+ else
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+
+ RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams );
+
+ // verify that the pattern is correct
+ if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ free( pSimInfo );
+ }
+
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+
+ PRT( "Time", clock() - clk );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: iprove [-rvh]\n" );
+ fprintf( pErr, "\t performs CEC using a new method\n" );
+ fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, fUseZeroCost, fVerbose, nIters;
+ extern Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nIters = 2;
+ fUseZeroCost = 0;
+ fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Izvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nIters < 0 )
+ goto usage;
+ break;
+ case 'z':
+ fUseZeroCost ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for strashed networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkIvyHaig( pNtk, nIters, fUseZeroCost, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: haig [-Izvh]\n" );
+ fprintf( pErr, "\t prints HAIG stats after sequential rewriting\n" );
+ fprintf( pErr, "\t-I num : the number of rewriting iterations [default = %d]\n", nIters );
+ fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMini( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for combinatinally strashed AIG networks.\n" );
+ return 1;
+ }
+
+ pNtkRes = Abc_NtkMiniBalance( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: mini [-h]\n" );
+ fprintf( pErr, "\t perform balancing using new package\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int fInit;
+ int fVerbose;
+
+ extern void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 5;
+ fInit = 0;
+ fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Kivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'i':
+ fInit ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkBmc( pNtk, nFrames, fInit, fVerbose );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ Abc_NtkBmc( pNtk, nFrames, fInit, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: _bmc [-K num] [-ivh]\n" );
+ fprintf( pErr, "\t perform bounded model checking\n" );
+ fprintf( pErr, "\t-K num : number of time frames [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-i : toggle initialization of the first frame [default = %s]\n", fInit? "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;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nPars;
+ int fVerbose;
+
+ extern void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nPars = -1;
+ fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Pvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPars = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPars < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "Works only for combinational networks.\n" );
+ return 1;
+ }
+ if ( Abc_NtkPoNum(pNtk) != 1 )
+ {
+ fprintf( pErr, "The miter should have one primary output.\n" );
+ return 1;
+ }
+ if ( !(nPars > 0 && nPars < Abc_NtkPiNum(pNtk)) )
+ {
+ fprintf( pErr, "The number of paramter variables is invalid (should be > 0 and < PI num).\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkQbf( pNtk, nPars, fVerbose );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ Abc_NtkQbf( pNtk, nPars, fVerbose );
+ Abc_NtkDelete( pNtk );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: qbf [-P num] [-vh]\n" );
+ fprintf( pErr, "\t solves a quantified boolean formula problem EpVxM(p,x)\n" );
+ fprintf( pErr, "\t-P num : number of paramters (should be the first PIs) [default = %d]\n", nPars );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ char Buffer[100];
+ Fraig_Params_t Params, * pParams = &Params;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fAllNodes;
+ int fExdc;
+ int c;
+ int fPartition = 0;
+ extern void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fExdc = 0;
+ fAllNodes = 0;
+ memset( pParams, 0, sizeof(Fraig_Params_t) );
+ pParams->nPatsRand = 2048; // the number of words of random simulation info
+ pParams->nPatsDyna = 2048; // the number of words of dynamic simulation info
+ pParams->nBTLimit = 100; // the max number of backtracks to perform
+ pParams->fFuncRed = 1; // performs only one level hashing
+ pParams->fFeedBack = 1; // enables solver feedback
+ pParams->fDist1Pats = 1; // enables distance-1 patterns
+ pParams->fDoSparse = 1; // performs equiv tests for sparse functions
+ pParams->fChoicing = 0; // enables recording structural choices
+ pParams->fTryProve = 0; // tries to solve the final miter
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->fVerboseP = 0; // the verbosiness flag
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "RDCrscptvaeh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'R':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nPatsRand = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nPatsRand < 0 )
+ goto usage;
+ break;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nPatsDyna = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nPatsDyna < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nBTLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nBTLimit < 0 )
+ goto usage;
+ break;
+
+ case 'r':
+ pParams->fFuncRed ^= 1;
+ break;
+ case 's':
+ pParams->fDoSparse ^= 1;
+ break;
+ case 'c':
+ pParams->fChoicing ^= 1;
+ break;
+ case 'p':
+ pParams->fTryProve ^= 1;
+ break;
+ case 'v':
+ pParams->fVerbose ^= 1;
+ break;
+ case 't':
+ fPartition ^= 1;
+ break;
+ case 'a':
+ fAllNodes ^= 1;
+ break;
+ case 'e':
+ fExdc ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Can only fraig a logic network or an AIG.\n" );
+ return 1;
+ }
+
+ // report the proof
+ pParams->fVerboseP = pParams->fTryProve;
+
+ // get the new network
+ if ( fPartition )
+ {
+ pNtkRes = Abc_NtkDup( pNtk );
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkFraigPartitionedTime( pNtk, &Params );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 );
+ Abc_NtkFraigPartitionedTime( pNtk, &Params );
+ Abc_NtkDelete( pNtk );
+ }
+ }
+ else
+ {
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc );
+ else
+ {
+ pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 );
+ pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc );
+ Abc_NtkDelete( pNtk );
+ }
+ }
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Fraiging has failed.\n" );
+ return 1;
+ }
+
+ if ( pParams->fTryProve ) // report the result
+ Abc_NtkMiterReport( pNtkRes );
+
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ sprintf( Buffer, "%d", pParams->nBTLimit );
+ fprintf( pErr, "usage: fraig [-R num] [-D num] [-C num] [-rscpvtah]\n" );
+ fprintf( pErr, "\t transforms a logic network into a functionally reduced AIG\n" );
+ fprintf( pErr, "\t-R num : number of random patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsRand );
+ fprintf( pErr, "\t-D num : number of systematic patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsDyna );
+ fprintf( pErr, "\t-C num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer );
+ fprintf( pErr, "\t-r : toggle functional reduction [default = %s]\n", pParams->fFuncRed? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", pParams->fDoSparse? "yes": "no" );
+ fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", pParams->fChoicing? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", pParams->fTryProve? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" );
+ fprintf( pErr, "\t-a : toggle between all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "dfs" );
+ fprintf( pErr, "\t-t : toggle using partitioned representation [default = %s]\n", fPartition? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fDuplicate;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fDuplicate = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'd':
+ fDuplicate ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkFraigTrust( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Fraiging in the trust mode has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: fraig_trust [-h]\n" );
+ fprintf( pErr, "\t transforms the current network into an AIG assuming it is FRAIG with choices\n" );
+// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fDuplicate;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fDuplicate = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'd':
+ fDuplicate ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkFraigStore( pNtk ) )
+ {
+ fprintf( pErr, "Fraig storing has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: fraig_store [-h]\n" );
+ fprintf( pErr, "\t saves the current network in the AIG database\n" );
+// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fDuplicate;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fDuplicate = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'd':
+ fDuplicate ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkFraigRestore();
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Fraig restoring has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: fraig_restore [-h]\n" );
+ fprintf( pErr, "\t makes the current network by fraiging the AIG database\n" );
+// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fDuplicate;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fDuplicate = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'd':
+ fDuplicate ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ Abc_NtkFraigStoreClean();
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: fraig_clean [-h]\n" );
+ fprintf( pErr, "\t cleans the internal FRAIG storage\n" );
+// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fUseInv;
+ int fExdc;
+ int fVerbose;
+ int fVeryVerbose;
+ extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseInv = 1;
+ fExdc = 0;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ievwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'i':
+ fUseInv ^= 1;
+ break;
+ case 'e':
+ fExdc ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Cannot sweep AIGs (use \"fraig\").\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "Transform the current network into a logic network.\n" );
+ return 1;
+ }
+ // modify the current network
+ if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) )
+ {
+ fprintf( pErr, "Sweeping has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: fraig_sweep [-evwh]\n" );
+ fprintf( pErr, "\t performs technology-dependent sweep\n" );
+ fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : prints equivalence class information [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFraigDress( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ char * pFileName;
+ int c;
+ int fVerbose;
+ extern void Abc_NtkDress( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for logic networks.\n" );
+ return 1;
+ }
+ if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 )
+ goto usage;
+ if ( argc == globalUtilOptind && Abc_NtkSpec(pNtk) == NULL )
+ {
+ fprintf( pErr, "The current network has no spec.\n" );
+ return 1;
+ }
+ // get the input file name
+ pFileName = (argc == globalUtilOptind + 1) ? argv[globalUtilOptind] : Abc_NtkSpec(pNtk);
+ // modify the current network
+ Abc_NtkDress( pNtk, pFileName, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dress [-vh] <file>\n" );
+ fprintf( pErr, "\t transfers internal node names from file to the current network\n" );
+ fprintf( pErr, "\t<file> : network with names (if not given, the current network spec is used)\n" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandHaigStart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" );
+ return 0;
+ }
+ Abc_NtkHaigStart( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: haig_start [-h]\n" );
+ fprintf( pErr, "\t starts constructive accumulation of combinational choices\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandHaigStop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" );
+ return 0;
+ }
+ Abc_NtkHaigStop( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: haig_stop [-h]\n" );
+ fprintf( pErr, "\t cleans the internal storage for combinational choices\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandHaigUse( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" );
+ return 0;
+ }
+ // get the new network
+ pNtkRes = Abc_NtkHaigUse( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Transforming internal storage into AIG with choices has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: haig_use [-h]\n" );
+ fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecStart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nVars;
+ int nCuts;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nVars = 4;
+ nCuts = 8;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nVars = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nVars < 1 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCuts = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCuts < 1 )
+ goto usage;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !(nVars >= 3 && nVars <= 16) )
+ {
+ fprintf( pErr, "The range of allowed values is 3 <= K <= 16.\n" );
+ return 0;
+ }
+ if ( Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "The AIG subgraph recording is already started.\n" );
+ return 0;
+ }
+ if ( pNtk && !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" );
+ return 0;
+ }
+ Abc_NtkRecStart( pNtk, nVars, nCuts );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_start [-K num] [-C num] [-h]\n" );
+ fprintf( pErr, "\t starts recording AIG subgraphs (should be called for\n" );
+ fprintf( pErr, "\t an empty network or after reading in a previous record)\n" );
+ fprintf( pErr, "\t-K num : the largest number of inputs [default = %d]\n", nVars );
+ fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecStop( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "This command works only after calling \"rec_start\".\n" );
+ return 0;
+ }
+ Abc_NtkRecStop();
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_stop [-h]\n" );
+ fprintf( pErr, "\t cleans the internal storage for AIG subgraphs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecAdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works for AIGs.\n" );
+ return 0;
+ }
+ if ( !Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "This command works for AIGs after calling \"rec_start\".\n" );
+ return 0;
+ }
+ Abc_NtkRecAdd( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_add [-h]\n" );
+ fprintf( pErr, "\t adds subgraphs from the current network to the set\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecPs( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" );
+ return 0;
+ }
+ Abc_NtkRecPs();
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_ps [-h]\n" );
+ fprintf( pErr, "\t prints statistics about the recorded AIG subgraphs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRecUse( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( !Abc_NtkRecIsRunning() )
+ {
+ fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" );
+ return 0;
+ }
+ // get the new network
+ pNtkRes = Abc_NtkRecUse();
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Transforming internal AIG subgraphs into an AIG with choices has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: rec_use [-h]\n" );
+ fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ char Buffer[100];
+ double DelayTarget;
+ int fRecovery;
+ int fSweep;
+ int fSwitching;
+ int fVerbose;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose );
+ extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ DelayTarget =-1;
+ fRecovery = 1;
+ fSweep = 1;
+ fSwitching = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( DelayTarget <= 0.0 )
+ goto usage;
+ break;
+ case 'a':
+ fRecovery ^= 1;
+ break;
+ case 's':
+ fSweep ^= 1;
+ break;
+ case 'p':
+ fSwitching ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Strashing before mapping has failed.\n" );
+ return 1;
+ }
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Balancing before mapping has failed.\n" );
+ return 1;
+ }
+ fprintf( pOut, "The network was strashed and balanced before mapping.\n" );
+ // get the new network
+ pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ fprintf( pErr, "Mapping has failed.\n" );
+ return 1;
+ }
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ {
+ // get the new network
+ pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Mapping has failed.\n" );
+ return 1;
+ }
+ }
+
+ if ( fSweep )
+ Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 );
+
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ if ( DelayTarget == -1 )
+ sprintf( Buffer, "not used" );
+ else
+ sprintf( Buffer, "%.3f", DelayTarget );
+ fprintf( pErr, "usage: map [-D float] [-aspvh]\n" );
+ fprintf( pErr, "\t performs standard cell mapping of the current network\n" );
+ fprintf( pErr, "\t-D float : sets the global required times [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+ fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" );
+ fprintf( pErr, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkHasMapping(pNtk) )
+ {
+ fprintf( pErr, "Cannot unmap the network that is not mapped.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkMapToSop( pNtk ) )
+ {
+ fprintf( pErr, "Unmapping has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: unmap [-h]\n" );
+ fprintf( pErr, "\t replaces the library gates by the logic nodes represented using SOPs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsSopLogic(pNtk) )
+ {
+ fprintf( pErr, "Can only attach gates if the nodes have SOP representations.\n" );
+ return 1;
+ }
+
+ // get the new network
+ if ( !Abc_NtkAttach( pNtk ) )
+ {
+ fprintf( pErr, "Attaching gates has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: attach [-h]\n" );
+ fprintf( pErr, "\t replaces the SOP functions by the gates from the library\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" );
+ return 1;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkSuperChoice( pNtk );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Superchoicing has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sc [-h]\n" );
+ fprintf( pErr, "\t performs superchoicing\n" );
+ fprintf( pErr, "\t (accumulate: \"r file.blif; rsup; b; sc; f -ac; wb file_sc.blif\")\n" );
+ fprintf( pErr, "\t (map without supergate library: \"r file_sc.blif; ft; map\")\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSuperChoiceLut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int nLutSize;
+ int nCutSizeMax;
+ int fVerbose;
+ extern int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 1;
+ nLutSize = 4;
+ nCutSizeMax = 10;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KNh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nCutSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutSizeMax < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" );
+ return 1;
+ }
+
+ // convert the network into the SOP network
+ pNtkRes = Abc_NtkToLogic( pNtk );
+
+ // get the new network
+ if ( !Abc_NtkSuperChoiceLut( pNtkRes, nLutSize, nCutSizeMax, fVerbose ) )
+ {
+ Abc_NtkDelete( pNtkRes );
+ fprintf( pErr, "Superchoicing has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: scl [-K num] [-N num] [-vh]\n" );
+ fprintf( pErr, "\t performs superchoicing for K-LUTs\n" );
+ fprintf( pErr, "\t (accumulate: \"r file.blif; b; scl; f -ac; wb file_sc.blif\")\n" );
+ fprintf( pErr, "\t (FPGA map: \"r file_sc.blif; ft; read_lut lutlibK; fpga\")\n" );
+ fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize );
+ fprintf( pErr, "\t-N num : the max size of the cut [default = %d]\n", nCutSizeMax );
+ 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_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ char Buffer[100];
+ char LutSize[100];
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fRecovery;
+ int fSwitching;
+ int fLatchPaths;
+ int fVerbose;
+ int nLutSize;
+ float DelayTarget;
+
+ extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fRecovery = 1;
+ fSwitching = 0;
+ fLatchPaths = 0;
+ fVerbose = 0;
+ DelayTarget =-1;
+ nLutSize =-1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "aplvhDK" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'a':
+ fRecovery ^= 1;
+ break;
+ case 'p':
+ fSwitching ^= 1;
+ break;
+ case 'l':
+ fLatchPaths ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( DelayTarget <= 0.0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ // create the new LUT library
+ if ( nLutSize >= 3 && nLutSize <= 10 )
+ Fpga_SetSimpleLutLib( nLutSize );
+/*
+ else
+ {
+ fprintf( pErr, "Cannot perform FPGA mapping with LUT size %d.\n", nLutSize );
+ return 1;
+ }
+*/
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ // strash and balance the network
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Strashing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Balancing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" );
+ // get the new network
+ pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 1;
+ }
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ {
+ // get the new network
+ pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 1;
+ }
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ if ( DelayTarget == -1 )
+ sprintf( Buffer, "best possible" );
+ else
+ sprintf( Buffer, "%.2f", DelayTarget );
+ if ( nLutSize == -1 )
+ sprintf( LutSize, "library" );
+ else
+ sprintf( LutSize, "%d", nLutSize );
+ fprintf( pErr, "usage: fpga [-D float] [-K num] [-aplvh]\n" );
+ fprintf( pErr, "\t performs FPGA mapping of the current network\n" );
+ fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+ fprintf( pErr, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" );
+ fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", fLatchPaths? "yes": "no" );
+ fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 11) [default = %s]%s\n", LutSize, (nLutSize == -1 ? " (type \"print_lut\")" : "") );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : prints the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandFpgaFast( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ char Buffer[100];
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fRecovery;
+ int fVerbose;
+ int nLutSize;
+ float DelayTarget;
+
+ extern Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fRecovery = 1;
+ fVerbose = 0;
+ DelayTarget =-1;
+ nLutSize = 5;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "avhDK" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'a':
+ fRecovery ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( DelayTarget <= 0.0 )
+ goto usage;
+ break;
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLutSize < 0 )
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ // strash and balance the network
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Strashing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Balancing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" );
+ // get the new network
+ pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 1;
+ }
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ {
+ // get the new network
+ pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 1;
+ }
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ if ( DelayTarget == -1 )
+ sprintf( Buffer, "not used" );
+ else
+ sprintf( Buffer, "%.2f", DelayTarget );
+ fprintf( pErr, "usage: ffpga [-K num] [-avh]\n" );
+ fprintf( pErr, "\t performs fast FPGA mapping of the current network\n" );
+ fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+// fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 32) [default = %d]\n", nLutSize );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : prints the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+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;
+ If_Par_t Pars, * pPars = &Pars;
+ int c;
+ 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( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+ pPars->nLutSize = -1;
+ pPars->nCutsMax = 8;
+ pPars->nFlowIters = 1;
+ pPars->nAreaIters = 2;
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 1;//
+ pPars->fArea = 0;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 1;//
+ pPars->fLatchPaths = 0;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = 0;//
+ // internal parameters
+ pPars->fTruth = 0;
+ pPars->nLatches = pNtk? Abc_NtkLatchNum(pNtk) : 0;
+ pPars->fLiftLeaves = 0;
+ pPars->pLutLib = Abc_FrameReadLibLut();
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->pFuncCost = NULL;
+
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADpaflrstvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ 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;
+ // if the LUT size is specified, disable library
+ pPars->pLutLib = NULL;
+ break;
+ 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 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ pPars->nFlowIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nFlowIters < 0 )
+ goto usage;
+ break;
+ case 'A':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ pPars->nAreaIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nAreaIters < 0 )
+ goto usage;
+ break;
+ case '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 'p':
+ pPars->fPreprocess ^= 1;
+ break;
+ case 'a':
+ pPars->fArea ^= 1;
+ break;
+ case 'f':
+ pPars->fFancy ^= 1;
+ break;
+ case 'l':
+ pPars->fLatchPaths ^= 1;
+ break;
+ case 'r':
+ pPars->fExpRed ^= 1;
+ break;
+ case 's':
+ pPars->fSeqMap ^= 1;
+ break;
+ case 't':
+ pPars->fLiftLeaves ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'h':
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( pPars->fSeqMap && pPars->nLatches == 0 )
+ {
+ fprintf( pErr, "The network has no latches. Use combinational mapping instead of sequential.\n" );
+ return 1;
+ }
+
+ if ( pPars->nLutSize == -1 )
+ {
+ if ( pPars->pLutLib == NULL )
+ {
+ fprintf( pErr, "The LUT library is not given.\n" );
+ return 1;
+ }
+ // get LUT size from the library
+ pPars->nLutSize = pPars->pLutLib->LutMax;
+ }
+
+ if ( pPars->nLutSize < 3 || pPars->nLutSize > IF_MAX_LUTSIZE )
+ {
+ fprintf( pErr, "Incorrect LUT size (%d).\n", pPars->nLutSize );
+ return 1;
+ }
+
+ if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) )
+ {
+ fprintf( pErr, "Incorrect number of cuts.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ printf( "Performing FPGA mapping with choices.\n" );
+// printf( "Currently mapping with choices is not enabled.\n" );
+ pPars->fTruth = 1;
+// return 1;
+ }
+
+ if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE )
+ {
+ fprintf( pErr, "Mapping with choices requires computing truth tables. In this case, the LUT size cannot be more than %d.\n", IF_MAX_FUNC_LUTSIZE );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ // strash and balance the network
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Strashing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Balancing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+ fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" );
+ // get the new network
+ pNtkRes = Abc_NtkIf( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 0;
+ }
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ {
+ // get the new network
+ pNtkRes = Abc_NtkIf( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "FPGA mapping has failed.\n" );
+ return 0;
+ }
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ if ( pPars->DelayTarget == -1 )
+ sprintf( Buffer, "best possible" );
+ else
+ sprintf( Buffer, "%.2f", pPars->DelayTarget );
+ if ( pPars->nLutSize == -1 )
+ sprintf( LutSize, "library" );
+ else
+ sprintf( LutSize, "%d", pPars->nLutSize );
+ fprintf( pErr, "usage: if [-K num] [-C num] [-F num] [-A num] [-D float] [-pafrsvh]\n" );
+ fprintf( pErr, "\t performs FPGA technology mapping of the network\n" );
+ fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
+ fprintf( pErr, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
+ fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters );
+ fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters );
+ fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" );
+ fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" );
+// fprintf( pErr, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" );
+ fprintf( pErr, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" );
+ fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" );
+ fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" );
+// fprintf( pErr, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" );
+ 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;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj;
+ int c, i;
+ int fZeros;
+ int fOnes;
+ int fRandom;
+ int fDontCare;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fZeros = 0;
+ fOnes = 0;
+ fRandom = 0;
+ fDontCare = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "zordh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'z':
+ fZeros ^= 1;
+ break;
+ case 'o':
+ fOnes ^= 1;
+ break;
+ case 'r':
+ fRandom ^= 1;
+ break;
+ case 'd':
+ fDontCare ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The current network is combinational.\n" );
+ return 0;
+ }
+
+ if ( fZeros )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_LatchSetInit0( pObj );
+ }
+ else if ( fOnes )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_LatchSetInit1( pObj );
+ }
+ else if ( fRandom )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( rand() & 1 )
+ Abc_LatchSetInit1( pObj );
+ else
+ Abc_LatchSetInit0( pObj );
+ }
+ else if ( fDontCare )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_LatchSetInitDc( pObj );
+ }
+ else
+ printf( "The initial states remain unchanged.\n" );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: init [-zordh]\n" );
+ fprintf( pErr, "\t resets initial states of all latches\n" );
+ fprintf( pErr, "\t-z : set zeros initial states [default = %s]\n", fZeros? "yes": "no" );
+ fprintf( pErr, "\t-o : set ones initial states [default = %s]\n", fOnes? "yes": "no" );
+ fprintf( pErr, "\t-d : set don't-care initial states [default = %s]\n", fDontCare? "yes": "no" );
+ fprintf( pErr, "\t-r : set random initial states [default = %s]\n", fRandom? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandZero( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ extern Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The current network is combinational.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command works only for AIGs.\n" );
+ return 0;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkRestrashZero( pNtk, 0 );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Converting to sequential AIG has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: zero [-h]\n" );
+ fprintf( pErr, "\t converts latches to have const-0 initial value\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandUndc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The current network is combinational.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command works only for logic networks.\n" );
+ return 0;
+ }
+
+ // get the new network
+ Abc_NtkConvertDcLatches( pNtk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: undc [-h]\n" );
+ fprintf( pErr, "\t converts latches with DC init values into free PIs\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nLatches;
+ extern void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nLatches = 5;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nLatches = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLatches < 0 )
+ goto usage;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The current network is combinational.\n" );
+ return 1;
+ }
+
+ // update the network
+ Abc_NtkLatchPipe( pNtk, nLatches );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: pipe [-L num] [-h]\n" );
+ fprintf( pErr, "\t inserts the given number of latches at each PI for pipelining\n" );
+ fprintf( pErr, "\t-L num : the number of latches to insert [default = %d]\n", nLatches );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkLatchNum(pNtk) == 0 )
+ {
+ fprintf( pErr, "The network has no latches.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Conversion to sequential AIG works only for combinational AIGs (run \"strash\").\n" );
+ return 1;
+ }
+
+ // get the new network
+// pNtkRes = Abc_NtkAigToSeq( pNtk );
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Converting to sequential AIG has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: seq [-h]\n" );
+ fprintf( pErr, "\t converts AIG into sequential AIG\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fShare;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fShare = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 's':
+ fShare ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+/*
+ if ( !Abc_NtkIsSeq(pNtk) )
+ {
+ fprintf( pErr, "Conversion to combinational AIG works only for sequential AIG (run \"seq\").\n" );
+ return 1;
+ }
+*/
+ // share the latches on the fanout edges
+// if ( fShare )
+// Seq_NtkShareFanouts(pNtk);
+
+ // get the new network
+// pNtkRes = Abc_NtkSeqToLogicSop( pNtk );
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Converting sequential AIG into an SOP logic network has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: unseq [-sh]\n" );
+ fprintf( pErr, "\t converts sequential AIG into an SOP logic network\n" );
+ fprintf( pErr, "\t-s : toggle sharing latches [default = %s]\n", fShare? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c, nMaxIters;
+ int fForward;
+ int fBackward;
+ int fOneStep;
+ int fVerbose;
+ int Mode;
+ extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Mode = 5;
+ fForward = 0;
+ fBackward = 0;
+ fOneStep = 0;
+ fVerbose = 0;
+ nMaxIters = 15;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Mfbsvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ Mode = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Mode < 0 )
+ goto usage;
+ break;
+ case 'f':
+ fForward ^= 1;
+ break;
+ case 'b':
+ fBackward ^= 1;
+ break;
+ case 's':
+ fOneStep ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( fForward && fBackward )
+ {
+ fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "The network has no latches. Retiming is not performed.\n" );
+ 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) )
+ {
+ fprintf( pErr, "Retiming with choice nodes is not implemented.\n" );
+ return 0;
+ }
+ // convert the network into an SOP network
+ pNtkRes = Abc_NtkToLogic( pNtk );
+ // perform the retiming
+ Abc_NtkRetime( pNtkRes, Mode, fForward, fBackward, fOneStep, fVerbose );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+ }
+
+ // get the network in the SOP form
+ if ( !Abc_NtkToSop(pNtk, 0) )
+ {
+ printf( "Converting to SOPs has failed.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "The network is not a logic network. Retiming is not performed.\n" );
+ return 0;
+ }
+
+ // perform the retiming
+ Abc_NtkRetime( pNtk, Mode, fForward, fBackward, fOneStep, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: retime [-M num] [-fbvh]\n" );
+ fprintf( pErr, "\t retimes the current network using one of the algorithms:\n" );
+ fprintf( pErr, "\t 1: most forward retiming\n" );
+ fprintf( pErr, "\t 2: most backward retiming\n" );
+ 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" );
+ fprintf( pErr, "\t-s : enables retiming one step only in mode 4 [default = %s]\n", fOneStep? "yes": "no" );
+ fprintf( pErr, "\t-v : enables verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+// fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
+// fprintf( pErr, "\t-f : toggle forward retiming (for AIGs) [default = %s]\n", fForward? "yes": "no" );
+// fprintf( pErr, "\t-b : toggle backward retiming (for AIGs) [default = %s]\n", fBackward? "yes": "no" );
+// fprintf( pErr, "\t-i : toggle computation of initial state [default = %s]\n", fInitial? "yes": "no" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+ int c, nMaxIters;
+ int fVerbose;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nMaxIters = 15;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxIters < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkHasAig(pNtk) )
+ {
+/*
+ // quit if there are choice nodes
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" );
+ return 0;
+ }
+*/
+// if ( Abc_NtkIsStrash(pNtk) )
+// pNtkNew = Abc_NtkAigToSeq(pNtk);
+// else
+// pNtkNew = Abc_NtkDup(pNtk);
+ pNtkNew = NULL;
+ }
+ else
+ {
+ // strash and balance the network
+ pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Strashing before FPGA mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Balancing before FPGA mapping has failed.\n" );
+ return 1;
+ }
+
+ // convert into a sequential AIG
+// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew );
+ pNtkNew = NULL;
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Converting into a seq AIG before FPGA mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ fprintf( pOut, "The network was strashed and balanced before FPGA mapping/retiming.\n" );
+ }
+
+ // get the new network
+// pNtkRes = Seq_NtkFpgaMapRetime( pNtkNew, nMaxIters, fVerbose );
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+// fprintf( pErr, "Sequential FPGA mapping has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return 0;
+ }
+ Abc_NtkDelete( pNtkNew );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sfpga [-I num] [-vh]\n" );
+ fprintf( pErr, "\t performs integrated sequential FPGA mapping/retiming\n" );
+ fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes;
+ int c, nMaxIters;
+ int fVerbose;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nMaxIters = 15;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxIters < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkHasAig(pNtk) )
+ {
+/*
+ // quit if there are choice nodes
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" );
+ return 0;
+ }
+*/
+// if ( Abc_NtkIsStrash(pNtk) )
+// pNtkNew = Abc_NtkAigToSeq(pNtk);
+// else
+// pNtkNew = Abc_NtkDup(pNtk);
+ pNtkNew = NULL;
+ }
+ else
+ {
+ // strash and balance the network
+ pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Strashing before SC mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Balancing before SC mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ // convert into a sequential AIG
+// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew );
+ pNtkNew = NULL;
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtkNew == NULL )
+ {
+ fprintf( pErr, "Converting into a seq AIG before SC mapping/retiming has failed.\n" );
+ return 1;
+ }
+
+ fprintf( pOut, "The network was strashed and balanced before SC mapping/retiming.\n" );
+ }
+
+ // get the new network
+// pNtkRes = Seq_MapRetime( pNtkNew, nMaxIters, fVerbose );
+ pNtkRes = NULL;
+ if ( pNtkRes == NULL )
+ {
+// fprintf( pErr, "Sequential FPGA mapping has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return 0;
+ }
+ Abc_NtkDelete( pNtkNew );
+
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: smap [-I num] [-vh]\n" );
+ fprintf( pErr, "\t performs integrated sequential standard-cell mapping/retiming\n" );
+ fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int nFramesP;
+ int nFramesK;
+ int nMaxImps;
+ int fUseImps;
+ int fRewrite;
+ int fLatchCorr;
+ int fWriteImps;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFrames, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFramesP = 0;
+ nFramesK = 1;
+ nMaxImps = 5000;
+ fUseImps = 0;
+ fRewrite = 0;
+ fLatchCorr = 0;
+ fWriteImps = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "PFIirlevh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFramesP = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFramesP < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFramesK = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFramesK <= 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nMaxImps = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxImps <= 0 )
+ goto usage;
+ break;
+ case 'i':
+ fUseImps ^= 1;
+ break;
+ case 'r':
+ fRewrite ^= 1;
+ break;
+ case 'l':
+ fLatchCorr ^= 1;
+ break;
+ case 'e':
+ fWriteImps ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkDarSeqSweep( pNtk, nFramesP, nFramesK, nMaxImps, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Sequential sweeping has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: ssweep [-P num] [-F num] [-I num] [-ilrevh]\n" );
+ fprintf( pErr, "\t performs sequential sweep using K-step induction\n" );
+ fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP );
+ fprintf( pErr, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFramesK );
+ fprintf( pErr, "\t-I num : max number of implications to consider [default = %d]\n", nMaxImps );
+ fprintf( pErr, "\t-i : toggle using implications [default = %s]\n", fUseImps? "yes": "no" );
+ fprintf( pErr, "\t-l : toggle latch correspondence only [default = %s]\n", fLatchCorr? "yes": "no" );
+ fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", fRewrite? "yes": "no" );
+ fprintf( pErr, "\t-e : toggle writing implications as assertions [default = %s]\n", fWriteImps? "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;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int nFramesP;
+ int nConfMax;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFramesP = 0;
+ nConfMax = 10000;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "PCvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFramesP = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFramesP < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfMax < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
+ }
+
+ // get the new network
+ pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Sequential sweeping has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: lcorr [-P num] [-C num] [-vh]\n" );
+ fprintf( pErr, "\t computes latch correspondence using 1-step induction\n" );
+ fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP );
+ fprintf( pErr, "\t-C num : max conflict number when proving latch equivalence [default = %d]\n", nConfMax );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fLatchSweep;
+ int fAutoSweep;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fLatchSweep = 0;
+ fAutoSweep = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ 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;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for structrally hashed networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+ // modify the current network
+ pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchSweep, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Sequential cleanup has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: scleanup [-lvh]\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 stuck-at and identical latches (latch sweep)\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;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCycle( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int fVerbose;
+ extern void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+ extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 100;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSopLogic(pNtk) )
+ {
+ fprintf( pErr, "Only works for strashed networks or logic SOP networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkIsStrash(pNtk) )
+ Abc_NtkCycleInitState( pNtk, nFrames, fVerbose );
+ else
+ Abc_NtkCycleInitStateSop( pNtk, nFrames, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: cycle [-F num] [-vh]\n" );
+ fprintf( pErr, "\t cycles sequiential circuit for the given number of timeframes\n" );
+ fprintf( pErr, "\t to derive a new initial state (which may be on the envelope)\n" );
+ fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandXsim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int fXInputs;
+ int fXState;
+ int fVerbose;
+ extern void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 10;
+ fXInputs = 0;
+ fXState = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fisvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'i':
+ fXInputs ^= 1;
+ break;
+ case 's':
+ fXState ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for strashed networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+ Abc_NtkXValueSimulate( pNtk, nFrames, fXInputs, fXState, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: xsim [-F num] [-isvh]\n" );
+ fprintf( pErr, "\t performs X-valued simulation of the AIG\n" );
+ fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-i : toggle X-valued representation of inputs [default = %s]\n", fXInputs? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle X-valued representation of state [default = %s]\n", fXState? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ char Buffer[16];
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c;
+ int fSat;
+ int fVerbose;
+ int nSeconds;
+ int nPartSize;
+ int nConfLimit;
+ int nInsLimit;
+ int fPartition;
+
+ extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit );
+ extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose );
+ extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose );
+ extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fSat = 0;
+ fVerbose = 0;
+ nSeconds = 20;
+ nPartSize = 0;
+ nConfLimit = 10000;
+ nInsLimit = 0;
+ fPartition = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nSeconds = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nSeconds < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPartSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPartSize < 0 )
+ goto usage;
+ break;
+ case 'p':
+ fPartition ^= 1;
+ break;
+ case 's':
+ fSat ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+
+ // perform equivalence checking
+ if ( fPartition )
+ Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose );
+ else if ( nPartSize )
+ Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose );
+ else if ( fSat )
+ Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit );
+ else
+ Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose );
+
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ return 0;
+
+usage:
+ if ( nPartSize == 0 )
+ strcpy( Buffer, "unused" );
+ else
+ sprintf( Buffer, "%d", nPartSize );
+ fprintf( pErr, "usage: cec [-T num] [-C num] [-I num] [-P num] [-psvh] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs combinational equivalence checking\n" );
+ fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\t-P num : partition size for multi-output networks [default = %s]\n", Buffer );
+ fprintf( pErr, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDCec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c;
+ int fSat;
+ int fVerbose;
+ int nSeconds;
+ int nConfLimit;
+ int nInsLimit;
+ int fPartition;
+ int fMiter;
+
+ extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose );
+ extern int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fPartition, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fSat = 0;
+ fVerbose = 0;
+ nSeconds = 20;
+ nConfLimit = 10000;
+ nInsLimit = 0;
+ fPartition = 0;
+ fMiter = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TCIpmsvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nSeconds = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nSeconds < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'p':
+ fPartition ^= 1;
+ break;
+ case 'm':
+ fMiter ^= 1;
+ break;
+ case 's':
+ fSat ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( fMiter )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk1 = pNtk;
+ fDelete1 = 0;
+ }
+ else
+ {
+ pNtk1 = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ fDelete1 = 1;
+ }
+ pNtk2 = NULL;
+ fDelete2 = 0;
+ }
+ else
+ {
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+ }
+
+ // perform equivalence checking
+ if ( fSat && fMiter )
+ Abc_NtkDSat( pNtk1, nConfLimit, nInsLimit, fVerbose );
+ else
+ Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose );
+
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dcec [-T num] [-C num] [-I num] [-mpsvh] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs combinational equivalence checking\n" );
+ fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\t-m : toggle working on two networks or a miter [default = %s]\n", fMiter? "miter": "two networks" );
+ fprintf( pErr, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle \"SAT only\" (miter) or \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c;
+ int fRetime;
+ int fSat;
+ int fVerbose;
+ int nFrames;
+ int nSeconds;
+ int nConfLimit;
+ int nInsLimit;
+
+ extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames );
+ extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose );
+ extern void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
+
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fRetime = 0; // verification after retiming
+ fSat = 0;
+ fVerbose = 0;
+ nFrames = 5;
+ nSeconds = 20;
+ nConfLimit = 10000;
+ nInsLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsrvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames <= 0 )
+ goto usage;
+ break;
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nSeconds = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nSeconds < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'r':
+ fRetime ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 's':
+ fSat ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+
+ if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+ {
+ printf( "The network has no latches. Used combinational command \"cec\".\n" );
+ return 0;
+ }
+
+ // perform equivalence checking
+ if ( fRetime )
+ Abc_NtkSecRetime( pNtk1, pNtk2 );
+ else if ( fSat )
+ Abc_NtkSecSat( pNtk1, pNtk2, nConfLimit, nInsLimit, nFrames );
+ else
+ Abc_NtkSecFraig( pNtk1, pNtk2, nSeconds, nFrames, fVerbose );
+
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sec [-F num] [-T num] [-C num] [-I num] [-srvh] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs bounded sequential equivalence checking\n" );
+ fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
+ fprintf( pErr, "\t-r : toggles retiming verification [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c;
+ int fRetimeFirst;
+ int fVerbose;
+ int fVeryVerbose;
+ int nFrames;
+
+ extern int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames =16;
+ fRetimeFirst = 1;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'r':
+ fRetimeFirst ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+
+ if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+ {
+ printf( "The network has no latches. Used combinational command \"cec\".\n" );
+ return 0;
+ }
+
+ // perform verification
+ Abc_NtkDarSec( pNtk1, pNtk2, nFrames, fRetimeFirst, fVerbose, fVeryVerbose );
+
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dsec [-K num] [-rwvh] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs inductive sequential equivalence checking\n" );
+ fprintf( pErr, "\t-K num : the limit on the depth of induction [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
+ fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
+ fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fRetimeFirst;
+ int fVerbose;
+ int fVeryVerbose;
+ int nFrames;
+
+ extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 16;
+ fRetimeFirst = 1;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'r':
+ fRetimeFirst ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( Abc_NtkLatchNum(pNtk) == 0 )
+ {
+ printf( "The network has no latches. Used combinational command \"iprove\".\n" );
+ return 0;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
+ }
+
+ // perform verification
+ Abc_NtkDarProve( pNtk, nFrames, fRetimeFirst, fVerbose, fVeryVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dprove [-K num] [-rwvh]\n" );
+ fprintf( pErr, "\t performs SEC on the sequential miter\n" );
+ fprintf( pErr, "\t-K num : the limit on the depth of induction [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int RetValue;
+ int fVerbose;
+ int nConfLimit;
+ int nInsLimit;
+ int clk;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ nConfLimit = 100000;
+ nInsLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
+ return 0;
+ }
+
+ clk = clock();
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL );
+ }
+ else
+ {
+ assert( Abc_NtkIsLogic(pNtk) );
+ Abc_NtkToBdd( pNtk );
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL );
+ }
+
+ // verify that the pattern is correct
+ if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 )
+ {
+ //int i;
+ //Abc_Obj_t * pObj;
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" );
+ free( pSimInfo );
+ /*
+ // print model
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ printf( "%d", (int)(pNtk->pModel[i] > 0) );
+ if ( i == 70 )
+ break;
+ }
+ printf( "\n" );
+ */
+ }
+
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+ PRT( "Time", clock() - clk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sat [-C num] [-I num] [-vh]\n" );
+ fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" );
+ fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int RetValue;
+ int fVerbose;
+ int nConfLimit;
+ int nInsLimit;
+ int clk;
+
+ extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose );
+
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ nConfLimit = 100000;
+ nInsLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nInsLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nInsLimit < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
+ return 0;
+ }
+ if ( Abc_NtkPoNum(pNtk) != 1 )
+ {
+ fprintf( stdout, "Currently expects a single-output miter.\n" );
+ return 0;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+
+ clk = clock();
+ RetValue = Abc_NtkDSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose );
+ // verify that the pattern is correct
+ if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 )
+ {
+ //int i;
+ //Abc_Obj_t * pObj;
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" );
+ free( pSimInfo );
+ /*
+ // print model
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ printf( "%d", (int)(pNtk->pModel[i] > 0) );
+ if ( i == 70 )
+ break;
+ }
+ printf( "\n" );
+ */
+ }
+
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+ PRT( "Time", clock() - clk );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: dsat [-C num] [-I num] [-vh]\n" );
+ fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" );
+ fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ Prove_Params_t Params, * pParams = &Params;
+ int c, clk, RetValue;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Prove_ParamsSetDefault( pParams );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NCFLIrfbvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nItersMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nItersMax < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nMiteringLimitStart < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nFraigingLimitStart < 0 )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nMiteringLimitLast < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pParams->nTotalInspectLimit < 0 )
+ goto usage;
+ break;
+ case 'r':
+ pParams->fUseRewriting ^= 1;
+ break;
+ case 'f':
+ pParams->fUseFraiging ^= 1;
+ break;
+ case 'b':
+ pParams->fUseBdds ^= 1;
+ break;
+ case 'v':
+ pParams->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
+ return 0;
+ }
+ if ( Abc_NtkCoNum(pNtk) != 1 )
+ {
+ fprintf( stdout, "Currently can only solve the miter with one output.\n" );
+ return 0;
+ }
+ clk = clock();
+
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkTemp = Abc_NtkDup( pNtk );
+ else
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
+
+ RetValue = Abc_NtkMiterProve( &pNtkTemp, pParams );
+
+ // verify that the pattern is correct
+ if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ free( pSimInfo );
+ }
+
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+
+ PRT( "Time", clock() - clk );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: prove [-N num] [-C num] [-F num] [-L num] [-I num] [-rfbvh]\n" );
+ fprintf( pErr, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" );
+ fprintf( pErr, "\t replaces the current network by the cone modified by rewriting\n" );
+ fprintf( pErr, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax );
+ fprintf( pErr, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart );
+ fprintf( pErr, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart );
+ fprintf( pErr, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast );
+ fprintf( pErr, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit );
+ fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" );
+ fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" );
+ fprintf( pErr, "\t-b : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ extern void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) );
+ extern int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command is applicable to logic networks.\n" );
+ return 1;
+ }
+
+ Abc_NtkAutoDebug( pNtk, Abc_NtkRetimeDebug );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: debug [-h]\n" );
+ fprintf( pErr, "\t performs automated debugging of the given procedure\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command is applicable to AIGs.\n" );
+ return 1;
+ }
+/*
+ Abc_HManStart();
+ if ( !Abc_HManPopulate( pNtk ) )
+ {
+ fprintf( pErr, "Failed to start the tracing database.\n" );
+ return 1;
+ }
+*/
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: trace_start [-h]\n" );
+ fprintf( pErr, "\t starts verification tracing\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command is applicable to AIGs.\n" );
+ return 1;
+ }
+/*
+ if ( !Abc_HManIsRunning(pNtk) )
+ {
+ fprintf( pErr, "The tracing database is not available.\n" );
+ return 1;
+ }
+
+ if ( !Abc_HManVerify( 1, pNtk->Id ) )
+ fprintf( pErr, "Verification failed.\n" );
+ Abc_HManStop();
+*/
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: trace_check [-h]\n" );
+ fprintf( pErr, "\t checks the current network using verification trace\n" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcAttach.c b/src/base/abci/abcAttach.c
new file mode 100644
index 00000000..d5d2aa16
--- /dev/null
+++ b/src/base/abci/abcAttach.c
@@ -0,0 +1,404 @@
+/**CFile****************************************************************
+
+ FileName [abcAttach.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Attaches the library gates to the current network.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcAttach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "main.h"
+#include "mio.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define ATTACH_FULL (~((unsigned)0))
+#define ATTACH_MASK(n) ((~((unsigned)0)) >> (32-(n)))
+
+static void Abc_AttachSetupTruthTables( unsigned uTruths[][2] );
+static void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthNode );
+static Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm );
+static int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode );
+static int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] );
+static void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm );
+
+static char ** s_pPerms = NULL;
+static int s_nPerms;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Attaches gates from the current library to the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkAttach( Abc_Ntk_t * pNtk )
+{
+ Mio_Library_t * pGenlib;
+ unsigned ** puTruthGates;
+ unsigned uTruths[6][2];
+ Abc_Obj_t * pNode;
+ Mio_Gate_t ** ppGates;
+ int nGates, nFanins, i;
+
+ assert( Abc_NtkIsSopLogic(pNtk) );
+
+ // check that the library is available
+ pGenlib = Abc_FrameReadLibGen();
+ if ( pGenlib == NULL )
+ {
+ printf( "The current library is not available.\n" );
+ return 0;
+ }
+
+ // start the truth tables
+ Abc_AttachSetupTruthTables( uTruths );
+
+ // collect all the gates
+ ppGates = Mio_CollectRoots( pGenlib, 6, (float)1.0e+20, 1, &nGates );
+
+ // derive the gate truth tables
+ puTruthGates = ALLOC( unsigned *, nGates );
+ puTruthGates[0] = ALLOC( unsigned, 2 * nGates );
+ for ( i = 1; i < nGates; i++ )
+ puTruthGates[i] = puTruthGates[i-1] + 2;
+ for ( i = 0; i < nGates; i++ )
+ Mio_DeriveTruthTable( ppGates[i], uTruths, Mio_GateReadInputs(ppGates[i]), 6, puTruthGates[i] );
+
+ // assign the gates to pNode->pCopy
+ Abc_NtkCleanCopy( pNtk );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ nFanins = Abc_ObjFaninNum(pNode);
+ if ( nFanins == 0 )
+ {
+ if ( Abc_SopIsConst1(pNode->pData) )
+ pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst1(pGenlib);
+ else
+ pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst0(pGenlib);
+ }
+ else if ( nFanins == 1 )
+ {
+ if ( Abc_SopIsBuf(pNode->pData) )
+ pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadBuf(pGenlib);
+ else
+ pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadInv(pGenlib);
+ }
+ else if ( nFanins > 6 )
+ {
+ printf( "Cannot attach gate with more than 6 inputs to node %s.\n", Abc_ObjName(pNode) );
+ free( puTruthGates[0] );
+ free( puTruthGates );
+ free( ppGates );
+ return 0;
+ }
+ else if ( !Abc_NodeAttach( pNode, ppGates, puTruthGates, nGates, uTruths ) )
+ {
+ printf( "Could not attach the library gate to node %s.\n", Abc_ObjName(pNode) );
+ free( puTruthGates[0] );
+ free( puTruthGates );
+ free( ppGates );
+ return 0;
+ }
+ }
+ free( puTruthGates[0] );
+ free( puTruthGates );
+ free( ppGates );
+ FREE( s_pPerms );
+
+ // perform the final transformation
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( pNode->pCopy == NULL )
+ {
+ printf( "Some elementary gates (constant, buffer, or inverter) are missing in the library.\n" );
+ return 0;
+ }
+ }
+
+ // replace SOP representation by the gate representation
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->pData = pNode->pCopy, pNode->pCopy = NULL;
+ pNtk->ntkFunc = ABC_FUNC_MAP;
+ Extra_MmFlexStop( pNtk->pManFunc );
+ pNtk->pManFunc = pGenlib;
+
+ printf( "Library gates are successfully attached to the nodes.\n" );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkAttach: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] )
+{
+ int Perm[10];
+ int pTempInts[10];
+ unsigned uTruthNode[2];
+ Abc_Obj_t * pFanin;
+ Mio_Gate_t * pGate;
+ int nFanins, i;
+
+ // compute the node's truth table
+ Abc_AttachComputeTruth( pNode->pData, uTruths, uTruthNode );
+ // find the matching gate and permutation
+ pGate = Abc_AttachFind( ppGates, puTruthGates, nGates, uTruthNode, Perm );
+ if ( pGate == NULL )
+ return 0;
+ // permute the fanins
+ nFanins = Abc_ObjFaninNum(pNode);
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ pTempInts[i] = pFanin->Id;
+ for ( i = 0; i < nFanins; i++ )
+ pNode->vFanins.pArray[Perm[i]] = pTempInts[i];
+ // set the gate
+ pNode->pCopy = (Abc_Obj_t *)pGate;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_AttachSetupTruthTables( unsigned uTruths[][2] )
+{
+ int m, v;
+ for ( v = 0; v < 5; v++ )
+ uTruths[v][0] = 0;
+ // set up the truth tables
+ for ( m = 0; m < 32; m++ )
+ for ( v = 0; v < 5; v++ )
+ if ( m & (1 << v) )
+ uTruths[v][0] |= (1 << m);
+ // make adjustments for the case of 6 variables
+ for ( v = 0; v < 5; v++ )
+ uTruths[v][1] = uTruths[v][0];
+ uTruths[5][0] = 0;
+ uTruths[5][1] = ATTACH_FULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the truth table of the node's cover.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthRes )
+{
+// Mvc_Cube_t * pCube;
+ unsigned uSignCube[2];
+ int Value;
+// int nInputs = pCover->nBits/2;
+ int nInputs = 6;
+ int nFanins = Abc_SopGetVarNum(pSop);
+ char * pCube;
+ int k;
+
+ // make sure that the number of input truth tables in equal to the number of gate inputs
+ assert( nInputs < 7 );
+
+ // clean the resulting truth table
+ uTruthRes[0] = 0;
+ uTruthRes[1] = 0;
+ if ( nInputs < 6 )
+ {
+ // consider the case when only one unsigned can be used
+// Mvc_CoverForEachCube( pCover, pCube )
+ Abc_SopForEachCube( pSop, nFanins, pCube )
+ {
+ uSignCube[0] = ATTACH_FULL;
+// Mvc_CubeForEachVarValue( pCover, pCube, Var, Value )
+ Abc_CubeForEachVar( pCube, Value, k )
+ {
+ if ( Value == '0' )
+ uSignCube[0] &= ~uTruthsIn[k][0];
+ else if ( Value == '1' )
+ uSignCube[0] &= uTruthsIn[k][0];
+ }
+ uTruthRes[0] |= uSignCube[0];
+ }
+ if ( Abc_SopGetPhase(pSop) == 0 )
+ uTruthRes[0] = ~uTruthRes[0];
+ if ( nInputs < 5 )
+ uTruthRes[0] &= ATTACH_MASK(1<<nInputs);
+ }
+ else
+ {
+ // consider the case when two unsigneds should be used
+// Mvc_CoverForEachCube( pCover, pCube )
+ Abc_SopForEachCube( pSop, nFanins, pCube )
+ {
+ uSignCube[0] = ATTACH_FULL;
+ uSignCube[1] = ATTACH_FULL;
+// Mvc_CubeForEachVarValue( pCover, pCube, Var, Value )
+ Abc_CubeForEachVar( pCube, Value, k )
+ {
+ if ( Value == '0' )
+ {
+ uSignCube[0] &= ~uTruthsIn[k][0];
+ uSignCube[1] &= ~uTruthsIn[k][1];
+ }
+ else if ( Value == '1' )
+ {
+ uSignCube[0] &= uTruthsIn[k][0];
+ uSignCube[1] &= uTruthsIn[k][1];
+ }
+ }
+ uTruthRes[0] |= uSignCube[0];
+ uTruthRes[1] |= uSignCube[1];
+ }
+
+ // complement if the SOP is complemented
+ if ( Abc_SopGetPhase(pSop) == 0 )
+ {
+ uTruthRes[0] = ~uTruthRes[0];
+ uTruthRes[1] = ~uTruthRes[1];
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the gate by truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm )
+{
+ unsigned uTruthPerm[2];
+ int i, v, iNum;
+
+ // try the gates without permutation
+ if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthNode )) >= 0 )
+ {
+ for ( v = 0; v < 6; v++ )
+ Perm[v] = v;
+ return ppGates[iNum];
+ }
+ // get permutations
+ if ( s_pPerms == NULL )
+ {
+ s_pPerms = Extra_Permutations( 6 );
+ s_nPerms = Extra_Factorial( 6 );
+ }
+ // try permutations
+ for ( i = 0; i < s_nPerms; i++ )
+ {
+ Abc_TruthPermute( s_pPerms[i], 6, uTruthNode, uTruthPerm );
+ if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthPerm )) >= 0 )
+ {
+ for ( v = 0; v < 6; v++ )
+ Perm[v] = (int)s_pPerms[i][v];
+ return ppGates[iNum];
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the gate by truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode )
+{
+ int i;
+ for ( i = 0; i < nGates; i++ )
+ if ( puTruthGates[i][0] == uTruthNode[0] && puTruthGates[i][1] == uTruthNode[1] )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Permutes the 6-input truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm )
+{
+ int nMints, iMintPerm, iMint, v;
+ uTruthPerm[0] = uTruthPerm[1] = 0;
+ nMints = (1 << nVars);
+ for ( iMint = 0; iMint < nMints; iMint++ )
+ {
+ if ( (uTruthNode[iMint>>5] & (1 << (iMint&31))) == 0 )
+ continue;
+ iMintPerm = 0;
+ for ( v = 0; v < nVars; v++ )
+ if ( iMint & (1 << v) )
+ iMintPerm |= (1 << pPerm[v]);
+ uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcAuto.c b/src/base/abci/abcAuto.c
new file mode 100644
index 00000000..40212c17
--- /dev/null
+++ b/src/base/abci/abcAuto.c
@@ -0,0 +1,239 @@
+/**CFile****************************************************************
+
+ FileName [abcAuto.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Computation of autosymmetries.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcAuto.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive );
+static void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose )
+{
+ DdManager * dd; // the BDD manager used to hold shared BDDs
+ DdNode ** pbGlobal; // temporary storage for global BDDs
+ char ** pInputNames; // pointers to the CI names
+ char ** pOutputNames; // pointers to the CO names
+ int nOutputs, nInputs, i;
+ Vec_Ptr_t * vFuncsGlob;
+ Abc_Obj_t * pObj;
+
+ // compute the global BDDs
+ if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose) == NULL )
+ return;
+
+ // get information about the network
+ nInputs = Abc_NtkCiNum(pNtk);
+ nOutputs = Abc_NtkCoNum(pNtk);
+// dd = pNtk->pManGlob;
+ dd = Abc_NtkGlobalBddMan( pNtk );
+
+ // complement the global functions
+ vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) );
+ pbGlobal = (DdNode **)Vec_PtrArray( vFuncsGlob );
+
+ // get the network names
+ pInputNames = Abc_NtkCollectCioNames( pNtk, 0 );
+ pOutputNames = Abc_NtkCollectCioNames( pNtk, 1 );
+
+ // print the size of the BDDs
+ if ( fVerbose )
+ printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+ // allocate additional variables
+ for ( i = 0; i < nInputs; i++ )
+ Cudd_bddNewVar( dd );
+ assert( Cudd_ReadSize(dd) == 2 * nInputs );
+
+ // create ZDD variables in the manager
+ Cudd_zddVarsFromBddVars( dd, 2 );
+
+ // perform the analysis of the primary output functions for auto-symmetry
+ if ( Output == -1 )
+ Abc_NtkAutoPrintAll( dd, nInputs, pbGlobal, nOutputs, pInputNames, pOutputNames, fNaive );
+ else
+ Abc_NtkAutoPrintOne( dd, nInputs, pbGlobal, Output, pInputNames, pOutputNames, fNaive );
+
+ // deref the PO functions
+// Abc_NtkFreeGlobalBdds( pNtk );
+ // stop the global BDD manager
+// Extra_StopManager( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
+ free( pInputNames );
+ free( pOutputNames );
+ Vec_PtrFree( vFuncsGlob );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive )
+{
+ DdNode * bSpace1, * bSpace2, * bCanVars, * bReduced, * zEquations;
+ double nMints;
+ int nSupp, SigCounter, o;
+
+ int nAutos;
+ int nAutoSyms;
+ int nAutoSymsMax;
+ int nAutoSymsMaxSupp;
+ int nAutoSymOuts;
+ int nSuppSizeMax;
+ int clk;
+
+ nAutoSymOuts = 0;
+ nAutoSyms = 0;
+ nAutoSymsMax = 0;
+ nAutoSymsMaxSupp = 0;
+ nSuppSizeMax = 0;
+ clk = clock();
+
+ SigCounter = 0;
+ for ( o = 0; o < nOutputs; o++ )
+ {
+// bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[o] ); Cudd_Ref( bSpace1 );
+ bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[o], pbOutputs[o] ); Cudd_Ref( bSpace1 );
+ bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars );
+ bReduced = Extra_bddSpaceReduce( dd, pbOutputs[o], bCanVars ); Cudd_Ref( bReduced );
+ zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations );
+
+ nSupp = Cudd_SupportSize( dd, bSpace1 );
+ nMints = Cudd_CountMinterm( dd, bSpace1, nSupp );
+ nAutos = Extra_Base2LogDouble(nMints);
+ printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", o, nSupp, nAutos );
+
+ if ( nAutos > 0 )
+ {
+ nAutoSymOuts++;
+ nAutoSyms += nAutos;
+ if ( nAutoSymsMax < nAutos )
+ {
+ nAutoSymsMax = nAutos;
+ nAutoSymsMaxSupp = nSupp;
+ }
+ }
+ if ( nSuppSizeMax < nSupp )
+ nSuppSizeMax = nSupp;
+
+
+//PRB( dd, bCanVars );
+//PRB( dd, bReduced );
+//Cudd_PrintMinterm( dd, bReduced );
+//printf( "The equations are:\n" );
+//Cudd_zddPrintCover( dd, zEquations );
+//printf( "\n" );
+//fflush( stdout );
+
+ bSpace2 = Extra_bddSpaceFromMatrixPos( dd, zEquations ); Cudd_Ref( bSpace2 );
+//PRB( dd, bSpace1 );
+//PRB( dd, bSpace2 );
+ if ( bSpace1 != bSpace2 )
+ printf( "Spaces are NOT EQUAL!\n" );
+// else
+// printf( "Spaces are equal.\n" );
+
+ Cudd_RecursiveDeref( dd, bSpace1 );
+ Cudd_RecursiveDeref( dd, bSpace2 );
+ Cudd_RecursiveDeref( dd, bCanVars );
+ Cudd_RecursiveDeref( dd, bReduced );
+ Cudd_RecursiveDerefZdd( dd, zEquations );
+ }
+
+ printf( "The cumulative statistics for all outputs:\n" );
+ printf( "Ins=%3d ", nInputs );
+ printf( "InMax=%3d ", nSuppSizeMax );
+ printf( "Outs=%3d ", nOutputs );
+ printf( "Auto=%3d ", nAutoSymOuts );
+ printf( "SumK=%3d ", nAutoSyms );
+ printf( "KMax=%2d ", nAutoSymsMax );
+ printf( "Supp=%3d ", nAutoSymsMaxSupp );
+ printf( "Time=%4.2f ", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive )
+{
+ DdNode * bSpace1, * bCanVars, * bReduced, * zEquations;
+ double nMints;
+ int nSupp, SigCounter;
+ int nAutos;
+
+ SigCounter = 0;
+ bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[Output] ); Cudd_Ref( bSpace1 );
+// bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[Output], pbOutputs[Output] ); Cudd_Ref( bSpace1 );
+ bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars );
+ bReduced = Extra_bddSpaceReduce( dd, pbOutputs[Output], bCanVars ); Cudd_Ref( bReduced );
+ zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations );
+
+ nSupp = Cudd_SupportSize( dd, bSpace1 );
+ nMints = Cudd_CountMinterm( dd, bSpace1, nSupp );
+ nAutos = Extra_Base2LogDouble(nMints);
+ printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", Output, nSupp, nAutos );
+
+ Cudd_RecursiveDeref( dd, bSpace1 );
+ Cudd_RecursiveDeref( dd, bCanVars );
+ Cudd_RecursiveDeref( dd, bReduced );
+ Cudd_RecursiveDerefZdd( dd, zEquations );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c
new file mode 100644
index 00000000..f9b3384e
--- /dev/null
+++ b/src/base/abci/abcBalance.c
@@ -0,0 +1,613 @@
+/**CFile****************************************************************
+
+ FileName [abcBalance.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Performs global balancing of the AIG by the number of levels.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel );
+static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel );
+static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, bool fSelective );
+static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective );
+static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk );
+static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Balances the AIG network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel )
+{
+ extern void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew );
+ Abc_Ntk_t * pNtkAig;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // compute the required times
+ if ( fSelective )
+ {
+ Abc_NtkStartReverseLevels( pNtk, 0 );
+ Abc_NtkMarkCriticalNodes( pNtk );
+ }
+ // perform balancing
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer HAIG
+ Abc_NtkHaigTranfer( pNtk, pNtkAig );
+ // perform balancing
+ Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel );
+ Abc_NtkFinalize( pNtk, pNtkAig );
+ // undo the required times
+ if ( fSelective )
+ {
+ Abc_NtkStopReverseLevels( pNtk );
+ Abc_NtkCleanMarkA( pNtk );
+ }
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkBalance: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Balances the AIG network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel )
+{
+ int fCheck = 1;
+ ProgressBar * pProgress;
+ Vec_Vec_t * vStorage;
+ Abc_Obj_t * pNode, * pDriver;
+ int i;
+
+ // set the level of PIs of AIG according to the arrival times of the old network
+ Abc_NtkSetNodeLevelsArrival( pNtk );
+ // allocate temporary storage for supergates
+ vStorage = Vec_VecStart( 10 );
+ // perform balancing of POs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // strash the driver node
+ pDriver = Abc_ObjFanin0(pNode);
+ Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_VecFree( vStorage );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the left bound on the next candidate to be paired.]
+
+ Description [The nodes in the array are in the decreasing order of levels.
+ The last node in the array has the smallest level. By default it would be paired
+ with the next node on the left. However, it may be possible to pair it with some
+ other node on the left, in such a way that the new node is shared. This procedure
+ finds the index of the left-most node, which can be paired with the last node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
+{
+ Abc_Obj_t * pNodeRight, * pNodeLeft;
+ int Current;
+ // if two or less nodes, pair with the first
+ if ( Vec_PtrSize(vSuper) < 3 )
+ return 0;
+ // set the pointer to the one before the last
+ Current = Vec_PtrSize(vSuper) - 2;
+ pNodeRight = Vec_PtrEntry( vSuper, Current );
+ // go through the nodes to the left of this one
+ for ( Current--; Current >= 0; Current-- )
+ {
+ // get the next node on the left
+ pNodeLeft = Vec_PtrEntry( vSuper, Current );
+ // if the level of this node is different, quit the loop
+ if ( Abc_ObjRegular(pNodeLeft)->Level != Abc_ObjRegular(pNodeRight)->Level )
+ break;
+ }
+ Current++;
+ // get the node, for which the equality holds
+ pNodeLeft = Vec_PtrEntry( vSuper, Current );
+ assert( Abc_ObjRegular(pNodeLeft)->Level == Abc_ObjRegular(pNodeRight)->Level );
+ return Current;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves closer to the end the node that is best for sharing.]
+
+ Description [If there is no node with sharing, randomly chooses one of
+ the legal nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBound )
+{
+ Abc_Obj_t * pNode1, * pNode2, * pNode3;
+ int RightBound, i;
+ // get the right bound
+ RightBound = Vec_PtrSize(vSuper) - 2;
+ assert( LeftBound <= RightBound );
+ if ( LeftBound == RightBound )
+ return;
+ // get the two last nodes
+ pNode1 = Vec_PtrEntry( vSuper, RightBound + 1 );
+ pNode2 = Vec_PtrEntry( vSuper, RightBound );
+ // find the first node that can be shared
+ for ( i = RightBound; i >= LeftBound; i-- )
+ {
+ pNode3 = Vec_PtrEntry( vSuper, i );
+ if ( Abc_AigAndLookup( pNtkNew->pManFunc, pNode1, pNode3 ) )
+ {
+ if ( pNode3 == pNode2 )
+ return;
+ Vec_PtrWriteEntry( vSuper, i, pNode2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
+ return;
+ }
+ }
+/*
+ // we did not find the node to share, randomize choice
+ {
+ int Choice = rand() % (RightBound - LeftBound + 1);
+ pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
+ if ( pNode3 == pNode2 )
+ return;
+ Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Rebalances the multi-input node rooted at pNodeOld.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel )
+{
+ Abc_Aig_t * pMan = pNtkNew->pManFunc;
+ Abc_Obj_t * pNodeNew, * pNode1, * pNode2;
+ Vec_Ptr_t * vSuper;
+ int i, LeftBound;
+ assert( !Abc_ObjIsComplement(pNodeOld) );
+ // return if the result if known
+ if ( pNodeOld->pCopy )
+ return pNodeOld->pCopy;
+ assert( Abc_ObjIsNode(pNodeOld) );
+ // get the implication supergate
+// Abc_NodeBalanceConeExor( pNodeOld );
+ vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, Level, fDuplicate, fSelective );
+ if ( vSuper->nSize == 0 )
+ { // it means that the supergate contains two nodes in the opposite polarity
+ pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pNtkNew));
+ return pNodeOld->pCopy;
+ }
+ // for each old node, derive the new well-balanced node
+ for ( i = 0; i < vSuper->nSize; i++ )
+ {
+ pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel );
+ vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) );
+ }
+ if ( vSuper->nSize < 2 )
+ printf( "BUG!\n" );
+ // sort the new nodes by level in the decreasing order
+ Vec_PtrSort( vSuper, Abc_NodeCompareLevelsDecrease );
+ // balance the nodes
+ assert( vSuper->nSize > 1 );
+ while ( vSuper->nSize > 1 )
+ {
+ // find the left bound on the node to be paired
+ LeftBound = (!fUpdateLevel)? 0 : Abc_NodeBalanceFindLeft( vSuper );
+ // find the node that can be shared (if no such node, randomize choice)
+ Abc_NodeBalancePermute( pNtkNew, vSuper, LeftBound );
+ // pull out the last two nodes
+ pNode1 = Vec_PtrPop(vSuper);
+ pNode2 = Vec_PtrPop(vSuper);
+ Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) );
+ }
+ // make sure the balanced node is not assigned
+ assert( pNodeOld->pCopy == NULL );
+ // mark the old node with the new node
+ pNodeOld->pCopy = vSuper->pArray[0];
+ vSuper->nSize = 0;
+// if ( Abc_ObjRegular(pNodeOld->pCopy) == Abc_AigConst1(pNtkNew) )
+// printf( "Constant node\n" );
+// assert( pNodeOld->Level >= Abc_ObjRegular(pNodeOld->pCopy)->Level );
+ // update HAIG
+ if ( Abc_ObjRegular(pNodeOld->pCopy)->pNtk->pHaig )
+ Hop_ObjCreateChoice( pNodeOld->pEquiv, Abc_ObjRegular(pNodeOld->pCopy)->pEquiv );
+ return pNodeOld->pCopy;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes in the cone delimited by fMarkA==1.]
+
+ Description [Returns -1 if the AND-cone has the same node in both polarities.
+ Returns 1 if the AND-cone has the same node in the same polarity. Returns 0
+ if the AND-cone has no repeated nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, bool fSelective )
+{
+ Vec_Ptr_t * vNodes;
+ int RetValue, i;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // extend the storage
+ if ( Vec_VecSize( vStorage ) <= Level )
+ Vec_VecPush( vStorage, Level, 0 );
+ // get the temporary array of nodes
+ vNodes = Vec_VecEntry( vStorage, Level );
+ Vec_PtrClear( vNodes );
+ // collect the nodes in the implication supergate
+ RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate, fSelective );
+ assert( vNodes->nSize > 1 );
+ // unmark the visited nodes
+ for ( i = 0; i < vNodes->nSize; i++ )
+ Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
+ // if we found the node and its complement in the same implication supergate,
+ // return empty set of nodes (meaning that we should use constant-0 node)
+ if ( RetValue == -1 )
+ vNodes->nSize = 0;
+ return vNodes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes in the cone delimited by fMarkA==1.]
+
+ Description [Returns -1 if the AND-cone has the same node in both polarities.
+ Returns 1 if the AND-cone has the same node in the same polarity. Returns 0
+ if the AND-cone has no repeated nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective )
+{
+ int RetValue1, RetValue2, i;
+ // check if the node is visited
+ if ( Abc_ObjRegular(pNode)->fMarkB )
+ {
+ // check if the node occurs in the same polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == pNode )
+ return 1;
+ // check if the node is present in the opposite polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == Abc_ObjNot(pNode) )
+ return -1;
+ assert( 0 );
+ return 0;
+ }
+ // if the new node is complemented or a PI, another gate begins
+ if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && !fSelective && (Abc_ObjFanoutNum(pNode) > 1)) )
+ {
+ Vec_PtrPush( vSuper, pNode );
+ Abc_ObjRegular(pNode)->fMarkB = 1;
+ return 0;
+ }
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ // go through the branches
+ RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate, fSelective );
+ RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate, fSelective );
+ if ( RetValue1 == -1 || RetValue2 == -1 )
+ return -1;
+ // return 1 if at least one branch has a duplicate
+ return RetValue1 || RetValue2;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeBalanceConeExor_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst )
+{
+ int RetValue1, RetValue2, i;
+ // check if the node occurs in the same polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == pNode )
+ return 1;
+ // if the new node is complemented or a PI, another gate begins
+ if ( !fFirst && (!pNode->fExor || !Abc_ObjIsNode(pNode)) )
+ {
+ Vec_PtrPush( vSuper, pNode );
+ return 0;
+ }
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ assert( pNode->fExor );
+ // go through the branches
+ RetValue1 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin0(Abc_ObjFanin0(pNode)), vSuper, 0 );
+ RetValue2 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin1(Abc_ObjFanin0(pNode)), vSuper, 0 );
+ if ( RetValue1 == -1 || RetValue2 == -1 )
+ return -1;
+ // return 1 if at least one branch has a duplicate
+ return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vSuper;
+ if ( !pNode->fExor )
+ return NULL;
+ vSuper = Vec_PtrAlloc( 10 );
+ Abc_NodeBalanceConeExor_rec( pNode, vSuper, 1 );
+ printf( "%d ", Vec_PtrSize(vSuper) );
+ Vec_PtrFree( vSuper );
+ return NULL;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes in the implication supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeFindCone_rec( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNodeC, * pNodeT, * pNodeE;
+ int RetValue, i;
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( Abc_ObjIsCi(pNode) )
+ return NULL;
+ // start the new array
+ vNodes = Vec_PtrAlloc( 4 );
+ // if the node is the MUX collect its fanins
+ if ( Abc_NodeIsMuxType(pNode) )
+ {
+ pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
+ Vec_PtrPush( vNodes, Abc_ObjRegular(pNodeC) );
+ Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeT) );
+ Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeE) );
+ }
+ else
+ {
+ // collect the nodes in the implication supergate
+ RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, 1, 0 );
+ assert( vNodes->nSize > 1 );
+ // unmark the visited nodes
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ Abc_ObjRegular(pNode)->fMarkB = 0;
+ // if we found the node and its complement in the same implication supergate,
+ // return empty set of nodes (meaning that we should use constant-0 node)
+ if ( RetValue == -1 )
+ vNodes->nSize = 0;
+ }
+ // call for the fanin
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ pNode = Abc_ObjRegular(pNode);
+ if ( pNode->pCopy )
+ continue;
+ pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode );
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attaches the implication supergates to internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkCleanCopy( pNtk );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pNode = Abc_ObjFanin0(pNode);
+ if ( pNode->pCopy )
+ continue;
+ pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attaches the implication supergates to internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->pCopy )
+ {
+ Vec_PtrFree( (Vec_Ptr_t *)pNode->pCopy );
+ pNode->pCopy = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute levels of implication supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkBalanceLevel_rec( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vSuper;
+ Abc_Obj_t * pFanin;
+ int i, LevelMax;
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( pNode->Level > 0 )
+ return pNode->Level;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ vSuper = (Vec_Ptr_t *)pNode->pCopy;
+ assert( vSuper != NULL );
+ LevelMax = 0;
+ Vec_PtrForEachEntry( vSuper, pFanin, i )
+ {
+ pFanin = Abc_ObjRegular(pFanin);
+ Abc_NtkBalanceLevel_rec(pFanin);
+ if ( LevelMax < (int)pFanin->Level )
+ LevelMax = pFanin->Level;
+ }
+ pNode->Level = LevelMax + 1;
+ return pNode->Level;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compute levels of implication supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBalanceLevel( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ pNode->Level = 0;
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_NtkBalanceLevel_rec( Abc_ObjFanin0(pNode) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks the nodes on the critical and near critical paths.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, Counter = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= 1 )
+ pNode->fMarkA = 1, Counter++;
+ printf( "The number of nodes on the critical paths = %6d (%5.2f %%)\n", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk) );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcBmc.c b/src/base/abci/abcBmc.c
new file mode 100644
index 00000000..af6d237b
--- /dev/null
+++ b/src/base/abci/abcBmc.c
@@ -0,0 +1,115 @@
+/**CFile****************************************************************
+
+ FileName [abcBmc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Performs bounded model check.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc );
+
+static void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose )
+{
+ Ivy_FraigParams_t Params, * pParams = &Params;
+ Ivy_Man_t * pMan, * pFrames, * pFraig;
+ Vec_Ptr_t * vMapping;
+ // convert to IVY manager
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ // generate timeframes
+ pFrames = Ivy_ManFrames( pMan, Abc_NtkLatchNum(pNtk), nFrames, fInit, &vMapping );
+ // fraig the timeframes
+ Ivy_FraigParamsDefault( pParams );
+ pParams->nBTLimitNode = ABC_INFINITY;
+ pParams->fVerbose = 0;
+ pParams->fProve = 0;
+ pFraig = Ivy_FraigPerform( pFrames, pParams );
+printf( "Frames have %6d nodes. ", Ivy_ManNodeNum(pFrames) );
+printf( "Fraig has %6d nodes.\n", Ivy_ManNodeNum(pFraig) );
+ // report the classes
+// if ( fVerbose )
+// Abc_NtkBmcReport( pMan, pFrames, pFraig, vMapping, nFrames );
+ // free stuff
+ Vec_PtrFree( vMapping );
+ Ivy_ManStop( pFraig );
+ Ivy_ManStop( pFrames );
+ Ivy_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames )
+{
+ Ivy_Obj_t * pFirst1, * pFirst2, * pFirst3;
+ int i, f, nIdMax, Prev2, Prev3;
+ nIdMax = Ivy_ManObjIdMax(pMan);
+ // check what is the number of nodes in each frame
+ Prev2 = Prev3 = 0;
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Ivy_ManForEachNode( pMan, pFirst1, i )
+ {
+ pFirst2 = Ivy_Regular( Vec_PtrEntry(vMapping, f * nIdMax + pFirst1->Id) );
+ if ( Ivy_ObjIsConst1(pFirst2) || pFirst2->Type == 0 )
+ continue;
+ pFirst3 = Ivy_Regular( pFirst2->pEquiv );
+ if ( Ivy_ObjIsConst1(pFirst3) || pFirst3->Type == 0 )
+ continue;
+ break;
+ }
+ if ( f )
+ printf( "Frame %3d : Strash = %5d Fraig = %5d\n", f, pFirst2->Id - Prev2, pFirst3->Id - Prev3 );
+ Prev2 = pFirst2->Id;
+ Prev3 = pFirst3->Id;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c
new file mode 100644
index 00000000..4ed7a774
--- /dev/null
+++ b/src/base/abci/abcCas.c
@@ -0,0 +1,111 @@
+/**CFile****************************************************************
+
+ FileName [abcCas.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Decomposition of shared BDDs into LUT cascade.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCas.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+/*
+ This LUT cascade synthesis algorithm is described in the paper:
+ A. Mishchenko and T. Sasao, "Encoding of Boolean functions and its
+ application to LUT cascade synthesis", Proc. IWLS '02, pp. 115-120.
+ http://www.eecs.berkeley.edu/~alanmi/publications/2002/iwls02_enc.pdf
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose )
+{
+ DdManager * dd;
+ DdNode ** ppOutputs;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode;
+ char * pFileGeneric;
+ int fBddSizeMax = 500000;
+ int fReorder = 1;
+ int i, clk = clock();
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // compute the global BDDs
+ if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL )
+ return NULL;
+
+ if ( fVerbose )
+ {
+ DdManager * dd = Abc_NtkGlobalBddMan( pNtk );
+ printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ PRT( "BDD construction time", clock() - clk );
+ }
+
+ // collect global BDDs
+ dd = Abc_NtkGlobalBddMan( pNtk );
+ ppOutputs = ALLOC( DdNode *, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ ppOutputs[i] = Abc_ObjGlobalBdd(pNode);
+
+ // call the decomposition
+ pFileGeneric = Extra_FileNameGeneric( pNtk->pSpec );
+ if ( !Abc_CascadeExperiment( pFileGeneric, dd, ppOutputs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), nLutSize, fCheck, fVerbose ) )
+ {
+ // the LUT size is too small
+ }
+
+ // for now, duplicate the network
+ pNtkNew = Abc_NtkDup( pNtk );
+
+ // cleanup
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
+ free( ppOutputs );
+ free( pFileGeneric );
+
+// if ( pNtk->pExdc )
+// pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkCollapse: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcClpBdd.c b/src/base/abci/abcClpBdd.c
new file mode 100644
index 00000000..341ff5b0
--- /dev/null
+++ b/src/base/abci/abcClpBdd.c
@@ -0,0 +1,162 @@
+/**CFile****************************************************************
+
+ FileName [abcCollapse.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Collapsing the network into two-levels.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk );
+static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Collapses the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ int clk = clock();
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // compute the global BDDs
+ if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL )
+ return NULL;
+ if ( fVerbose )
+ {
+ DdManager * dd = Abc_NtkGlobalBddMan( pNtk );
+ printf( "Shared BDD size = %6d 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, 1 );
+ if ( pNtkNew == NULL )
+ {
+// Cudd_Quit( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
+ return NULL;
+ }
+// Extra_StopManager( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
+
+ // make the network minimum base
+ Abc_NtkMinimumBase( pNtkNew );
+
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkCollapse: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the network with the given global BDD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkNew;
+ 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 );
+ // make sure the new manager has the same number of inputs
+ Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 );
+ // process the POs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pDriver = Abc_ObjFanin0(pNode);
+ if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) )
+ {
+ Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy );
+ continue;
+ }
+// pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) );
+ pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Abc_ObjGlobalBdd(pNode) );
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ }
+ Extra_ProgressBarStop( pProgress );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the network with the given global BDD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc )
+{
+ Abc_Obj_t * pNodeNew, * pTemp;
+ int i;
+ // create a new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ // add the fanins in the order, in which they appear in the reordered manager
+ Abc_NtkForEachCi( pNtkNew, pTemp, i )
+ Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, dd->invperm[i]) );
+ // transfer the function
+ pNodeNew->pData = Extra_TransferLevelByLevel( dd, pNtkNew->pManFunc, bFunc ); Cudd_Ref( pNodeNew->pData );
+ return pNodeNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcClpSop.c b/src/base/abci/abcClpSop.c
new file mode 100644
index 00000000..de92243f
--- /dev/null
+++ b/src/base/abci/abcClpSop.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+ FileName [abcCollapse.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Collapsing the network into two-levels.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Collapses the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCollapseSop( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ pNtkNew = NULL;
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c
new file mode 100644
index 00000000..d399ce5f
--- /dev/null
+++ b/src/base/abci/abcCut.c
@@ -0,0 +1,620 @@
+/**CFile****************************************************************
+
+ FileName [abcCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface to cut computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "cut.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq );
+static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq );
+
+extern int nTotal, nGood, nEqual;
+
+static Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+ ProgressBar * pProgress;
+ Cut_Man_t * p;
+ Abc_Obj_t * pObj, * pNode;
+ Vec_Ptr_t * vNodes;
+ Vec_Int_t * vChoices;
+ int i;
+ int clk = clock();
+
+ extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk );
+ extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk );
+
+ nTotal = nGood = nEqual = 0;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the manager
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ p = Cut_ManStart( pParams );
+ // compute node attributes if local or global cuts are requested
+ if ( pParams->fGlobal || pParams->fLocal )
+ {
+ extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+ Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) );
+ }
+ // prepare for cut dropping
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( p, pObj->Id );
+ // compute cuts for internal nodes
+ vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+ vChoices = Vec_IntAlloc( 100 );
+ pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // when we reached a CO, it is time to deallocate the cuts
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ if ( pParams->fDrop )
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ continue;
+ }
+ // skip constant node, it has no cuts
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // compute the cuts to the internal node
+ Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree );
+ // consider dropping the fanins cuts
+ if ( pParams->fDrop )
+ {
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+ }
+ // add cuts due to choices
+ if ( Abc_AigNodeIsChoice(pObj) )
+ {
+ Vec_IntClear( vChoices );
+ for ( pNode = pObj; pNode; pNode = pNode->pData )
+ Vec_IntPush( vChoices, pNode->Id );
+ Cut_NodeUnionCuts( p, vChoices );
+ }
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+ Vec_IntFree( vChoices );
+ Cut_ManPrintStats( p );
+PRT( "TOTAL ", clock() - clk );
+ printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) );
+//Abc_NtkPrintCuts( p, pNtk, 0 );
+// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
+
+ // temporary printout of stats
+ if ( nTotal )
+ printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cut computation using the oracle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p )
+{
+ Abc_Obj_t * pObj;
+ Vec_Ptr_t * vNodes;
+ int i, clk = clock();
+ int fDrop = Cut_OracleReadDrop(p);
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // prepare cut droppping
+ if ( fDrop )
+ Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_OracleNodeSetTriv( p, pObj->Id );
+
+ // compute cuts for internal nodes
+ vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // when we reached a CO, it is time to deallocate the cuts
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ if ( fDrop )
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ continue;
+ }
+ // skip constant node, it has no cuts
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ // compute the cuts to the internal node
+ Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ // consider dropping the fanins cuts
+ if ( fDrop )
+ {
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+ }
+ }
+ Vec_PtrFree( vNodes );
+//PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts_( p, pNtk, 0 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+/*
+ Cut_Man_t * p;
+ Abc_Obj_t * pObj, * pNode;
+ int i, nIters, fStatus;
+ Vec_Int_t * vChoices;
+ int clk = clock();
+
+ assert( Abc_NtkIsSeq(pNtk) );
+ assert( pParams->fSeq );
+// assert( Abc_NtkIsDfsOrdered(pNtk) );
+
+ // start the manager
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk );
+ p = Cut_ManStart( pParams );
+
+ // set cuts for the constant node and the PIs
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( p, pObj->Id );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+ Cut_NodeSetTriv( p, pObj->Id );
+ }
+ // label the cutset nodes and set their number in the array
+ // assign the elementary cuts to the cutset nodes
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ {
+ assert( pObj->fMarkC == 0 );
+ pObj->fMarkC = 1;
+ pObj->pCopy = (Abc_Obj_t *)i;
+ Cut_NodeSetTriv( p, pObj->Id );
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+ }
+
+ // process the nodes
+ vChoices = Vec_IntAlloc( 100 );
+ for ( nIters = 0; nIters < 10; nIters++ )
+ {
+//printf( "ITERATION %d:\n", nIters );
+ // compute the cuts for the internal nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Abc_NodeGetCutsSeq( p, pObj, nIters==0 );
+ // add cuts due to choices
+ if ( Abc_AigNodeIsChoice(pObj) )
+ {
+ Vec_IntClear( vChoices );
+ for ( pNode = pObj; pNode; pNode = pNode->pData )
+ Vec_IntPush( vChoices, pNode->Id );
+ Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 );
+ }
+ }
+ // merge the new cuts with the old cuts
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ // for the cutset, transfer temp cuts to new cuts
+ fStatus = 0;
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i );
+ if ( fStatus == 0 )
+ break;
+ }
+ Vec_IntFree( vChoices );
+
+ // if the status is not finished, transfer new to old for the cutset
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+
+ // transfer the old cuts to the new positions
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Cut_NodeOldTransferToNew( p, pObj->Id );
+
+ // unlabel the cutset nodes
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ pObj->fMarkC = 0;
+if ( pParams->fVerbose )
+{
+ Cut_ManPrintStats( p );
+PRT( "TOTAL ", clock() - clk );
+printf( "Converged after %d iterations.\n", nIters );
+}
+//Abc_NtkPrintCuts( p, pNtk, 1 );
+ return p;
+*/
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p )
+{
+ Abc_Obj_t * pObj;
+ int Counter, i;
+ Counter = 0;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Counter += Cut_ManMappingArea_rec( p, Abc_ObjFaninId0(pObj) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+ void * pList;
+ if ( pList = Abc_NodeReadCuts( p, pObj ) )
+ return pList;
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree );
+ return Abc_NodeGetCuts( p, pObj, fDag, fTree );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+ Abc_Obj_t * pFanin;
+ int fDagNode, fTriv, TreeCode = 0;
+// assert( Abc_NtkIsStrash(pObj->pNtk) );
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+
+
+ // check if the node is a DAG node
+ fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj));
+ // increment the counter of DAG nodes
+ if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+ // add the trivial cut if the node is a DAG node, or if we compute all cuts
+ fTriv = fDagNode || !fDag;
+ // check if fanins are DAG nodes
+ if ( fTree )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin));
+ pFanin = Abc_ObjFanin1(pObj);
+ TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1);
+ }
+
+
+ // changes due to the global/local cut computation
+ {
+ Cut_Params_t * pParams = Cut_ManReadParams(p);
+ if ( pParams->fLocal )
+ {
+ Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p);
+ fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id );
+ if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+// fTriv = fDagNode || !pParams->fGlobal;
+ fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id );
+ TreeCode = 0;
+ pFanin = Abc_ObjFanin0(pObj);
+ TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id );
+ pFanin = Abc_ObjFanin1(pObj);
+ TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1);
+ }
+ }
+ return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv )
+{
+/*
+ int CutSetNum;
+ assert( Abc_NtkIsSeq(pObj->pNtk) );
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ fTriv = pObj->fMarkC ? 0 : fTriv;
+ CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1;
+ Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum );
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj )
+{
+ return Cut_NodeReadCutsNew( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj )
+{
+ Cut_NodeFreeCuts( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+ Cut_Man_t * pMan = p;
+ Cut_Cut_t * pList;
+ Abc_Obj_t * pObj;
+ int i;
+ printf( "Cuts of the network:\n" );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ pList = Abc_NodeReadCuts( p, pObj );
+ printf( "Node %s:\n", Abc_ObjName(pObj) );
+ Cut_CutPrintList( pList, fSeq );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+ Cut_Man_t * pMan = p;
+ Cut_Cut_t * pList;
+ Abc_Obj_t * pObj;
+ pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 );
+ pList = Abc_NodeReadCuts( p, pObj );
+ printf( "Node %s:\n", Abc_ObjName(pObj) );
+ Cut_CutPrintList( pList, fSeq );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Assigns global attributes randomly.]
+
+ Description [Old code.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vAttrs;
+// Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;//, * pTemp;
+ int i;//, k;
+ int nNodesTotal = 0, nMffcsTotal = 0;
+ extern Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode );
+
+ vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+// Abc_NtkForEachCi( pNtk, pObj, i )
+// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsNode(pObj) )
+ nNodesTotal++;
+ if ( Abc_ObjIsCo(pObj) && Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+ nMffcsTotal += Abc_NodeMffcSize( Abc_ObjFanin0(pObj) );
+// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) )
+// if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) )
+ if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) )
+ {
+ int nMffc = Abc_NodeMffcSize(pObj);
+ nMffcsTotal += Abc_NodeMffcSize(pObj);
+// printf( "%d ", nMffc );
+
+ if ( nMffc > 2 || Abc_ObjFanoutNum(pObj) > 8 )
+ Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+ }
+ }
+/*
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( Vec_IntEntry( vAttrs, pObj->Id ) )
+ {
+ vNodes = Abc_NodeMffsInsideCollect( pObj );
+ Vec_PtrForEachEntry( vNodes, pTemp, k )
+ if ( pTemp != pObj )
+ Vec_IntWriteEntry( vAttrs, pTemp->Id, 0 );
+ Vec_PtrFree( vNodes );
+ }
+ }
+*/
+ printf( "Total nodes = %d. Total MFFC nodes = %d.\n", nNodesTotal, nMffcsTotal );
+ return vAttrs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns global attributes randomly.]
+
+ Description [Old code.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSubDagSize_rec( Abc_Obj_t * pObj, Vec_Int_t * vAttrs )
+{
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ if ( Vec_IntEntry( vAttrs, pObj->Id ) )
+ return 0;
+ if ( Abc_ObjIsCi(pObj) )
+ return 1;
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ return 1 + Abc_NtkSubDagSize_rec(Abc_ObjFanin0(pObj), vAttrs) +
+ Abc_NtkSubDagSize_rec(Abc_ObjFanin1(pObj), vAttrs);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns global attributes randomly.]
+
+ Description [Old code.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetNodeAttributes2( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vAttrs;
+ Abc_Obj_t * pObj;
+ int i, nSize;
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+ vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ // skip no-nodes and nodes without fanouts
+ if ( pObj->Id == 0 || !(Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) )
+ continue;
+ // the node has more than one fanout - count its sub-DAG size
+ Abc_NtkIncrementTravId( pNtk );
+ nSize = Abc_NtkSubDagSize_rec( pObj, vAttrs );
+ if ( nSize > 15 )
+ Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+ }
+ return vAttrs;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c
new file mode 100644
index 00000000..abf79a82
--- /dev/null
+++ b/src/base/abci/abcDar.c
@@ -0,0 +1,1245 @@
+/**CFile****************************************************************
+
+ FileName [abcDar.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [DAG-aware rewriting.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcDar.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "aig.h"
+#include "dar.h"
+#include "cnf.h"
+#include "fra.h"
+#include "fraig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description [Assumes that registers are ordered after PIs/POs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
+{
+ Aig_Man_t * pMan;
+ Aig_Obj_t * pObjNew;
+ Abc_Obj_t * pObj;
+ int i, nNodes, nDontCares;
+ // make sure the latches follow PIs/POs
+ if ( fRegisters )
+ {
+ assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( i < Abc_NtkPiNum(pNtk) )
+ assert( Abc_ObjIsPi(pObj) );
+ else
+ assert( Abc_ObjIsBo(pObj) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ if ( i < Abc_NtkPoNum(pNtk) )
+ assert( Abc_ObjIsPo(pObj) );
+ else
+ assert( Abc_ObjIsBi(pObj) );
+ // print warning about initial values
+ nDontCares = 0;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( Abc_LatchIsInitDc(pObj) )
+ {
+ Abc_LatchSetInit0(pObj);
+ nDontCares++;
+ }
+ if ( nDontCares )
+ {
+ printf( "Warning: %d registers in this network have don't-care init values.\n", nDontCares );
+ printf( "The don't-care are assumed to be 0. The result may not verify.\n" );
+ printf( "Use command \"print_latch\" to see the init values of registers.\n" );
+ printf( "Use command \"init\" to change the values.\n" );
+ }
+ }
+ // create the manager
+ pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 );
+ pMan->pName = Extra_UtilStrsav( pNtk->pName );
+ // save the number of registers
+ if ( fRegisters )
+ {
+ pMan->nRegs = Abc_NtkLatchNum(pNtk);
+ pMan->vFlopNums = Vec_IntStartNatural( pMan->nRegs );
+ }
+ // transfer the pointers to the basic nodes
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreatePi(pMan);
+ // complement the 1-values registers
+ if ( fRegisters )
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( Abc_LatchIsInit1(pObj) )
+ Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy);
+ // perform the conversion of the internal nodes (assumes DFS ordering)
+// pMan->fAddStrash = 1;
+ 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) );
+// printf( "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id );
+ }
+ pMan->fAddStrash = 0;
+ // create the POs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Aig_ObjCreatePo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) );
+ // complement the 1-valued registers
+ if ( fRegisters )
+ Aig_ManForEachLiSeq( pMan, pObjNew, i )
+ if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) )
+ pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0);
+ // remove dangling nodes
+ if ( nNodes = Aig_ManCleanup( pMan ) )
+ printf( "Abc_NtkToDar(): Unexpected %d dangling nodes when converting to AIG!\n", nNodes );
+//Aig_ManDumpVerilog( pMan, "test.v" );
+ if ( !Aig_ManCheck( pMan ) )
+ {
+ printf( "Abc_NtkToDar: AIG check has failed.\n" );
+ Aig_ManStop( pMan );
+ return NULL;
+ }
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjNew;
+ Aig_Obj_t * pObj;
+ int i;
+// assert( Aig_ManRegNum(pMan) == Abc_NtkLatchNum(pNtkOld) );
+ // perform strashing
+ pNtkNew = Abc_NtkStartFrom( pNtkOld, 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 )
+ pObj->pData = Abc_NtkCi(pNtkNew, i);
+ // rebuild the AIG
+ vNodes = Aig_ManDfs( pMan );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ if ( Aig_ObjIsBuf(pObj) )
+ pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+ else
+ pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) );
+ Vec_PtrFree( vNodes );
+ // connect the PO nodes
+ Aig_ManForEachPo( pMan, pObj, i )
+ {
+ if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts )
+ break;
+ Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
+ }
+ // if there are assertions, add them
+ if ( pMan->nAsserts > 0 )
+ Aig_ManForEachAssert( pMan, pObj, i )
+ {
+ pObjNew = Abc_NtkCreateAssert(pNtkNew);
+ Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) );
+ Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
+ }
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description [This procedure should be called after seq sweeping,
+ which changes the number of registers.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjNew, * pLatch;
+ Aig_Obj_t * pObj, * pObjLo, * pObjLi;
+ int i;
+// assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) );
+ // perform strashing
+ pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+ Aig_ManForEachPiSeq( pMan, pObj, i )
+ pObj->pData = Abc_NtkCi(pNtkNew, i);
+ // create as many latches as there are registers in the manager
+ Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i )
+ {
+ pObjNew = Abc_NtkCreateLatch( pNtkNew );
+ pObjLi->pData = Abc_NtkCreateBi( pNtkNew );
+ pObjLo->pData = Abc_NtkCreateBo( pNtkNew );
+ Abc_ObjAddFanin( pObjNew, pObjLi->pData );
+ Abc_ObjAddFanin( pObjLo->pData, pObjNew );
+ Abc_LatchSetInit0( pObjNew );
+ }
+ if ( pMan->vFlopNums == NULL )
+ Abc_NtkAddDummyBoxNames( pNtkNew );
+ else
+ {
+ assert( Abc_NtkBoxNum(pNtkOld) == Abc_NtkLatchNum(pNtkOld) );
+ Abc_NtkForEachLatch( pNtkNew, pObjNew, i )
+ {
+ pLatch = Abc_NtkBox( pNtkOld, Vec_IntEntry( pMan->vFlopNums, i ) );
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pLatch), NULL );
+ Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pLatch)), NULL );
+ Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pLatch)), NULL );
+ }
+ }
+ // rebuild the AIG
+ vNodes = Aig_ManDfs( pMan );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ if ( Aig_ObjIsBuf(pObj) )
+ pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+ else
+ pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) );
+ Vec_PtrFree( vNodes );
+ // connect the PO nodes
+ Aig_ManForEachPo( pMan, pObj, i )
+ {
+ if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts )
+ break;
+ Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
+ }
+ // if there are assertions, add them
+ if ( pMan->nAsserts > 0 )
+ Aig_ManForEachAssert( pMan, pObj, i )
+ {
+ pObjNew = Abc_NtkCreateAssert(pNtkNew);
+ Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) );
+ Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
+ }
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew;
+ Aig_Obj_t * pObj, * pTemp;
+ int i;
+ assert( pMan->pEquivs != NULL );
+ assert( Aig_ManBufNum(pMan) == 0 );
+ // perform strashing
+ pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+ Aig_ManForEachPi( pMan, pObj, i )
+ pObj->pData = Abc_NtkCi(pNtkNew, i);
+
+ // rebuild the AIG
+ vNodes = Aig_ManDfsChoices( pMan );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) );
+ if ( pTemp = pMan->pEquivs[pObj->Id] )
+ {
+ Abc_Obj_t * pAbcRepr, * pAbcObj;
+ assert( pTemp->pData != NULL );
+ pAbcRepr = pObj->pData;
+ pAbcObj = pTemp->pData;
+ pAbcObj->pData = pAbcRepr->pData;
+ pAbcRepr->pData = pAbcObj;
+ }
+ }
+//printf( "Total = %d. Collected = %d.\n", Aig_ManNodeNum(pMan), Vec_PtrSize(vNodes) );
+ Vec_PtrFree( vNodes );
+ // connect the PO nodes
+ Aig_ManForEachPo( pMan, pObj, i )
+ Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromDarSeq( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+ Aig_Obj_t * pObj;
+ int i;
+// assert( Aig_ManLatchNum(pMan) > 0 );
+ // perform strashing
+ pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, 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 )
+ pObj->pData = Abc_NtkPi(pNtkNew, i);
+ // create latches of the new network
+ Aig_ManForEachObj( pMan, pObj, i )
+ {
+ if ( !Aig_ObjIsLatch(pObj) )
+ continue;
+ pObjNew = Abc_NtkCreateLatch( pNtkNew );
+ pFaninNew0 = Abc_NtkCreateBi( pNtkNew );
+ pFaninNew1 = Abc_NtkCreateBo( pNtkNew );
+ Abc_ObjAddFanin( pObjNew, pFaninNew0 );
+ Abc_ObjAddFanin( pFaninNew1, pObjNew );
+ Abc_LatchSetInit0( pObjNew );
+ pObj->pData = Abc_ObjFanout0( pObjNew );
+ }
+ Abc_NtkAddDummyBoxNames( pNtkNew );
+ // rebuild the AIG
+ vNodes = Aig_ManDfs( pMan );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // add the first fanin
+ pObj->pData = pFaninNew0 = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+ if ( Aig_ObjIsBuf(pObj) )
+ continue;
+ // add the second fanin
+ pFaninNew1 = (Abc_Obj_t *)Aig_ObjChild1Copy(pObj);
+ // create the new node
+ if ( Aig_ObjIsExor(pObj) )
+ pObj->pData = pObjNew = Abc_AigXor( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 );
+ else
+ pObj->pData = pObjNew = Abc_AigAnd( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 );
+ }
+ Vec_PtrFree( vNodes );
+ // connect the PO nodes
+ Aig_ManForEachPo( pMan, pObj, i )
+ {
+ pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), pFaninNew );
+ }
+ // connect the latches
+ Aig_ManForEachObj( pMan, pObj, i )
+ {
+ if ( !Aig_ObjIsLatch(pObj) )
+ continue;
+ pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj );
+ Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pObj->pData)), pFaninNew );
+ }
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect latch values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetLatchValues( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vInits;
+ Abc_Obj_t * pLatch;
+ int i;
+ vInits = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ assert( Abc_LatchIsInit1(pLatch) == 0 );
+ Vec_IntPush( vInits, Abc_LatchIsInit1(pLatch) );
+ }
+ return vInits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs verification after retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+{
+ int fRemove1, fRemove2;
+ Aig_Man_t * pMan1, * pMan2;
+ int * pArray;
+
+ fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0));
+ fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0));
+
+
+ pMan1 = Abc_NtkToDar( pNtk1, 0 );
+ pMan2 = Abc_NtkToDar( pNtk2, 0 );
+
+ Aig_ManPrintStats( pMan1 );
+ Aig_ManPrintStats( pMan2 );
+
+// pArray = Abc_NtkGetLatchValues(pNtk1);
+ pArray = NULL;
+ Aig_ManSeqStrash( pMan1, Abc_NtkLatchNum(pNtk1), pArray );
+ free( pArray );
+
+// pArray = Abc_NtkGetLatchValues(pNtk2);
+ pArray = NULL;
+ Aig_ManSeqStrash( pMan2, Abc_NtkLatchNum(pNtk2), pArray );
+ free( pArray );
+
+ Aig_ManPrintStats( pMan1 );
+ Aig_ManPrintStats( pMan2 );
+
+ Aig_ManStop( pMan1 );
+ Aig_ManStop( pMan2 );
+
+
+ if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+ if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkAig = NULL;
+ Aig_Man_t * pMan;
+ extern void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim );
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // convert to the AIG manager
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+
+ // perform computation
+// Fra_ManPartitionTest( pMan, 4 );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+
+ // make sure everything is okay
+ if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkDar: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose )
+{
+ Fra_Par_t Pars, * pPars = &Pars;
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ Fra_ParamsDefault( pPars );
+ pPars->nBTLimitNode = nConfLimit;
+ pPars->fChoicing = fChoicing;
+ pPars->fDoSparse = fDoSparse;
+ pPars->fSpeculate = fSpeculate;
+ pPars->fProve = fProve;
+ pPars->fVerbose = fVerbose;
+ pMan = Fra_FraigPerform( pTemp = pMan, pPars );
+ if ( fChoicing )
+ pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan );
+ else
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pTemp );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose )
+{
+ extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose );
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Csw_Sweep( pTemp = pMan, nCutsMax, nLeafMax, fVerbose );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pTemp );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManPrintStats( pMan );
+/*
+// Aig_ManSupports( pMan );
+ {
+ Vec_Vec_t * vParts;
+ vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL );
+ Vec_VecFree( vParts );
+ }
+*/
+ Dar_ManRewrite( pMan, pPars );
+// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel );
+// Aig_ManStop( pTemp );
+
+clk = clock();
+ pMan = Aig_ManDup( pTemp = pMan, 0 );
+ Aig_ManStop( pTemp );
+//PRT( "time", clock() - clk );
+
+// Aig_ManPrintStats( pMan );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManPrintStats( pMan );
+
+ Dar_ManRefactor( pMan, pPars );
+// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel );
+// Aig_ManStop( pTemp );
+
+clk = clock();
+ pMan = Aig_ManDup( pTemp = pMan, 0 );
+ Aig_ManStop( pTemp );
+//PRT( "time", clock() - clk );
+
+// Aig_ManPrintStats( pMan );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fVerbose );
+ Aig_ManStop( pTemp );
+//PRT( "time", clock() - clk );
+
+// Aig_ManPrintStats( pMan );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Dar_ManChoice( pTemp = pMan, fBalance, fUpdateLevel, fVerbose );
+ Aig_ManStop( pTemp );
+ pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManPrintStats( pMan );
+
+clk = clock();
+ pMan = Dar_ManRwsat( pTemp = pMan, fBalance, fVerbose );
+ Aig_ManStop( pTemp );
+//PRT( "time", clock() - clk );
+
+// Aig_ManPrintStats( pMan );
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkConstructFromCnf( Abc_Ntk_t * pNtk, Cnf_Man_t * p, Vec_Ptr_t * vMapped )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode, * pNodeNew;
+ Aig_Obj_t * pObj, * pLeaf;
+ Cnf_Cut_t * pCut;
+ Vec_Int_t * vCover;
+ unsigned uTruth;
+ int i, k, nDupGates;
+ // create the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+ // make the mapper point to the new network
+ Aig_ManConst1(p->pManAig)->pData = Abc_NtkCreateNodeConst1(pNtkNew);
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ Aig_ManPi(p->pManAig, i)->pData = pNode->pCopy;
+ // process the nodes in topological order
+ vCover = Vec_IntAlloc( 1 << 16 );
+ Vec_PtrForEachEntry( vMapped, pObj, i )
+ {
+ // create new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ // add fanins according to the cut
+ pCut = pObj->pData;
+ Cnf_CutForEachLeaf( p->pManAig, pCut, pLeaf, k )
+ Abc_ObjAddFanin( pNodeNew, pLeaf->pData );
+ // add logic function
+ if ( pCut->nFanins < 5 )
+ {
+ uTruth = 0xFFFF & *Cnf_CutTruth(pCut);
+ Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vCover );
+ pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, vCover );
+ }
+ else
+ pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, pCut->vIsop[1] );
+ // save the node
+ pObj->pData = pNodeNew;
+ }
+ Vec_IntFree( vCover );
+ // add the CO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pObj = Aig_ManPo(p->pManAig, i);
+ pNodeNew = Abc_ObjNotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ }
+
+ // remove the constant node if not used
+ pNodeNew = (Abc_Obj_t *)Aig_ManConst1(p->pManAig)->pData;
+ if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
+ Abc_NtkDeleteObj( pNodeNew );
+ // minimize the node
+// Abc_NtkSweep( pNtkNew, 0 );
+ // decouple the PO driver nodes to reduce the number of levels
+ nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+// if ( nDupGates && If_ManReadVerbose(pIfMan) )
+// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkConstructFromCnf(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName )
+{
+ Vec_Ptr_t * vMapped;
+ Aig_Man_t * pMan;
+ Cnf_Man_t * pManCnf;
+ Cnf_Dat_t * pCnf;
+ Abc_Ntk_t * pNtkNew = NULL;
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // convert to the AIG manager
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ if ( !Aig_ManCheck( pMan ) )
+ {
+ printf( "Abc_NtkDarToCnf: AIG check has failed.\n" );
+ Aig_ManStop( pMan );
+ return NULL;
+ }
+ // perform balance
+ Aig_ManPrintStats( pMan );
+
+ // derive CNF
+ pCnf = Cnf_Derive( pMan, 0 );
+ pManCnf = Cnf_ManRead();
+
+ // write the network for verification
+ vMapped = Cnf_ManScanMapping( pManCnf, 1, 0 );
+ pNtkNew = Abc_NtkConstructFromCnf( pNtk, pManCnf, vMapped );
+ Vec_PtrFree( vMapped );
+
+ // write CNF into a file
+ Cnf_DataWriteIntoFile( pCnf, pFileName, 0 );
+ Cnf_DataFree( pCnf );
+ Cnf_ClearMemory();
+
+ Aig_ManStop( pMan );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Solves combinational miter using a SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose )
+{
+ Aig_Man_t * pMan;
+ int RetValue;//, clk = clock();
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkLatchNum(pNtk) == 0 );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+ pMan = Abc_NtkToDar( pNtk, 0 );
+ RetValue = Fra_FraigSat( pMan, nConfLimit, nInsLimit, fVerbose );
+ pNtk->pModel = pMan->pData, pMan->pData = NULL;
+ Aig_ManStop( pMan );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fPartition, int fVerbose )
+{
+ Aig_Man_t * pMan, * pMan1, * pMan2;
+ Abc_Ntk_t * pMiter;
+ int RetValue, clkTotal = clock();
+
+ // cannot partition if it is already a miter
+ if ( pNtk2 == NULL && fPartition == 1 )
+ {
+ printf( "Abc_NtkDarCec(): Switching to non-partitioned CEC for the miter.\n" );
+ fPartition = 0;
+ }
+
+ // if partitioning is selected, call partitioned CEC
+ if ( fPartition )
+ {
+ pMan1 = Abc_NtkToDar( pNtk1, 0 );
+ pMan2 = Abc_NtkToDar( pNtk2, 0 );
+ RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, fVerbose );
+ Aig_ManStop( pMan1 );
+ Aig_ManStop( pMan2 );
+ goto finish;
+ }
+
+ if ( pNtk2 != NULL )
+ {
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return 0;
+ }
+ }
+ else
+ {
+ pMiter = Abc_NtkDup( pNtk1 );
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+// extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ if ( pNtk2 == NULL )
+ pNtk1->pModel = Abc_NtkVerifyGetCleanModel( pNtk1, 1 );
+// pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+// FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return 0;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiter );
+ printf( "Networks are equivalent after structural hashing.\n" );
+ return 1;
+ }
+
+ // derive the AIG manager
+ pMan = Abc_NtkToDar( pMiter, 0 );
+ Abc_NtkDelete( pMiter );
+ if ( pMan == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ // perform verification
+ RetValue = Fra_FraigCec( &pMan, fVerbose );
+ // transfer model if given
+ if ( pNtk2 == NULL )
+ pNtk1->pModel = pMan->pData, pMan->pData = NULL;
+ Aig_ManStop( pMan );
+
+finish:
+ // report the miter
+ if ( RetValue == 1 )
+ {
+ printf( "Networks are equivalent. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ else if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ else
+ {
+ printf( "Networks are UNDECIDED. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ fflush( stdout );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose )
+{
+ Fraig_Params_t Params;
+ Abc_Ntk_t * pNtkAig, * pNtkFraig;
+ Aig_Man_t * pMan, * pTemp;
+ int clk = clock();
+
+ // preprocess the miter by fraiging it
+ // (note that for each functional class, fraiging leaves one representative;
+ // so fraiging does not reduce the number of functions represented by nodes
+ Fraig_ParamsSetDefault( &Params );
+ Params.nBTLimit = 100000;
+// pNtkFraig = Abc_NtkFraig( pNtk, &Params, 0, 0 );
+ pNtkFraig = Abc_NtkDup( pNtk );
+if ( fVerbose )
+{
+PRT( "Initial fraiging time", clock() - clk );
+}
+
+ pMan = Abc_NtkToDar( pNtkFraig, 1 );
+ Abc_NtkDelete( pNtkFraig );
+ if ( pMan == NULL )
+ return NULL;
+
+ pMan = Fra_FraigInduction( pTemp = pMan, nFramesP, nFramesK, nMaxImps, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose, NULL );
+ Aig_ManStop( pTemp );
+
+ if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ else
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes latch correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose )
+{
+ Aig_Man_t * pMan, * pTemp;
+ Abc_Ntk_t * pNtkAig;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, NULL );
+ Aig_ManStop( pTemp );
+ if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ else
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose )
+{
+ Aig_Man_t * pMan;
+ int RetValue;
+ // derive the AIG manager
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ assert( pMan->nRegs > 0 );
+ // perform verification
+ RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose );
+ Aig_ManStop( pMan );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose )
+{
+// Fraig_Params_t Params;
+ Aig_Man_t * pMan;
+ Abc_Ntk_t * pMiter;//, * pTemp;
+ int RetValue;
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return 0;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+ Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return 0;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiter );
+ printf( "Networks are equivalent after structural hashing.\n" );
+ return 1;
+ }
+
+ // commented out because something became non-inductive
+/*
+ // preprocess the miter by fraiging it
+ // (note that for each functional class, fraiging leaves one representative;
+ // so fraiging does not reduce the number of functions represented by nodes
+ Fraig_ParamsSetDefault( &Params );
+ Params.nBTLimit = 100000;
+ pMiter = Abc_NtkFraig( pTemp = pMiter, &Params, 0, 0 );
+ Abc_NtkDelete( pTemp );
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+ Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return 0;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiter );
+ printf( "Networks are equivalent after structural hashing.\n" );
+ return 1;
+ }
+*/
+ // derive the AIG manager
+ pMan = Abc_NtkToDar( pMiter, 1 );
+ Abc_NtkDelete( pMiter );
+ if ( pMan == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ assert( pMan->nRegs > 0 );
+
+ // perform verification
+ RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose );
+ Aig_ManStop( pMan );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+ Aig_ManSeqCleanup( pMan );
+ if ( fLatchSweep )
+ {
+ if ( pMan->nRegs )
+ pMan = Aig_ManReduceLaches( pMan, fVerbose );
+ if ( pMan->nRegs )
+ pMan = Aig_ManConstReduce( pMan, fVerbose );
+ }
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManReduceLachesCount( pMan );
+
+ pMan = Rtm_ManRetime( pTemp = pMan, 1, nStepsMax, 0 );
+ Aig_ManStop( pTemp );
+
+// pMan = Aig_ManReduceLaches( pMan, 1 );
+// pMan = Aig_ManConstReduce( pMan, 1 );
+
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcDebug.c b/src/base/abci/abcDebug.c
new file mode 100644
index 00000000..95b95d89
--- /dev/null
+++ b/src/base/abci/abcDebug.c
@@ -0,0 +1,208 @@
+/**CFile****************************************************************
+
+ FileName [abcDebug.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Automated debugging procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcDebug.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtk, int ObjNum, int fConst1 );
+
+extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Takes a network and a procedure to test.]
+
+ Description [The network demonstrates the bug in the procedure.
+ Procedure should return 1 if the bug is demonstrated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) )
+{
+ Abc_Ntk_t * pNtkMod;
+ char * pFileName = "bug_found.blif";
+ int i, nSteps, nIter, ModNum, RandNum = 1, clk, clkTotal = clock();
+ assert( Abc_NtkIsLogic(pNtk) );
+ srand( 0x123123 );
+ // create internal copy of the network
+ pNtk = Abc_NtkDup(pNtk);
+ if ( !(*pFuncError)( pNtk ) )
+ {
+ printf( "The original network does not cause the bug. Quitting.\n" );
+ Abc_NtkDelete( pNtk );
+ return;
+ }
+ // perform incremental modifications
+ for ( nIter = 0; ; nIter++ )
+ {
+ clk = clock();
+ // count how many ways of modifying the network exists
+ nSteps = 2 * Abc_NtkCountFaninsTotal(pNtk);
+ // try modifying the network as many times
+ RandNum ^= rand();
+ for ( i = 0; i < nSteps; i++ )
+ {
+ // get the shifted number of bug
+ ModNum = (i + RandNum) % nSteps;
+ // get the modified network
+ pNtkMod = Abc_NtkAutoDebugModify( pNtk, ModNum/2, ModNum%2 );
+ // write the network
+ Io_WriteBlifLogic( pNtk, "bug_temp.blif", 1 );
+ // check if the bug is still there
+ if ( (*pFuncError)( pNtkMod ) ) // bug is still there
+ {
+ Abc_NtkDelete( pNtk );
+ pNtk = pNtkMod;
+ break;
+ }
+ else // no bug
+ Abc_NtkDelete( pNtkMod );
+ }
+ printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d. ",
+ nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i );
+ PRT( "Time", clock() - clk );
+ if ( i == nSteps ) // could not modify it while preserving the bug
+ break;
+ }
+ // write out the final network
+ Io_WriteBlifLogic( pNtk, pFileName, 1 );
+ printf( "Final network written into file \"%s\". ", pFileName );
+ PRT( "Total time", clock() - clkTotal );
+ Abc_NtkDelete( pNtk );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the total number of fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) )
+ continue;
+ if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 )
+ continue;
+ if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) )
+ continue;
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the node and fanin to be modified.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_Obj_t ** ppFanin )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) )
+ continue;
+ if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 )
+ continue;
+ if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) )
+ continue;
+ if ( Counter++ == Step )
+ {
+ *ppObj = pObj;
+ *ppFanin = pFanin;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform modification with the given number.]
+
+ Description [Modification consists of replacing the node by a constant.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 )
+{
+ extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj, * pFanin, * pConst;
+ // copy the network
+ pNtk = Abc_NtkDup( pNtkInit );
+ assert( Abc_NtkNodeNum(pNtk) == Abc_NtkNodeNum(pNtkInit) );
+ // find the object number
+ Abc_NtkFindGivenFanin( pNtk, Step, &pObj, &pFanin );
+ // consider special case
+ if ( Abc_ObjIsPo(pObj) && Abc_NodeIsConst(pFanin) )
+ {
+ Abc_NtkDeleteAll_rec( pObj );
+ return pNtk;
+ }
+ // plug in a constant node
+ pConst = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk);
+ Abc_ObjTransferFanout( pFanin, pConst );
+ Abc_NtkDeleteAll_rec( pFanin );
+
+ Abc_NtkSweep( pNtk, 0 );
+ Abc_NtkCleanupSeq( pNtk, 0, 0, 0 );
+ Abc_NtkToSop( pNtk, 0 );
+ Abc_NtkCycleInitStateSop( pNtk, 50, 0 );
+ return pNtk;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcDress.c b/src/base/abci/abcDress.c
new file mode 100644
index 00000000..f8182532
--- /dev/null
+++ b/src/base/abci/abcDress.c
@@ -0,0 +1,209 @@
+/**CFile****************************************************************
+
+ FileName [abcDress.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Transfers names from one netlist to the other.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcDress.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "io.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk );
+static void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose );
+
+extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Transfers names from one netlist to the other.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDress( Abc_Ntk_t * pNtkLogic, char * pFileName, int fVerbose )
+{
+ Abc_Ntk_t * pNtkOrig, * pNtkLogicOrig;
+ Abc_Ntk_t * pMiter, * pMiterFraig;
+ stmm_table * tMapping;
+
+ assert( Abc_NtkIsLogic(pNtkLogic) );
+
+ // get the original netlist
+ pNtkOrig = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 1 );
+ if ( pNtkOrig == NULL )
+ return;
+ assert( Abc_NtkIsNetlist(pNtkOrig) );
+
+ Abc_NtkCleanCopy(pNtkLogic);
+ Abc_NtkCleanCopy(pNtkOrig);
+
+ // convert it into the logic network
+ pNtkLogicOrig = Abc_NtkToLogic( pNtkOrig );
+ // check that the networks have the same PIs/POs/latches
+ if ( !Abc_NtkCompareSignals( pNtkLogic, pNtkLogicOrig, 1, 1 ) )
+ {
+ Abc_NtkDelete( pNtkOrig );
+ Abc_NtkDelete( pNtkLogicOrig );
+ return;
+ }
+
+ // convert the current logic network into an AIG
+ pMiter = Abc_NtkStrash( pNtkLogic, 1, 0, 0 );
+
+ // convert it into the AIG and make the netlist point to the AIG
+ Abc_NtkAppend( pMiter, pNtkLogicOrig, 1 );
+ Abc_NtkTransferCopy( pNtkOrig );
+ Abc_NtkDelete( pNtkLogicOrig );
+
+if ( fVerbose )
+{
+printf( "After mitering:\n" );
+printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) );
+printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) );
+}
+
+ // fraig the miter (miter nodes point to the fraiged miter)
+ pMiterFraig = Abc_NtkIvyFraig( pMiter, 100, 1, 0, 1, 0 );
+ // make netlists point to the fraiged miter
+ Abc_NtkTransferCopy( pNtkLogic );
+ Abc_NtkTransferCopy( pNtkOrig );
+ Abc_NtkDelete( pMiter );
+
+if ( fVerbose )
+{
+printf( "After fraiging:\n" );
+printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) );
+printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) );
+}
+
+ // derive mapping from the fraiged nodes into their prototype nodes in the original netlist
+ tMapping = Abc_NtkDressDeriveMapping( pNtkOrig );
+
+ // transfer the names to the new netlist
+ Abc_NtkDressTransferNames( pNtkLogic, tMapping, fVerbose );
+
+ // clean up
+ stmm_free_table( tMapping );
+ Abc_NtkDelete( pMiterFraig );
+ Abc_NtkDelete( pNtkOrig );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the mapping from the fraig nodes point into the nodes of the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk )
+{
+ stmm_table * tResult;
+ Abc_Obj_t * pNode, * pNodeMap, * pNodeFraig;
+ int i;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // get the fraiged node
+ pNodeFraig = Abc_ObjRegular(pNode->pCopy);
+ // if this node is already mapped, skip
+ if ( stmm_is_member( tResult, (char *)pNodeFraig ) )
+ continue;
+ // get the mapping of this node
+ pNodeMap = Abc_ObjNotCond( pNode, Abc_ObjIsComplement(pNode->pCopy) );
+ // add the mapping
+ stmm_insert( tResult, (char *)pNodeFraig, (char *)pNodeMap );
+ }
+ return tResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attaches the names of to the new netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose )
+{
+ Abc_Obj_t * pNet, * pNode, * pNodeMap, * pNodeFraig;
+ char * pName;
+ int i, Counter = 0, CounterInv = 0, CounterInit = stmm_count(tMapping);
+ assert( Abc_NtkIsLogic(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // if the node already has a name, quit
+ pName = Nm_ManFindNameById( pNtk->pManName, pNode->Id );
+ if ( pName != NULL )
+ continue;
+ // get the fraiged node
+ pNodeFraig = Abc_ObjRegular(pNode->pCopy);
+ // find the matching node of the original netlist
+ if ( !stmm_lookup( tMapping, (char *)pNodeFraig, (char **)&pNodeMap ) )
+ continue;
+ // find the true match
+ pNodeMap = Abc_ObjNotCond( pNodeMap, Abc_ObjIsComplement(pNode->pCopy) );
+ // get the name
+ pNet = Abc_ObjFanout0(Abc_ObjRegular(pNodeMap));
+ pName = Nm_ManFindNameById( pNet->pNtk->pManName, pNet->Id );
+ assert( pName != NULL );
+ // set the name
+ if ( Abc_ObjIsComplement(pNodeMap) )
+ {
+ Abc_ObjAssignName( pNode, pName, "_inv" );
+ CounterInv++;
+ }
+ else
+ {
+ Abc_ObjAssignName( pNode, pName, NULL );
+ Counter++;
+ }
+ // remove the name
+ stmm_delete( tMapping, (char **)&pNodeFraig, (char **)&pNodeMap );
+ }
+ if ( fVerbose )
+ {
+ printf( "Total number of names collected = %5d.\n", CounterInit );
+ printf( "Total number of names assigned = %5d. (Dir = %5d. Compl = %5d.)\n",
+ Counter + CounterInv, Counter, CounterInv );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c
new file mode 100644
index 00000000..c00a7d7c
--- /dev/null
+++ b/src/base/abci/abcDsd.c
@@ -0,0 +1,551 @@
+/**CFile****************************************************************
+
+ FileName [abcDsd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Decomposes the network using disjoint-support decomposition.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dsd.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort );
+static void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters );
+
+static Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk );
+static void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters );
+static bool Abc_NodeIsForDsd( Abc_Obj_t * pNode );
+static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives the DSD network.]
+
+ Description [Takes the strashed network (pNtk), derives global BDDs for
+ the combinational outputs of this network, and decomposes these BDDs using
+ disjoint support decomposition. Finally, constructs and return a new
+ network, which is topologically equivalent to the decomposition tree.
+ Allocates and frees a new BDD manager and a new DSD manager.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort )
+{
+ DdManager * dd;
+ Abc_Ntk_t * pNtkNew;
+ assert( Abc_NtkIsStrash(pNtk) );
+ dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
+ if ( dd == NULL )
+ return NULL;
+ if ( fVerbose )
+ printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ // transform the result of mapping into a BDD network
+ pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort );
+ Extra_StopManager( dd );
+ if ( pNtkNew == NULL )
+ return NULL;
+ // copy EXDC network
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkDsdGlobal: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the decomposed network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort )
+{
+ char ** ppNamesCi, ** ppNamesCo;
+ Vec_Ptr_t * vFuncsGlob;
+ Dsd_Manager_t * pManDsd;
+ Abc_Ntk_t * pNtkNew;
+ DdManager * dd;
+ Abc_Obj_t * pObj;
+ int i;
+
+ // complement the global functions
+ vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) );
+
+ // perform the decomposition
+ dd = Abc_NtkGlobalBddMan(pNtk);
+ pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose );
+ Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) );
+ Vec_PtrFree( vFuncsGlob );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
+ if ( pManDsd == NULL )
+ {
+ Cudd_Quit( dd );
+ return NULL;
+ }
+
+ // start the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+ // make sure the new manager has enough inputs
+ Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 );
+ // put the results into the new network (save new CO drivers in old CO drivers)
+ Abc_NtkDsdConstruct( pManDsd, pNtk, pNtkNew );
+ // finalize the new network
+ Abc_NtkFinalize( pNtk, pNtkNew );
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+ if ( fPrint )
+ {
+ ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 );
+ ppNamesCo = Abc_NtkCollectCioNames( pNtk, 1 );
+ Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, fShort, -1 );
+ free( ppNamesCi );
+ free( ppNamesCo );
+ }
+
+ // stop the DSD manager
+ Dsd_ManagerStop( pManDsd );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the decomposed network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+ Dsd_Node_t ** ppNodesDsd;
+ Dsd_Node_t * pNodeDsd;
+ Abc_Obj_t * pNode, * pNodeNew, * pDriver;
+ int i, nNodesDsd;
+
+ // save the CI nodes in the DSD nodes
+ Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), (int)Abc_NtkCreateNodeConst1(pNtkNew) );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ pNodeDsd = Dsd_ManagerReadInput( pManDsd, i );
+ Dsd_NodeSetMark( pNodeDsd, (int)pNode->pCopy );
+ }
+
+ // collect DSD nodes in DFS order (leaves and const1 are not collected)
+ ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd );
+ for ( i = 0; i < nNodesDsd; i++ )
+ Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew, NULL );
+ free( ppNodesDsd );
+
+ // set the pointers to the CO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pDriver = Abc_ObjFanin0( pNode );
+ if ( !Abc_ObjIsNode(pDriver) )
+ continue;
+ if ( !Abc_AigNodeIsAnd(pDriver) )
+ continue;
+ pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i );
+ pNodeNew = (Abc_Obj_t *)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) );
+ assert( !Abc_ObjIsComplement(pNodeNew) );
+ pDriver->pCopy = Abc_ObjNotCond( pNodeNew, Dsd_IsComplement(pNodeDsd) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs DSD using the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters )
+{
+ DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd );
+ DdManager * ddNew = pNtkNew->pManFunc;
+ Dsd_Node_t * pFaninDsd;
+ Abc_Obj_t * pNodeNew, * pFanin;
+ DdNode * bLocal, * bTemp, * bVar;
+ Dsd_Type_t Type;
+ int i, nDecs;
+
+ // create the new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ // add the fanins
+ Type = Dsd_NodeReadType( pNodeDsd );
+ nDecs = Dsd_NodeReadDecsNum( pNodeDsd );
+ assert( nDecs > 1 );
+ for ( i = 0; i < nDecs; i++ )
+ {
+ pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i );
+ pFanin = (Abc_Obj_t *)Dsd_NodeReadMark(Dsd_Regular(pFaninDsd));
+ Abc_ObjAddFanin( pNodeNew, pFanin );
+ assert( Type == DSD_NODE_OR || !Dsd_IsComplement(pFaninDsd) );
+ }
+
+ // create the local function depending on the type of the node
+ ddNew = pNtkNew->pManFunc;
+ switch ( Type )
+ {
+ case DSD_NODE_CONST1:
+ {
+ bLocal = ddNew->one; Cudd_Ref( bLocal );
+ break;
+ }
+ case DSD_NODE_OR:
+ {
+ bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal );
+ for ( i = 0; i < nDecs; i++ )
+ {
+ pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i );
+ bVar = Cudd_NotCond( ddNew->vars[i], Dsd_IsComplement(pFaninDsd) );
+ bLocal = Cudd_bddOr( ddNew, bTemp = bLocal, bVar ); Cudd_Ref( bLocal );
+ Cudd_RecursiveDeref( ddNew, bTemp );
+ }
+ break;
+ }
+ case DSD_NODE_EXOR:
+ {
+ bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal );
+ for ( i = 0; i < nDecs; i++ )
+ {
+ bLocal = Cudd_bddXor( ddNew, bTemp = bLocal, ddNew->vars[i] ); Cudd_Ref( bLocal );
+ Cudd_RecursiveDeref( ddNew, bTemp );
+ }
+ break;
+ }
+ case DSD_NODE_PRIME:
+ {
+ if ( pCounters )
+ {
+ if ( nDecs < 10 )
+ pCounters[nDecs]++;
+ else
+ pCounters[10]++;
+ }
+ bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd ); Cudd_Ref( bLocal );
+ bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal );
+/*
+if ( nDecs == 3 )
+{
+Extra_bddPrint( ddDsd, bTemp );
+printf( "\n" );
+}
+*/
+ Cudd_RecursiveDeref( ddDsd, bTemp );
+ // bLocal is now in the new BDD manager
+ break;
+ }
+ default:
+ {
+ assert( 0 );
+ break;
+ }
+ }
+ pNodeNew->pData = bLocal;
+ Dsd_NodeSetMark( pNodeDsd, (int)pNodeNew );
+ return pNodeNew;
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively decomposes internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive )
+{
+ Dsd_Manager_t * pManDsd;
+ DdManager * dd = pNtk->pManFunc;
+ Vec_Ptr_t * vNodes;
+ int i;
+ int pCounters[11] = {0};
+
+ assert( Abc_NtkIsBddLogic(pNtk) );
+
+ // make the network minimum base
+ Abc_NtkMinimumBase( pNtk );
+
+ // start the DSD manager
+ pManDsd = Dsd_ManagerStart( dd, dd->size, 0 );
+
+ // collect nodes for decomposition
+ vNodes = Abc_NtkCollectNodesForDsd( pNtk );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive, pCounters );
+ Vec_PtrFree( vNodes );
+
+ printf( "Number of non-decomposable functions:\n" );
+ for ( i = 3; i < 10; i++ )
+ printf( "Inputs = %d. Functions = %6d.\n", i, pCounters[i] );
+ printf( "Inputs > %d. Functions = %6d.\n", 9, pCounters[10] );
+
+ // stop the DSD manager
+ Dsd_ManagerStop( pManDsd );
+
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkDsdRecursive: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes that may need decomposition.]
+
+ Description [The nodes that do not need decomposition are those
+ whose BDD has more internal nodes than the support size.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
+ int i;
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( Abc_NodeIsForDsd(pNode) )
+ Vec_PtrPush( vNodes, pNode );
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs decomposition of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters )
+{
+ DdManager * dd = pNode->pNtk->pManFunc;
+ Abc_Obj_t * pRoot, * pFanin, * pNode1, * pNode2, * pNodeC;
+ Dsd_Node_t ** ppNodesDsd, * pNodeDsd, * pFaninDsd;
+ int i, nNodesDsd, iVar, fCompl;
+
+ // try disjoint support decomposition
+ pNodeDsd = Dsd_DecomposeOne( pManDsd, pNode->pData );
+ fCompl = Dsd_IsComplement( pNodeDsd );
+ pNodeDsd = Dsd_Regular( pNodeDsd );
+
+ // determine what decomposition to use
+ if ( !fRecursive || Dsd_NodeReadDecsNum(pNodeDsd) != Abc_ObjFaninNum(pNode) )
+ { // perform DSD
+
+ // set the inputs
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ pFaninDsd = Dsd_ManagerReadInput( pManDsd, i );
+ Dsd_NodeSetMark( pFaninDsd, (int)pFanin );
+ }
+
+ // construct the intermediate nodes
+ ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd );
+ for ( i = 0; i < nNodesDsd; i++ )
+ {
+ pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters );
+ if ( Abc_NodeIsForDsd(pRoot) && fRecursive )
+ Vec_PtrPush( vNodes, pRoot );
+ }
+ free( ppNodesDsd );
+
+ // remove the current fanins
+ Abc_ObjRemoveFanins( pNode );
+ // add fanin to the root
+ Abc_ObjAddFanin( pNode, pRoot );
+ // update the function to be that of buffer
+ Cudd_RecursiveDeref( dd, pNode->pData );
+ pNode->pData = Cudd_NotCond( dd->vars[0], fCompl ); Cudd_Ref( pNode->pData );
+ }
+ else // perform MUX-decomposition
+ {
+ // get the cofactoring variable
+ iVar = Abc_NodeFindMuxVar( dd, pNode->pData, Abc_ObjFaninNum(pNode) );
+ pNodeC = Abc_ObjFanin( pNode, iVar );
+
+ // get the negative cofactor
+ pNode1 = Abc_NtkCloneObj( pNode );
+ pNode1->pData = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(dd->vars[iVar]) ); Cudd_Ref( pNode1->pData );
+ Abc_NodeMinimumBase( pNode1 );
+ if ( Abc_NodeIsForDsd(pNode1) )
+ Vec_PtrPush( vNodes, pNode1 );
+
+ // get the positive cofactor
+ pNode2 = Abc_NtkCloneObj( pNode );
+ pNode2->pData = Cudd_Cofactor( dd, pNode->pData, dd->vars[iVar] ); Cudd_Ref( pNode2->pData );
+ Abc_NodeMinimumBase( pNode2 );
+ if ( Abc_NodeIsForDsd(pNode2) )
+ Vec_PtrPush( vNodes, pNode2 );
+
+ // remove the current fanins
+ Abc_ObjRemoveFanins( pNode );
+ // add new fanins
+ Abc_ObjAddFanin( pNode, pNodeC );
+ Abc_ObjAddFanin( pNode, pNode2 );
+ Abc_ObjAddFanin( pNode, pNode1 );
+ // update the function to be that of MUX
+ Cudd_RecursiveDeref( dd, pNode->pData );
+ pNode->pData = Cudd_bddIte( dd, dd->vars[0], dd->vars[1], dd->vars[2] ); Cudd_Ref( pNode->pData );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the node should be decomposed by DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsForDsd( Abc_Obj_t * pNode )
+{
+ DdManager * dd = pNode->pNtk->pManFunc;
+// DdNode * bFunc, * bFunc0, * bFunc1;
+ assert( Abc_ObjIsNode(pNode) );
+// if ( Cudd_DagSize(pNode->pData)-1 > Abc_ObjFaninNum(pNode) )
+// return 1;
+// return 0;
+
+/*
+ // this does not catch things like a(b+c), which should be decomposed
+ for ( bFunc = Cudd_Regular(pNode->pData); !cuddIsConstant(bFunc); )
+ {
+ bFunc0 = Cudd_Regular( cuddE(bFunc) );
+ bFunc1 = cuddT(bFunc);
+ if ( bFunc0 == b1 )
+ bFunc = bFunc1;
+ else if ( bFunc1 == b1 || bFunc0 == bFunc1 )
+ bFunc = bFunc0;
+ else
+ return 1;
+ }
+*/
+ if ( Abc_ObjFaninNum(pNode) > 2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determines a cofactoring variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars )
+{
+ DdNode * bVar, * bCof0, * bCof1;
+ int SuppSumMin = 1000000;
+ int i, nSSD, nSSQ, iVar;
+
+// printf( "\n\nCofactors:\n\n" );
+ iVar = -1;
+ for ( i = 0; i < nVars; i++ )
+ {
+ bVar = dd->vars[i];
+
+ bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof0 );
+ bCof1 = Cudd_Cofactor( dd, bFunc, bVar ); Cudd_Ref( bCof1 );
+
+// nodD = Cudd_DagSize(bCof0);
+// nodQ = Cudd_DagSize(bCof1);
+// printf( "+%02d: D=%2d. Q=%2d. ", i, nodD, nodQ );
+// printf( "S=%2d. D=%2d. ", nodD + nodQ, abs(nodD-nodQ) );
+
+ nSSD = Cudd_SupportSize( dd, bCof0 );
+ nSSQ = Cudd_SupportSize( dd, bCof1 );
+
+// printf( "SD=%2d. SQ=%2d. ", nSSD, nSSQ );
+// printf( "S=%2d. D=%2d. ", nSSD + nSSQ, abs(nSSD - nSSQ) );
+// printf( "Cost=%3d. ", Cost(nodD,nodQ,nSSD,nSSQ) );
+// printf( "\n" );
+
+ Cudd_RecursiveDeref( dd, bCof0 );
+ Cudd_RecursiveDeref( dd, bCof1 );
+
+ if ( SuppSumMin > nSSD + nSSQ )
+ {
+ SuppSumMin = nSSD + nSSQ;
+ iVar = i;
+ }
+ }
+ return iVar;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcEspresso.c b/src/base/abci/abcEspresso.c
new file mode 100644
index 00000000..8f9c7277
--- /dev/null
+++ b/src/base/abci/abcEspresso.c
@@ -0,0 +1,250 @@
+/**CFile****************************************************************
+
+ FileName [abcEspresso.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures to minimize SOPs using Espresso.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcEspresso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "espresso.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NodeEspresso( Abc_Obj_t * pNode );
+static pset_family Abc_SopToEspresso( char * pSop );
+static char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover );
+static pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes SOP representations using Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // convert the network to have SOPs
+ if ( Abc_NtkHasMapping(pNtk) )
+ Abc_NtkMapToSop(pNtk);
+ else if ( Abc_NtkHasBdd(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Abc_NtkEspresso(): Converting to SOPs has failed.\n" );
+ return;
+ }
+ }
+ // minimize SOPs of all nodes
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( i ) Abc_NodeEspresso( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes SOP representation of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEspresso( Abc_Obj_t * pNode )
+{
+ extern void define_cube_size( int n );
+ pset_family Cover;
+ int fCompl;
+
+ assert( Abc_ObjIsNode(pNode) );
+ // define the cube for this node
+ define_cube_size( Abc_ObjFaninNum(pNode) );
+ // create the Espresso cover
+ fCompl = Abc_SopIsComplement( pNode->pData );
+ Cover = Abc_SopToEspresso( pNode->pData );
+ // perform minimization
+ Cover = Abc_EspressoMinimize( Cover, NULL ); // deletes also cover
+ // convert back onto the node's SOP representation
+ pNode->pData = Abc_SopFromEspresso( pNode->pNtk->pManFunc, Cover );
+ if ( fCompl ) Abc_SopComplement( pNode->pData );
+ sf_free(Cover);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP in ABC into SOP representation in Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+pset_family Abc_SopToEspresso( char * pSop )
+{
+ char * pCube;
+ pset_family Cover;
+ pset set;
+ int nCubes, nVars, Value, v;
+
+ if ( pSop == NULL )
+ return NULL;
+
+ nVars = Abc_SopGetVarNum(pSop);
+ nCubes = Abc_SopGetCubeNum(pSop);
+ assert( cube.size == 2 * nVars );
+
+ if ( Abc_SopIsConst0(pSop) )
+ {
+ Cover = sf_new(0, cube.size);
+ return Cover;
+ }
+ if ( Abc_SopIsConst1(pSop) )
+ {
+ Cover = sf_new(1, cube.size);
+ set = GETSET(Cover, Cover->count++);
+ set_copy( set, cube.fullset );
+ return Cover;
+ }
+
+ // create the cover
+ Cover = sf_new(nCubes, cube.size);
+ // fill in the cubes
+ Abc_SopForEachCube( pSop, nVars, pCube )
+ {
+ set = GETSET(Cover, Cover->count++);
+ set_copy( set, cube.fullset );
+ Abc_CubeForEachVar( pCube, Value, v )
+ {
+ if ( Value == '0' )
+ set_remove(set, 2*v+1);
+ else if ( Value == '1' )
+ set_remove(set, 2*v);
+ }
+ }
+ return Cover;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP representation in Espresso into SOP in ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover )
+{
+ pset set;
+ char * pSop, * pCube;
+ int Lit, nVars, nCubes, i, k;
+
+ nVars = Cover->sf_size/2;
+ nCubes = Cover->count;
+
+ pSop = Abc_SopStart( pMan, nCubes, nVars );
+
+ // go through the cubes
+ i = 0;
+ Abc_SopForEachCube( pSop, nVars, pCube )
+ {
+ set = GETSET(Cover, i++);
+ for ( k = 0; k < nVars; k++ )
+ {
+ Lit = GETINPUT(set, k);
+ if ( Lit == ZERO )
+ pCube[k] = '0';
+ else if ( Lit == ONE )
+ pCube[k] = '1';
+ }
+ }
+ return pSop;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes the cover using Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset )
+{
+ pset_family pOffset;
+ int fNewDcset, i;
+ int fSimple = 0;
+ int fSparse = 0;
+
+ if ( fSimple )
+ {
+ for ( i = 0; i < cube.num_vars; i++ )
+ pOnset = d1merge( pOnset, i );
+ pOnset = sf_contain( pOnset );
+ return pOnset;
+ }
+
+ // create the dcset
+ fNewDcset = (pDcset == NULL);
+ if ( pDcset == NULL )
+ pDcset = sf_new( 1, cube.size );
+ pDcset->wsize = pOnset->wsize;
+ pDcset->sf_size = pOnset->sf_size;
+
+ // derive the offset
+ if ( pDcset->sf_size == 0 || pDcset->count == 0 )
+ pOffset = complement(cube1list(pOnset));
+ else
+ pOffset = complement(cube2list(pOnset, pDcset));
+
+ // perform minimization
+ skip_make_sparse = !fSparse;
+ pOnset = espresso( pOnset, pDcset, pOffset );
+
+ // free covers
+ sf_free( pOffset );
+ if ( fNewDcset )
+ sf_free( pDcset );
+ return pOnset;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcExtract.c b/src/base/abci/abcExtract.c
new file mode 100644
index 00000000..52ea03a3
--- /dev/null
+++ b/src/base/abci/abcExtract.c
@@ -0,0 +1,51 @@
+/**CFile****************************************************************
+
+ FileName [abcMvCost.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Calculating the cost of one MV block.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMvCost.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvCostTest( Abc_Ntk_t * pNtk )
+{
+
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcFpga.c b/src/base/abci/abcFpga.c
new file mode 100644
index 00000000..3bc9fbed
--- /dev/null
+++ b/src/base/abci/abcFpga.c
@@ -0,0 +1,278 @@
+/**CFile****************************************************************
+
+ FileName [abcFpga.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface with the FPGA mapping package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcFpga.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose );
+static Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Interface with the FPGA mapping package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose )
+{
+ int fShowSwitching = 1;
+ Abc_Ntk_t * pNtkNew;
+ Fpga_Man_t * pMan;
+ Vec_Int_t * vSwitching;
+ float * pSwitching = NULL;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // print a warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Performing FPGA mapping with choices.\n" );
+
+ // compute switching activity
+ fShowSwitching |= fSwitching;
+ if ( fShowSwitching )
+ {
+ extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns );
+ vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 );
+ pSwitching = (float *)vSwitching->pArray;
+ }
+
+ // perform FPGA mapping
+ pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fLatchPaths, fVerbose );
+ if ( pSwitching ) Vec_IntFree( vSwitching );
+ if ( pMan == NULL )
+ return NULL;
+ Fpga_ManSetSwitching( pMan, fSwitching );
+ Fpga_ManSetLatchPaths( pMan, fLatchPaths );
+ Fpga_ManSetLatchNum( pMan, Abc_NtkLatchNum(pNtk) );
+ Fpga_ManSetDelayTarget( pMan, DelayTarget );
+ if ( !Fpga_Mapping( pMan ) )
+ {
+ Fpga_ManFree( pMan );
+ return NULL;
+ }
+
+ // transform the result of mapping into a BDD network
+ pNtkNew = Abc_NtkFromFpga( pMan, pNtk );
+ if ( pNtkNew == NULL )
+ return NULL;
+ Fpga_ManFree( pMan );
+
+ // make the network minimum base
+ Abc_NtkMinimumBase( pNtkNew );
+
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkFpga: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Load the network into FPGA manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose )
+{
+ Fpga_Man_t * pMan;
+ ProgressBar * pProgress;
+ Fpga_Node_t * pNodeFpga;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode, * pFanin, * pPrev;
+ float * pfArrivals;
+ int i;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // start the mapping manager and set its parameters
+ pMan = Fpga_ManCreate( Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), fVerbose );
+ if ( pMan == NULL )
+ return NULL;
+ Fpga_ManSetAreaRecovery( pMan, fRecovery );
+ Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) );
+ pfArrivals = Abc_NtkGetCiArrivalFloats(pNtk);
+ if ( fLatchPaths )
+ {
+ for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+ pfArrivals[i] = -FPGA_FLOAT_LARGE;
+ }
+ Fpga_ManSetInputArrivals( pMan, pfArrivals );
+
+ // create PIs and remember them in the old nodes
+ Abc_NtkCleanCopy( pNtk );
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan);
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ pNodeFpga = Fpga_ManReadInputs(pMan)[i];
+ pNode->pCopy = (Abc_Obj_t *)pNodeFpga;
+ if ( pSwitching )
+ Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] );
+ }
+
+ // load the AIG into the mapper
+ vNodes = Abc_AigDfs( pNtk, 0, 0 );
+ pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // add the node to the mapper
+ pNodeFpga = Fpga_NodeAnd( pMan,
+ Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
+ Fpga_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) );
+ assert( pNode->pCopy == NULL );
+ // remember the node
+ pNode->pCopy = (Abc_Obj_t *)pNodeFpga;
+ if ( pSwitching )
+ Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] );
+ // set up the choice node
+ if ( Abc_AigNodeIsChoice( pNode ) )
+ for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
+ {
+ Fpga_NodeSetNextE( (Fpga_Node_t *)pPrev->pCopy, (Fpga_Node_t *)pFanin->pCopy );
+ Fpga_NodeSetRepr( (Fpga_Node_t *)pFanin->pCopy, (Fpga_Node_t *)pNode->pCopy );
+ }
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+
+ // set the primary outputs without copying the phase
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Fpga_ManReadOutputs(pMan)[i] = (Fpga_Node_t *)Abc_ObjFanin0(pNode)->pCopy;
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the mapped network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode, * pNodeNew;
+ int i, nDupGates;
+ // create the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+ // make the mapper point to the new network
+ Fpga_CutsCleanSign( pMan );
+ Fpga_ManCleanData0( pMan );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ Fpga_NodeSetData0( Fpga_ManReadInputs(pMan)[i], (char *)pNode->pCopy );
+ // set the constant node
+// if ( Fpga_NodeReadRefs(Fpga_ManReadConst1(pMan)) > 0 )
+ Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NtkCreateNodeConst1(pNtkNew) );
+ // process the nodes in topological order
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNodeNew = Abc_NodeFromFpga_rec( pNtkNew, Fpga_ManReadOutputs(pMan)[i] );
+ assert( !Abc_ObjIsComplement(pNodeNew) );
+ Abc_ObjFanin0(pNode)->pCopy = pNodeNew;
+ }
+ Extra_ProgressBarStop( pProgress );
+ // finalize the new network
+ Abc_NtkFinalize( pNtk, pNtkNew );
+ // remove the constant node if not used
+ pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0(Fpga_ManReadConst1(pMan));
+ if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
+ Abc_NtkDeleteObj( pNodeNew );
+ // decouple the PO driver nodes to reduce the number of levels
+ nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+// if ( nDupGates && Fpga_ManReadVerbose(pMan) )
+// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derive one node after FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga )
+{
+ Fpga_Cut_t * pCutBest;
+ Fpga_Node_t ** ppLeaves;
+ Abc_Obj_t * pNodeNew;
+ int i, nLeaves;
+ assert( !Fpga_IsComplement(pNodeFpga) );
+ // return if the result if known
+ pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0( pNodeFpga );
+ if ( pNodeNew )
+ return pNodeNew;
+ assert( Fpga_NodeIsAnd(pNodeFpga) );
+ // get the parameters of the best cut
+ pCutBest = Fpga_NodeReadCutBest( pNodeFpga );
+ ppLeaves = Fpga_CutReadLeaves( pCutBest );
+ nLeaves = Fpga_CutReadLeavesNum( pCutBest );
+ // create a new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ for ( i = 0; i < nLeaves; i++ )
+ Abc_ObjAddFanin( pNodeNew, Abc_NodeFromFpga_rec(pNtkNew, ppLeaves[i]) );
+ // derive the function of this node
+ pNodeNew->pData = Fpga_TruthsCutBdd( pNtkNew->pManFunc, pCutBest ); Cudd_Ref( pNodeNew->pData );
+ Fpga_NodeSetData0( pNodeFpga, (char *)pNodeNew );
+ return pNodeNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcFpgaFast.c b/src/base/abci/abcFpgaFast.c
new file mode 100644
index 00000000..356b855e
--- /dev/null
+++ b/src/base/abci/abcFpgaFast.c
@@ -0,0 +1,190 @@
+/**CFile****************************************************************
+
+ FileName [abcFpgaFast.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Fast FPGA mapper.]
+
+ Author [Sungmin Cho]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcFpgaFast.c,v 1.00 2006/09/02 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc );
+
+static Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan );
+static Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes );
+
+static inline void Abc_ObjSetIvy2Abc( Ivy_Man_t * p, int IvyId, Abc_Obj_t * pObjAbc ) { assert(Vec_PtrEntry(p->pCopy, IvyId) == NULL); assert(!Abc_ObjIsComplement(pObjAbc)); Vec_PtrWriteEntry( p->pCopy, IvyId, pObjAbc ); }
+static inline Abc_Obj_t * Abc_ObjGetIvy2Abc( Ivy_Man_t * p, int IvyId ) { return Vec_PtrEntry( p->pCopy, IvyId ); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast FPGA mapping of the network.]
+
+ Description [Takes the AIG to be mapped, the LUT size, and verbosity
+ flag. Produces the new network by fast FPGA mapping of the current
+ network. If the current network in ABC in not an AIG, the user should
+ run command "strash" to make sure that the current network into an AIG
+ before calling this procedure.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose )
+{
+ Ivy_Man_t * pMan;
+ Abc_Ntk_t * pNtkNew;
+ // make sure the network is an AIG
+ assert( Abc_NtkIsStrash(pNtk) );
+ // convert the network into the AIG
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ // perform fast FPGA mapping
+ Ivy_FastMapPerform( pMan, nLutSize, fRecovery, fVerbose );
+ // convert back into the ABC network
+ pNtkNew = Ivy_ManFpgaToAbc( pNtk, pMan );
+ Ivy_FastMapStop( pMan );
+ Ivy_ManStop( pMan );
+ // make sure that the final network passes the test
+ if ( pNtkNew != NULL && !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkFastMap: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the ABC network after mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjAbc, * pObj;
+ Ivy_Obj_t * pObjIvy;
+ Vec_Int_t * vNodes;
+ int i;
+ // start mapping from Ivy into Abc
+ pMan->pCopy = Vec_PtrStart( Ivy_ManObjIdMax(pMan) + 1 );
+ // start the new ABC network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Abc_ObjSetIvy2Abc( pMan, Ivy_ManConst1(pMan)->Id, Abc_NtkCreateNodeConst1(pNtkNew) );
+ Abc_NtkForEachCi( pNtkNew, pObjAbc, i )
+ Abc_ObjSetIvy2Abc( pMan, Ivy_ManPi(pMan, i)->Id, pObjAbc );
+ // recursively construct the network
+ vNodes = Vec_IntAlloc( 100 );
+ Ivy_ManForEachPo( pMan, pObjIvy, i )
+ {
+ // get the new ABC node corresponding to the old fanin of the PO in IVY
+ pObjAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ObjFanin0(pObjIvy), vNodes );
+ // consider the case of complemented fanin of the PO
+ if ( Ivy_ObjFaninC0(pObjIvy) ) // complement
+ {
+ if ( Abc_ObjIsCi(pObjAbc) )
+ pObjAbc = Abc_NtkCreateNodeInv( pNtkNew, pObjAbc );
+ else
+ {
+ // clone the node
+ pObj = Abc_NtkCloneObj( pObjAbc );
+ // set complemented functions
+ pObj->pData = Hop_Not( pObjAbc->pData );
+ // return the new node
+ pObjAbc = pObj;
+ }
+ }
+ Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjAbc );
+ }
+ Vec_IntFree( vNodes );
+ Vec_PtrFree( pMan->pCopy );
+ pMan->pCopy = NULL;
+ // remove dangling nodes
+ Abc_NtkCleanup( pNtkNew, 0 );
+ // fix CIs feeding directly into COs
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively construct the new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes )
+{
+ Vec_Int_t Supp, * vSupp = &Supp;
+ Abc_Obj_t * pObjAbc, * pFaninAbc;
+ Ivy_Obj_t * pNodeIvy;
+ int i, Entry;
+ // skip the node if it is a constant or already processed
+ pObjAbc = Abc_ObjGetIvy2Abc( pMan, pObjIvy->Id );
+ if ( pObjAbc )
+ return pObjAbc;
+ assert( Ivy_ObjIsAnd(pObjIvy) || Ivy_ObjIsExor(pObjIvy) );
+ // get the support of K-LUT
+ Ivy_FastMapReadSupp( pMan, pObjIvy, vSupp );
+ // create new ABC node and its fanins
+ pObjAbc = Abc_NtkCreateNode( pNtkNew );
+ Vec_IntForEachEntry( vSupp, Entry, i )
+ {
+ pFaninAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ManObj(pMan, Entry), vNodes );
+ Abc_ObjAddFanin( pObjAbc, pFaninAbc );
+ }
+ // collect the nodes used in the cut
+ Ivy_ManCollectCut( pMan, pObjIvy, vSupp, vNodes );
+ // create the local function
+ Ivy_ManForEachNodeVec( pMan, vNodes, pNodeIvy, i )
+ {
+ if ( i < Vec_IntSize(vSupp) )
+ pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_IthVar( pNtkNew->pManFunc, i );
+ else
+ 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;
+ // set the node
+ Abc_ObjSetIvy2Abc( pMan, pObjIvy->Id, pObjAbc );
+ return pObjAbc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcFraig.c b/src/base/abci/abcFraig.c
new file mode 100644
index 00000000..be8a25f1
--- /dev/null
+++ b/src/base/abci/abcFraig.c
@@ -0,0 +1,803 @@
+/**CFile****************************************************************
+
+ FileName [abcFraig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures interfacing with the FRAIG package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcFraig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fraig.h"
+#include "main.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig );
+static void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs );
+extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc );
+static void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+
+static int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk );
+static void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Interfaces the network with the FRAIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc )
+{
+ Fraig_Params_t * pPars = pParams;
+ Abc_Ntk_t * pNtkNew;
+ Fraig_Man_t * pMan;
+ // check if EXDC is present
+ if ( fExdc && pNtk->pExdc == NULL )
+ fExdc = 0, printf( "Warning: Networks has no EXDC.\n" );
+ // perform fraiging
+ pMan = Abc_NtkToFraig( pNtk, pParams, fAllNodes, fExdc );
+ // add algebraic choices
+// if ( pPars->fChoicing )
+// Fraig_ManAddChoices( pMan, 0, 6 );
+ // prove the miter if asked to
+ if ( pPars->fTryProve )
+ Fraig_ManProveMiter( pMan );
+ // reconstruct FRAIG in the new network
+ if ( fExdc )
+ pNtkNew = Abc_NtkFromFraig2( pMan, pNtk );
+ else
+ pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
+ Fraig_ManFree( pMan );
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkFraig: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the strashed network into FRAIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc )
+{
+ int fInternal = ((Fraig_Params_t *)pParams)->fInternal;
+ Fraig_Man_t * pMan;
+ ProgressBar * pProgress;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
+ int i;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // create the FRAIG manager
+ pMan = Fraig_ManCreate( pParams );
+
+ // map the constant node
+ Abc_NtkCleanCopy( pNtk );
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan);
+ // create PIs and remember them in the old nodes
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, i);
+
+ // perform strashing
+ vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 );
+ if ( !fInternal )
+ pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( Abc_ObjFaninNum(pNode) == 0 )
+ continue;
+ if ( !fInternal )
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNode->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan,
+ Fraig_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
+ Fraig_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) );
+ }
+ if ( !fInternal )
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+
+ // use EXDC to change the mapping of nodes into FRAIG nodes
+ if ( fExdc )
+ Abc_NtkFraigRemapUsingExdc( pMan, pNtk );
+
+ // set the primary outputs
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Fraig_ManSetPo( pMan, (Fraig_Node_t *)Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives EXDC node for the given network.]
+
+ Description [Assumes that EXDCs of all POs are the same.
+ Returns the EXDC of the first PO.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc )
+{
+ Abc_Ntk_t * pNtkStrash;
+ Abc_Obj_t * pObj;
+ Fraig_Node_t * gResult;
+ char ** ppNames;
+ int i, k;
+ // strash the EXDC network
+ pNtkStrash = Abc_NtkStrash( pNtkExdc, 0, 0, 0 );
+ Abc_NtkCleanCopy( pNtkStrash );
+ Abc_AigConst1(pNtkStrash)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan);
+ // set the mapping of the PI nodes
+ ppNames = Abc_NtkCollectCioNames( pNtkMain, 0 );
+ Abc_NtkForEachCi( pNtkStrash, pObj, i )
+ {
+ for ( k = 0; k < Abc_NtkCiNum(pNtkMain); k++ )
+ if ( strcmp( Abc_ObjName(pObj), ppNames[k] ) == 0 )
+ {
+ pObj->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, k);
+ break;
+ }
+ assert( pObj->pCopy != NULL );
+ }
+ free( ppNames );
+ // build FRAIG for each node
+ Abc_AigForEachAnd( pNtkStrash, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan,
+ Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ),
+ Fraig_NotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ) );
+ // get the EXDC to be returned
+ pObj = Abc_NtkPo( pNtkStrash, 0 );
+ gResult = Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+ Abc_NtkDelete( pNtkStrash );
+ return gResult;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Changes mapping of the old nodes into FRAIG nodes using EXDC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ Fraig_Node_t * gNodeNew, * gNodeExdc;
+ stmm_table * tTable;
+ stmm_generator * gen;
+ Abc_Obj_t * pNode, * pNodeBest;
+ Abc_Obj_t * pClass, ** ppSlot;
+ Vec_Ptr_t * vNexts;
+ int i;
+
+ // get the global don't-cares
+ assert( pNtk->pExdc );
+ gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc );
+
+ // save the next pointers
+ vNexts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Vec_PtrWriteEntry( vNexts, pNode->Id, pNode->pNext );
+
+ // find the classes of AIG nodes which have FRAIG nodes assigned
+ Abc_NtkCleanNext( pNtk );
+ tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->pCopy )
+ {
+ gNodeNew = Fraig_NodeAnd( pMan, (Fraig_Node_t *)pNode->pCopy, Fraig_Not(gNodeExdc) );
+ if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(gNodeNew), (char ***)&ppSlot ) )
+ *ppSlot = NULL;
+ pNode->pNext = *ppSlot;
+ *ppSlot = pNode;
+ }
+
+ // for reach non-trival class, find the node with minimum level, and replace other nodes by it
+ Abc_AigSetNodePhases( pNtk );
+ stmm_foreach_item( tTable, gen, (char **)&gNodeNew, (char **)&pClass )
+ {
+ if ( pClass->pNext == NULL )
+ continue;
+ // find the node with minimum level
+ pNodeBest = pClass;
+ for ( pNode = pClass->pNext; pNode; pNode = pNode->pNext )
+ if ( pNodeBest->Level > pNode->Level )
+ pNodeBest = pNode;
+ // remap the class nodes
+ for ( pNode = pClass; pNode; pNode = pNode->pNext )
+ pNode->pCopy = Abc_ObjNotCond( pNodeBest->pCopy, pNode->fPhase ^ pNodeBest->fPhase );
+ }
+ stmm_free_table( tTable );
+
+ // restore the next pointers
+ Abc_NtkCleanNext( pNtk );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->pNext = Vec_PtrEntry( vNexts, pNode->Id );
+ Vec_PtrFree( vNexts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms FRAIG into strashed network with choices.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode, * pNodeNew;
+ int i;
+ // create the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // make the mapper point to the new network
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ Fraig_NodeSetData1( Fraig_ManReadIthVar(pMan, i), (Fraig_Node_t *)pNode->pCopy );
+ // set the constant node
+ Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew) );
+ // process the nodes in topological order
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNodeNew = Abc_NodeFromFraig_rec( pNtkNew, Fraig_ManReadOutputs(pMan)[i] );
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Abc_NtkReassignIds( pNtkNew );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms into AIG one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig )
+{
+ Abc_Obj_t * pRes, * pRes0, * pRes1, * pResMin, * pResCur;
+ Fraig_Node_t * pNodeTemp, * pNodeFraigR = Fraig_Regular(pNodeFraig);
+ void ** ppTail;
+ // check if the node was already considered
+ if ( pRes = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeFraigR) )
+ return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) );
+ // solve the children
+ pRes0 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadOne(pNodeFraigR) );
+ pRes1 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadTwo(pNodeFraigR) );
+ // derive the new node
+ pRes = Abc_AigAnd( pNtkNew->pManFunc, pRes0, pRes1 );
+ pRes->fPhase = Fraig_NodeReadSimInv( pNodeFraigR );
+ // if the node has an equivalence class, find its representative
+ if ( Fraig_NodeReadRepr(pNodeFraigR) == NULL && Fraig_NodeReadNextE(pNodeFraigR) != NULL )
+ {
+ // go through the FRAIG nodes belonging to this equivalence class
+ // and find the representative node (the node with the smallest level)
+ pResMin = pRes;
+ for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) )
+ {
+ assert( Fraig_NodeReadData1(pNodeTemp) == NULL );
+ pResCur = Abc_NodeFromFraig_rec( pNtkNew, pNodeTemp );
+ if ( pResMin->Level > pResCur->Level )
+ pResMin = pResCur;
+ }
+ // link the nodes in such a way that representative goes first
+ ppTail = &pResMin->pData;
+ if ( pRes != pResMin )
+ {
+ *ppTail = pRes;
+ ppTail = &pRes->pData;
+ }
+ for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) )
+ {
+ pResCur = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeTemp);
+ assert( pResCur );
+ if ( pResMin == pResCur )
+ continue;
+ *ppTail = pResCur;
+ ppTail = &pResCur->pData;
+ }
+ assert( *ppTail == NULL );
+
+ // update the phase of the node
+ pRes = Abc_ObjNotCond( pResMin, (pRes->fPhase ^ pResMin->fPhase) );
+ }
+ Fraig_NodeSetData1( pNodeFraigR, (Fraig_Node_t *)pRes );
+ return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms FRAIG into strashed network without choices.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ stmm_table * tTable;
+ Vec_Ptr_t * vNodeReprs;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode, * pRepr, ** ppSlot;
+ int i;
+
+ // map the nodes into their lowest level representives
+ tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+ pNode = Abc_AigConst1(pNtk);
+ if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+ *ppSlot = pNode;
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+ *ppSlot = pNode;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->pCopy )
+ {
+ if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) )
+ *ppSlot = pNode;
+ else if ( (*ppSlot)->Level > pNode->Level )
+ *ppSlot = pNode;
+ }
+ // save representatives for each node
+ vNodeReprs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->pCopy )
+ {
+ if ( !stmm_lookup( tTable, (char *)Fraig_Regular(pNode->pCopy), (char **)&pRepr ) )
+ assert( 0 );
+ if ( pNode != pRepr )
+ Vec_PtrWriteEntry( vNodeReprs, pNode->Id, pRepr );
+ }
+ stmm_free_table( tTable );
+
+ // create the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+
+ // perform strashing
+ Abc_AigSetNodePhases( pNtk );
+ Abc_NtkIncrementTravId( pNtk );
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodeReprs );
+
+ // finalize the network
+ Abc_NtkFinalize( pNtk, pNtkNew );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transforms into AIG one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs )
+{
+ Abc_Obj_t * pRepr;
+ // skip the PIs and constants
+ if ( Abc_ObjFaninNum(pNode) < 2 )
+ return;
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ assert( Abc_ObjIsNode( pNode ) );
+ // get the node's representative
+ if ( pRepr = Vec_PtrEntry(vNodeReprs, pNode->Id) )
+ {
+ Abc_NtkFromFraig2_rec( pNtkNew, pRepr, vNodeReprs );
+ pNode->pCopy = Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pNode->fPhase );
+ return;
+ }
+ Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs );
+ Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin1(pNode), vNodeReprs );
+ pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Interfaces the network with the FRAIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+
+ if ( !Abc_NtkIsSopLogic(pNtk) )
+ {
+ printf( "Abc_NtkFraigTrust: Trust mode works for netlists and logic SOP networks.\n" );
+ return NULL;
+ }
+
+ if ( !Abc_NtkFraigTrustCheck(pNtk) )
+ {
+ printf( "Abc_NtkFraigTrust: The network does not look like an AIG with choice nodes.\n" );
+ return NULL;
+ }
+
+ // perform strashing
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ Abc_NtkFraigTrustOne( pNtk, pNtkNew );
+ Abc_NtkFinalize( pNtk, pNtkNew );
+ Abc_NtkReassignIds( pNtkNew );
+
+ // print a warning about choice nodes
+ printf( "Warning: The resulting AIG contains %d choice nodes.\n", Abc_NtkGetChoiceNum( pNtkNew ) );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkFraigTrust: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks whether the node can be processed in the trust mode.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, nFanins;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ nFanins = Abc_ObjFaninNum(pNode);
+ if ( nFanins < 2 )
+ continue;
+ if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) )
+ continue;
+ if ( !Abc_SopIsOrType(pNode->pData) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interfaces the network with the FRAIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+ ProgressBar * pProgress;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode, * pNodeNew, * pObj;
+ int i;
+
+ // perform strashing
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // get the node
+ assert( Abc_ObjIsNode(pNode) );
+ // strash the node
+ pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode );
+ // get the old object
+ if ( Abc_NtkIsNetlist(pNtk) )
+ pObj = Abc_ObjFanout0( pNode ); // the fanout net
+ else
+ pObj = pNode; // the node itself
+ // make sure the node is not yet strashed
+ assert( pObj->pCopy == NULL );
+ // mark the old object with the new AIG node
+ pObj->pCopy = pNodeNew;
+ }
+ Vec_PtrFree( vNodes );
+ Extra_ProgressBarStop( pProgress );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms one node into a FRAIG in the trust mode.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pSum, * pFanin;
+ void ** ppTail;
+ int i, nFanins, fCompl;
+
+ assert( Abc_ObjIsNode(pNode) );
+ // get the number of node's fanins
+ nFanins = Abc_ObjFaninNum( pNode );
+ assert( nFanins == Abc_SopGetVarNum(pNode->pData) );
+ // check if it is a constant
+ if ( nFanins == 0 )
+ return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Abc_SopIsConst0(pNode->pData) );
+ if ( nFanins == 1 )
+ return Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_SopIsInv(pNode->pData) );
+ if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) )
+ return Abc_AigAnd( pNtkNew->pManFunc,
+ Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,0) ),
+ Abc_ObjNotCond( Abc_ObjFanin1(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,1) ) );
+ assert( Abc_SopIsOrType(pNode->pData) );
+ fCompl = Abc_SopGetIthCareLit(pNode->pData,0);
+ // get the root of the choice node (the first fanin)
+ pSum = Abc_ObjFanin0(pNode)->pCopy;
+ // connect other fanins
+ ppTail = &pSum->pData;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( i == 0 )
+ continue;
+ *ppTail = pFanin->pCopy;
+ ppTail = &pFanin->pCopy->pData;
+ // set the complemented bit of this cut
+ if ( fCompl ^ Abc_SopGetIthCareLit(pNode->pData, i) )
+ pFanin->pCopy->fPhase = 1;
+ }
+ assert( *ppTail == NULL );
+ return pSum;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Interfaces the network with the FRAIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd )
+{
+ Vec_Ptr_t * vStore;
+ Abc_Ntk_t * pNtk;
+ // create the network to be stored
+ pNtk = Abc_NtkStrash( pNtkAdd, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" );
+ return 0;
+ }
+ // get the network currently stored
+ vStore = Abc_FrameReadStore();
+ if ( Vec_PtrSize(vStore) > 0 )
+ {
+ // check that the networks have the same PIs
+ // reorder PIs of pNtk2 according to pNtk1
+ if ( !Abc_NtkCompareSignals( pNtk, Vec_PtrEntry(vStore, 0), 1, 1 ) )
+ {
+ printf( "Trying to store the network with different primary inputs.\n" );
+ printf( "The previously stored networks are deleted and this one is added.\n" );
+ Abc_NtkFraigStoreClean();
+ }
+ }
+ Vec_PtrPush( vStore, pNtk );
+// printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interfaces the network with the FRAIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFraigRestore()
+{
+ extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams );
+ Fraig_Params_t Params;
+ Vec_Ptr_t * vStore;
+ Abc_Ntk_t * pNtk, * pFraig;
+ int nWords1, nWords2, nWordsMin;
+ int clk = clock();
+
+ // get the stored network
+ vStore = Abc_FrameReadStore();
+ if ( Vec_PtrSize(vStore) == 0 )
+ {
+ printf( "There are no network currently in storage.\n" );
+ return NULL;
+ }
+// printf( "Currently stored %d networks will be fraiged.\n", Vec_PtrSize(vStore) );
+ pNtk = Vec_PtrEntry( vStore, 0 );
+
+ // swap the first and last network
+ // this should lead to the primary choice being "better" because of synthesis
+ pNtk = Vec_PtrPop( vStore );
+ Vec_PtrPush( vStore, Vec_PtrEntry(vStore,0) );
+ Vec_PtrWriteEntry( vStore, 0, pNtk );
+
+ // to determine the number of simulation patterns
+ // use the following strategy
+ // at least 64 words (32 words random and 32 words dynamic)
+ // no more than 256M for one circuit (128M + 128M)
+ nWords1 = 32;
+ nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk));
+ nWordsMin = ABC_MIN( nWords1, nWords2 );
+
+ // set parameters for fraiging
+ Fraig_ParamsSetDefault( &Params );
+ Params.nPatsRand = nWordsMin * 32; // the number of words of random simulation info
+ Params.nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info
+ Params.nBTLimit = 1000; // the max number of backtracks to perform
+ Params.fFuncRed = 1; // performs only one level hashing
+ Params.fFeedBack = 1; // enables solver feedback
+ Params.fDist1Pats = 1; // enables distance-1 patterns
+ Params.fDoSparse = 1; // performs equiv tests for sparse functions
+ Params.fChoicing = 1; // enables recording structural choices
+ Params.fTryProve = 0; // tries to solve the final miter
+ Params.fVerbose = 0; // the verbosiness flag
+
+ // perform partitioned computation of structural choices
+ pFraig = Abc_NtkFraigPartitioned( vStore, &Params );
+ Abc_NtkFraigStoreClean();
+//PRT( "Total choicing time", clock() - clk );
+ return pFraig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interfaces the network with the FRAIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigStoreClean()
+{
+ Vec_Ptr_t * vStore;
+ Abc_Ntk_t * pNtk;
+ int i;
+ vStore = Abc_FrameReadStore();
+ Vec_PtrForEachEntry( vStore, pNtk, i )
+ Abc_NtkDelete( pNtk );
+ Vec_PtrClear( vStore );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks the correctness of stored networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig )
+{
+ Abc_Obj_t * pNode0, * pNode1;
+ int nPoOrig, nPoFinal, nStored;
+ int i, k;
+ // check that the PO functions are correct
+ nPoFinal = Abc_NtkPoNum(pFraig);
+ nStored = Abc_FrameReadStoreSize();
+ assert( nPoFinal % nStored == 0 );
+ nPoOrig = nPoFinal / nStored;
+ for ( i = 0; i < nPoOrig; i++ )
+ {
+ pNode0 = Abc_ObjFanin0( Abc_NtkPo(pFraig, i) );
+ for ( k = 1; k < nStored; k++ )
+ {
+ pNode1 = Abc_ObjFanin0( Abc_NtkPo(pFraig, k*nPoOrig+i) );
+ if ( pNode0 != pNode1 )
+ printf( "Verification for PO #%d of network #%d has failed. The PO function is not used.\n", i+1, k+1 );
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcFxu.c b/src/base/abci/abcFxu.c
new file mode 100644
index 00000000..45515dd1
--- /dev/null
+++ b/src/base/abci/abcFxu.c
@@ -0,0 +1,260 @@
+/**CFile****************************************************************
+
+ FileName [abcFxu.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface with the fast extract package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcFxu.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fxu.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk );
+static void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
+static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast_extract on the current network.]
+
+ Description [Takes the network and the maximum number of nodes to extract.
+ Uses the concurrent double-cube and single cube divisor extraction procedure.
+ Modifies the network in the end, after extracting all nodes. Note that
+ Ntk_NetworkSweep() may increase the performance of this procedure because
+ the single-literal nodes will not be created in the sparse matrix. Returns 1
+ if the network has been changed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p )
+{
+ assert( Abc_NtkIsLogic(pNtk) );
+ // if the network is already in the SOP form, it may come from BLIF file
+ // and it may not be SCC-free, in which case FXU will not work correctly
+ if ( Abc_NtkIsSopLogic(pNtk) )
+ { // to make sure the SOPs are SCC-free
+// Abc_NtkSopToBdd(pNtk);
+// Abc_NtkBddToSop(pNtk);
+ }
+ // get the network in the SOP form
+ if ( !Abc_NtkToSop(pNtk, 0) )
+ {
+ printf( "Abc_NtkFastExtract(): Converting to SOPs has failed.\n" );
+ return 0;
+ }
+ // check if the network meets the requirements
+ if ( !Abc_NtkFxuCheck(pNtk) )
+ {
+ printf( "Abc_NtkFastExtract: Nodes have duplicated or complemented fanins. FXU is not performed.\n" );
+ return 0;
+ }
+ // sweep removes useless nodes
+ Abc_NtkCleanup( pNtk, 0 );
+ // collect information about the covers
+ Abc_NtkFxuCollectInfo( pNtk, p );
+ // call the fast extract procedure
+ if ( Fxu_FastExtract(p) > 0 )
+ {
+ // update the network
+ Abc_NtkFxuReconstruct( pNtk, p );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtk ) )
+ printf( "Abc_NtkFastExtract: The network check has failed.\n" );
+ return 1;
+ }
+ else
+ printf( "Warning: The network has not been changed by \"fx\".\n" );
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Makes sure the nodes do not have complemented and duplicated fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode, * pFanin1, * pFanin2;
+ int n, i, k;
+ Abc_NtkForEachNode( pNtk, pNode, n )
+ {
+ Abc_ObjForEachFanin( pNode, pFanin1, i )
+ {
+ if ( i < 2 && Abc_ObjFaninC(pNode, i) )
+ return 0;
+ Abc_ObjForEachFanin( pNode, pFanin2, k )
+ {
+ if ( i == k )
+ continue;
+ if ( pFanin1 == pFanin2 )
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect information about the network for fast_extract.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ // add information to the manager
+ p->pManSop = pNtk->pManFunc;
+ p->vSops = Vec_PtrAlloc(0);
+ p->vFanins = Vec_PtrAlloc(0);
+ p->vSopsNew = Vec_PtrAlloc(0);
+ p->vFaninsNew = Vec_PtrAlloc(0);
+ Vec_PtrFill( p->vSops, Abc_NtkObjNumMax(pNtk), NULL );
+ Vec_PtrFill( p->vFanins, Abc_NtkObjNumMax(pNtk), NULL );
+ Vec_PtrFill( p->vSopsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL );
+ Vec_PtrFill( p->vFaninsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL );
+ // add SOPs and fanin array
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( Abc_SopGetVarNum(pNode->pData) < 2 )
+ continue;
+ if ( Abc_SopGetCubeNum(pNode->pData) < 1 )
+ continue;
+ p->vSops->pArray[i] = pNode->pData;
+ p->vFanins->pArray[i] = &pNode->vFanins;
+ }
+ p->nNodesOld = Abc_NtkObjNumMax(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFxuFreeInfo( Fxu_Data_t * p )
+{
+ int i;
+ // free the arrays of new fanins
+ if ( p->vFaninsNew )
+ for ( i = 0; i < p->vFaninsNew->nSize; i++ )
+ if ( p->vFaninsNew->pArray[i] )
+ Vec_IntFree( p->vFaninsNew->pArray[i] );
+ // free the arrays
+ if ( p->vSops ) Vec_PtrFree( p->vSops );
+ if ( p->vSopsNew ) Vec_PtrFree( p->vSopsNew );
+ if ( p->vFanins ) Vec_PtrFree( p->vFanins );
+ if ( p->vFaninsNew ) Vec_PtrFree( p->vFaninsNew );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recostructs the network after FX.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p )
+{
+ Vec_Int_t * vFanins;
+ Abc_Obj_t * pNode, * pFanin;
+ int i, k;
+
+ assert( p->vFanins->nSize < p->vFaninsNew->nSize );
+ // create the new nodes
+ for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ )
+ {
+ // start the node
+ pNode = Abc_NtkCreateNode( pNtk );
+ assert( i == (int)pNode->Id );
+ }
+ // update the old nodes
+ for ( i = 0; i < p->vFanins->nSize; i++ )
+ {
+ // the new array of fanins
+ vFanins = p->vFaninsNew->pArray[i];
+ if ( vFanins == NULL )
+ continue;
+ // remove old fanins
+ pNode = Abc_NtkObj( pNtk, i );
+ Abc_ObjRemoveFanins( pNode );
+ // add new fanins
+ vFanins = p->vFaninsNew->pArray[i];
+ for ( k = 0; k < vFanins->nSize; k++ )
+ {
+ pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] );
+ Abc_ObjAddFanin( pNode, pFanin );
+ }
+ pNode->pData = p->vSopsNew->pArray[i];
+ assert( pNode->pData != NULL );
+ }
+ // set up the new nodes
+ for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ )
+ {
+ // get the new node
+ pNode = Abc_NtkObj( pNtk, i );
+ // add the fanins
+ vFanins = p->vFaninsNew->pArray[i];
+ for ( k = 0; k < vFanins->nSize; k++ )
+ {
+ pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] );
+ Abc_ObjAddFanin( pNode, pFanin );
+ }
+ pNode->pData = p->vSopsNew->pArray[i];
+ assert( pNode->pData != NULL );
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcGen.c b/src/base/abci/abcGen.c
new file mode 100644
index 00000000..bfb41374
--- /dev/null
+++ b/src/base/abci/abcGen.c
@@ -0,0 +1,511 @@
+/**CFile****************************************************************
+
+ FileName [abc_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 );
+void Abc_WriteComp( FILE * pFile );
+void Abc_WriteFullAdder( FILE * pFile );
+
+void Abc_GenAdder( char * pFileName, int nVars );
+void Abc_GenSorter( char * pFileName, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_GenAdder( char * pFileName, int nVars )
+{
+ FILE * pFile;
+ int i;
+
+ assert( nVars > 0 );
+
+ pFile = fopen( pFileName, "w" );
+ fprintf( pFile, "# %d-bit ripple-carry adder generated by ABC on %s\n", nVars, Extra_TimeStamp() );
+ fprintf( pFile, ".model Adder%02d\n", nVars );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " a%02d", i );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " b%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".outputs" );
+ for ( i = 0; i <= nVars; i++ )
+ fprintf( pFile, " y%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".names c\n" );
+ if ( nVars == 1 )
+ fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=y01\n" );
+ else
+ {
+ fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=%02d\n", 0 );
+ for ( i = 1; i < nVars-1; i++ )
+ fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=%02d\n", i, i, i-1, i, i );
+ fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=y%02d\n", i, i, i-1, i, i+1 );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+
+ Abc_WriteFullAdder( pFile );
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_GenSorter( char * pFileName, int nVars )
+{
+ FILE * pFile;
+ int i, k, Counter, nDigits;
+
+ assert( nVars > 1 );
+
+ pFile = fopen( pFileName, "w" );
+ fprintf( pFile, "# %d-bit sorter generated by ABC on %s\n", nVars, Extra_TimeStamp() );
+ fprintf( pFile, ".model Sorter%02d\n", nVars );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " x%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".outputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " y%02d", i );
+ fprintf( pFile, "\n" );
+
+ Counter = 0;
+ nDigits = Extra_Base10Log( (nVars-2)*nVars );
+ if ( nVars == 2 )
+ fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" );
+ else
+ {
+ fprintf( pFile, ".subckt Layer0" );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " x%02d=x%02d", k, k );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ );
+ fprintf( pFile, "\n" );
+ Counter -= nVars;
+ for ( i = 1; i < nVars-2; i++ )
+ {
+ fprintf( pFile, ".subckt Layer%d", (i&1) );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ );
+ fprintf( pFile, "\n" );
+ Counter -= nVars;
+ }
+ fprintf( pFile, ".subckt Layer%d", (i&1) );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ );
+ for ( k = 0; k < nVars; k++ )
+ fprintf( pFile, " y%02d=y%02d", k, k );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+
+ Abc_WriteLayer( pFile, nVars, 0 );
+ Abc_WriteLayer( pFile, nVars, 1 );
+ Abc_WriteComp( pFile );
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 )
+{
+ int i;
+ fprintf( pFile, ".model Layer%d\n", fSkip1 );
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " x%02d", i );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".outputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " y%02d", i );
+ fprintf( pFile, "\n" );
+ if ( fSkip1 )
+ {
+ fprintf( pFile, ".names x00 y00\n" );
+ fprintf( pFile, "1 1\n" );
+ i = 1;
+ }
+ else
+ i = 0;
+ for ( ; i + 1 < nVars; i += 2 )
+ fprintf( pFile, ".subckt Comp a=x%02d b=x%02d x=y%02d y=y%02d\n", i, i+1, i, i+1 );
+ if ( i < nVars )
+ {
+ fprintf( pFile, ".names x%02d y%02d\n", i, i );
+ fprintf( pFile, "1 1\n" );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteComp( FILE * pFile )
+{
+ fprintf( pFile, ".model Comp\n" );
+ fprintf( pFile, ".inputs a b\n" );
+ fprintf( pFile, ".outputs x y\n" );
+ fprintf( pFile, ".names a b x\n" );
+ fprintf( pFile, "11 1\n" );
+ fprintf( pFile, ".names a b y\n" );
+ fprintf( pFile, "1- 1\n" );
+ fprintf( pFile, "-1 1\n" );
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteFullAdder( FILE * pFile )
+{
+ fprintf( pFile, ".model FA\n" );
+ fprintf( pFile, ".inputs a b cin\n" );
+ fprintf( pFile, ".outputs s cout\n" );
+ fprintf( pFile, ".names a b k\n" );
+ fprintf( pFile, "10 1\n" );
+ fprintf( pFile, "01 1\n" );
+ fprintf( pFile, ".names k cin s\n" );
+ fprintf( pFile, "10 1\n" );
+ fprintf( pFile, "01 1\n" );
+ fprintf( pFile, ".names a b cin cout\n" );
+ fprintf( pFile, "11- 1\n" );
+ fprintf( pFile, "1-1 1\n" );
+ fprintf( pFile, "-11 1\n" );
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteCell( FILE * pFile )
+{
+ fprintf( pFile, ".model cell\n" );
+ fprintf( pFile, ".inputs px1 px2 py1 py2 x y\n" );
+ fprintf( pFile, ".outputs fx fy\n" );
+ fprintf( pFile, ".names x y a\n" );
+ fprintf( pFile, "11 1\n" );
+ fprintf( pFile, ".names px1 a x nx\n" );
+ fprintf( pFile, "11- 1\n" );
+ fprintf( pFile, "0-1 1\n" );
+ fprintf( pFile, ".names py1 a y ny\n" );
+ fprintf( pFile, "11- 1\n" );
+ fprintf( pFile, "0-1 1\n" );
+ fprintf( pFile, ".names px2 nx fx\n" );
+ fprintf( pFile, "10 1\n" );
+ fprintf( pFile, "01 1\n" );
+ fprintf( pFile, ".names py2 ny fy\n" );
+ fprintf( pFile, "10 1\n" );
+ fprintf( pFile, "01 1\n" );
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_GenMesh( char * pFileName, int nVars )
+{
+ FILE * pFile;
+ int i, k;
+
+ assert( nVars > 0 );
+
+ pFile = fopen( pFileName, "w" );
+ fprintf( pFile, "# %dx%d mesh generated by ABC on %s\n", nVars, nVars, Extra_TimeStamp() );
+ fprintf( pFile, ".model mesh%d\n", nVars );
+
+ for ( i = 0; i < nVars; i++ )
+ for ( k = 0; k < nVars; k++ )
+ {
+ fprintf( pFile, ".inputs" );
+ fprintf( pFile, " p%d%dx1", i, k );
+ fprintf( pFile, " p%d%dx2", i, k );
+ fprintf( pFile, " p%d%dy1", i, k );
+ fprintf( pFile, " p%d%dy2", i, k );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " v%02d v%02d", 2*i, 2*i+1 );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".outputs" );
+ fprintf( pFile, " fx00" );
+ fprintf( pFile, "\n" );
+
+ for ( i = 0; i < nVars; i++ ) // horizontal
+ for ( k = 0; k < nVars; k++ ) // vertical
+ {
+ fprintf( pFile, ".subckt cell" );
+ fprintf( pFile, " px1=p%d%dx1", i, k );
+ fprintf( pFile, " px2=p%d%dx2", i, k );
+ fprintf( pFile, " py1=p%d%dy1", i, k );
+ fprintf( pFile, " py2=p%d%dy2", i, k );
+ if ( k == nVars - 1 )
+ fprintf( pFile, " x=v%02d", i );
+ else
+ fprintf( pFile, " x=fx%d%d", i, k+1 );
+ if ( i == nVars - 1 )
+ fprintf( pFile, " y=v%02d", nVars+k );
+ else
+ fprintf( pFile, " y=fy%d%d", i+1, k );
+ // outputs
+ fprintf( pFile, " fx=fx%d%d", i, k );
+ fprintf( pFile, " fy=fy%d%d", i, k );
+ fprintf( pFile, "\n" );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "\n" );
+
+ Abc_WriteCell( pFile );
+ fclose( pFile );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_WriteKLut( FILE * pFile, int nLutSize )
+{
+ int i, iVar, iNext, nPars = (1 << nLutSize);
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".model lut%d\n", nLutSize );
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nPars; i++ )
+ fprintf( pFile, " p%02d", i );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nLutSize; i++ )
+ fprintf( pFile, " i%d", i );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".outputs o\n" );
+ fprintf( pFile, ".names n01 o\n" );
+ fprintf( pFile, "1 1\n" );
+ // write internal MUXes
+ iVar = 0;
+ iNext = 2;
+ for ( i = 1; i < nPars; i++ )
+ {
+ if ( i == iNext )
+ {
+ iNext *= 2;
+ iVar++;
+ }
+ if ( iVar == nLutSize - 1 )
+ fprintf( pFile, ".names i%d p%02d p%02d n%02d\n", iVar, 2*(i-nPars/2), 2*(i-nPars/2)+1, i );
+ else
+ fprintf( pFile, ".names i%d n%02d n%02d n%02d\n", iVar, 2*i, 2*i+1, i );
+ fprintf( pFile, "01- 1\n" );
+ fprintf( pFile, "1-1 1\n" );
+ }
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Generates structure of L K-LUTs implementing an N-var function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars )
+{
+ FILE * pFile;
+ int nVarsLut = (1 << nLutSize); // the number of LUT variables
+ int nVarsLog = Extra_Base2Log( nVars + nLuts - 1 ); // the number of encoding vars
+ int nVarsDeg = (1 << nVarsLog); // the number of LUT variables (total)
+ int nParsLut = nLuts * (1 << nLutSize); // the number of LUT params
+ int nParsVar = nLuts * nLutSize * nVarsLog; // the number of var params
+ int i, j, k;
+
+ assert( nVars > 0 );
+
+ pFile = fopen( pFileName, "w" );
+ fprintf( pFile, "# Structure with %d %d-LUTs for %d-var function generated by ABC on %s\n", nLuts, nLutSize, nVars, Extra_TimeStamp() );
+ fprintf( pFile, ".model struct%dx%d_%d\n", nLuts, nLutSize, nVars );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nParsLut; i++ )
+ fprintf( pFile, " pl%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nParsVar; i++ )
+ fprintf( pFile, " pv%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".inputs" );
+ for ( i = 0; i < nVars; i++ )
+ fprintf( pFile, " v%02d", i );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, ".outputs" );
+ fprintf( pFile, " v%02d", nVars + nLuts - 1 );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, ".names Gnd\n" );
+ fprintf( pFile, " 0\n" );
+
+ // generate LUTs
+ for ( i = 0; i < nLuts; i++ )
+ {
+ fprintf( pFile, ".subckt lut%d", nLutSize );
+ // generate config parameters
+ for ( k = 0; k < nVarsLut; k++ )
+ fprintf( pFile, " p%02d=pl%02d", k, i * nVarsLut + k );
+ // generate the inputs
+ for ( k = 0; k < nLutSize; k++ )
+ fprintf( pFile, " i%d=s%02d", k, i * nLutSize + k );
+ // generate the output
+ fprintf( pFile, " o=v%02d", nVars + i );
+ fprintf( pFile, "\n" );
+ }
+
+ // generate LUT inputs
+ for ( i = 0; i < nLuts; i++ )
+ {
+ for ( j = 0; j < nLutSize; j++ )
+ {
+ fprintf( pFile, ".subckt lut%d", nVarsLog );
+ // generate config parameters
+ for ( k = 0; k < nVarsDeg; k++ )
+ {
+ if ( k < nVars + nLuts - 1 && k < nVars + i )
+ fprintf( pFile, " p%02d=v%02d", k, k );
+ else
+ fprintf( pFile, " p%02d=Gnd", k );
+ }
+ // generate the inputs
+ for ( k = 0; k < nVarsLog; k++ )
+ fprintf( pFile, " i%d=pv%02d", k, (i * nLutSize + j) * nVarsLog + k );
+ // generate the output
+ fprintf( pFile, " o=s%02d", i * nLutSize + j );
+ fprintf( pFile, "\n" );
+ }
+ }
+
+ fprintf( pFile, ".end\n" );
+ fprintf( pFile, "\n" );
+
+ // generate LUTs
+ Abc_WriteKLut( pFile, nLutSize );
+ if ( nVarsLog != nLutSize )
+ Abc_WriteKLut( pFile, nVarsLog );
+ fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcHaig.c b/src/base/abci/abcHaig.c
new file mode 100644
index 00000000..d3513bbe
--- /dev/null
+++ b/src/base/abci/abcHaig.c
@@ -0,0 +1,726 @@
+/**CFile****************************************************************
+
+ FileName [abcHaig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Implements history AIG for combinational rewriting.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcHaig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Start history AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkHaigStart( Abc_Ntk_t * pNtk )
+{
+ Hop_Man_t * p;
+ Abc_Obj_t * pObj, * pTemp;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // check if the package is already started
+ if ( pNtk->pHaig )
+ {
+ Abc_NtkHaigStop( pNtk );
+ assert( pNtk->pHaig == NULL );
+ printf( "Warning: Previous history AIG was removed.\n" );
+ }
+ // make sure the data is clean
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ assert( pObj->pEquiv == NULL );
+ // start the HOP package
+ p = Hop_ManStart();
+ p->vObjs = Vec_PtrAlloc( 4096 );
+ Vec_PtrPush( p->vObjs, Hop_ManConst1(p) );
+ // map the constant node
+ Abc_AigConst1(pNtk)->pEquiv = Hop_ManConst1(p);
+ // map the CIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pEquiv = Hop_ObjCreatePi(p);
+ // map the internal nodes
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pEquiv = Hop_And( p, Abc_ObjChild0Equiv(pObj), Abc_ObjChild1Equiv(pObj) );
+ // map the choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ // print warning about choice nodes
+ printf( "Warning: The choice nodes in the original AIG are converted into HAIG.\n" );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( !Abc_AigNodeIsChoice( pObj ) )
+ continue;
+ for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData )
+ Hop_ObjCreateChoice( pObj->pEquiv, pTemp->pEquiv );
+ }
+ }
+ // make sure everything is okay
+ if ( !Hop_ManCheck(p) )
+ {
+ printf( "Abc_NtkHaigStart: Check for History AIG has failed.\n" );
+ Hop_ManStop(p);
+ return 0;
+ }
+ pNtk->pHaig = p;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops history AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkHaigStop( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ if ( pNtk->pHaig == NULL )
+ {
+ printf( "Warning: History AIG is not allocated.\n" );
+ return 1;
+ }
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pEquiv = NULL;
+ Hop_ManStop( pNtk->pHaig );
+ pNtk->pHaig = NULL;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the HAIG to the new network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ if ( pNtkOld->pHaig == NULL )
+ return;
+ // transfer the package
+ assert( pNtkNew->pHaig == NULL );
+ pNtkNew->pHaig = pNtkOld->pHaig;
+ pNtkOld->pHaig = NULL;
+ // transfer constant pointer
+ Abc_AigConst1(pNtkOld)->pCopy->pEquiv = Abc_AigConst1(pNtkOld)->pEquiv;
+ // transfer the CI pointers
+ Abc_NtkForEachCi( pNtkOld, pObj, i )
+ pObj->pCopy->pEquiv = pObj->pEquiv;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes in the classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkHaigCollectMembers( Hop_Man_t * p )
+{
+ Vec_Ptr_t * vObjs;
+ Hop_Obj_t * pObj;
+ int i;
+ vObjs = Vec_PtrAlloc( 4098 );
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ if ( pObj->pData == NULL )
+ continue;
+ pObj->pData = Hop_ObjRepr( pObj );
+ Vec_PtrPush( vObjs, pObj );
+ }
+ return vObjs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkHaigCreateClasses( Vec_Ptr_t * vMembers )
+{
+ Vec_Ptr_t * vClasses;
+ Hop_Obj_t * pObj, * pRepr;
+ int i;
+
+ // count classes
+ vClasses = Vec_PtrAlloc( 4098 );
+ Vec_PtrForEachEntry( vMembers, pObj, i )
+ {
+ pRepr = pObj->pData;
+ assert( pRepr->pData == NULL );
+ if ( pRepr->fMarkA == 0 ) // new
+ {
+ pRepr->fMarkA = 1;
+ Vec_PtrPush( vClasses, pRepr );
+ }
+ }
+
+ // set representatives as representatives
+ Vec_PtrForEachEntry( vClasses, pObj, i )
+ {
+ pObj->fMarkA = 0;
+ pObj->pData = pObj;
+ }
+
+ // go through the members and update
+ Vec_PtrForEachEntry( vMembers, pObj, i )
+ {
+ pRepr = pObj->pData;
+ if ( ((Hop_Obj_t *)pRepr->pData)->Id > pObj->Id )
+ pRepr->pData = pObj;
+ }
+
+ // change representatives of the class
+ Vec_PtrForEachEntry( vMembers, pObj, i )
+ {
+ pRepr = pObj->pData;
+ pObj->pData = pRepr->pData;
+ assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id );
+ }
+
+ // update classes
+ Vec_PtrForEachEntry( vClasses, pObj, i )
+ {
+ pRepr = pObj->pData;
+ assert( pRepr->pData == pRepr );
+// pRepr->pData = NULL;
+ Vec_PtrWriteEntry( vClasses, i, pRepr );
+ Vec_PtrPush( vMembers, pObj );
+ }
+
+ Vec_PtrForEachEntry( vMembers, pObj, i )
+ if ( pObj->pData == pObj )
+ pObj->pData = NULL;
+
+/*
+ Vec_PtrForEachEntry( vMembers, pObj, i )
+ {
+ printf( "ObjId = %4d : ", pObj->Id );
+ if ( pObj->pData == NULL )
+ {
+ printf( "NULL" );
+ }
+ else
+ {
+ printf( "%4d", ((Hop_Obj_t *)pObj->pData)->Id );
+ assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id );
+ }
+ printf( "\n" );
+ }
+*/
+ return vClasses;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts how many data members have non-trivial fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkHaigCountFans( Hop_Man_t * p )
+{
+ Hop_Obj_t * pObj;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ if ( pObj->pData == NULL )
+ continue;
+ if ( Hop_ObjRefs(pObj) > 0 )
+ Counter++;
+ }
+ printf( "The number of class members with fanouts = %5d.\n", Counter );
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hop_Obj_t * Hop_ObjReprHop( Hop_Obj_t * pObj )
+{
+ Hop_Obj_t * pRepr;
+ assert( pObj->pNext != NULL );
+ if ( pObj->pData == NULL )
+ return pObj->pNext;
+ pRepr = pObj->pData;
+ assert( pRepr->pData == pRepr );
+ return Hop_NotCond( pRepr->pNext, pObj->fPhase ^ pRepr->fPhase );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hop_Obj_t * Hop_ObjChild0Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin0(pObj)), Hop_ObjFaninC0(pObj) ); }
+static inline Hop_Obj_t * Hop_ObjChild1Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin1(pObj)), Hop_ObjFaninC1(pObj) ); }
+
+/**Function*************************************************************
+
+ Synopsis [Stops history AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Man_t * Abc_NtkHaigReconstruct( Hop_Man_t * p )
+{
+ Hop_Man_t * pNew;
+ Hop_Obj_t * pObj;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ pObj->pNext = NULL;
+ // start the HOP package
+ pNew = Hop_ManStart();
+ pNew->vObjs = Vec_PtrAlloc( p->nCreated );
+ Vec_PtrPush( pNew->vObjs, Hop_ManConst1(pNew) );
+ // map the constant node
+ Hop_ManConst1(p)->pNext = Hop_ManConst1(pNew);
+ // map the CIs
+ Hop_ManForEachPi( p, pObj, i )
+ pObj->pNext = Hop_ObjCreatePi(pNew);
+ // map the internal nodes
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ if ( !Hop_ObjIsNode(pObj) )
+ continue;
+ pObj->pNext = Hop_And( pNew, Hop_ObjChild0Hop(pObj), Hop_ObjChild1Hop(pObj) );
+// assert( !Hop_IsComplement(pObj->pNext) );
+ if ( Hop_ManConst1(pNew) == Hop_Regular(pObj->pNext) )
+ Counter++;
+ if ( pObj->pData ) // member of the class
+ Hop_Regular(pObj->pNext)->pData = Hop_Regular(((Hop_Obj_t *)pObj->pData)->pNext);
+ }
+// printf( " Counter = %d.\n", Counter );
+ // transfer the POs
+ Hop_ManForEachPo( p, pObj, i )
+ Hop_ObjCreatePo( pNew, Hop_ObjChild0Hop(pObj) );
+ // check the new manager
+ if ( !Hop_ManCheck(pNew) )
+ {
+ printf( "Abc_NtkHaigReconstruct: Check for History AIG has failed.\n" );
+ Hop_ManStop(pNew);
+ return NULL;
+ }
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pOld is in the TFI of pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkHaigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld )
+{
+ if ( pNode == NULL )
+ return 0;
+ if ( pNode == pOld )
+ return 1;
+ // check the trivial cases
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ assert( Abc_ObjIsNode(pNode) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return 0;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // check the children
+ if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) )
+ return 1;
+ if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) )
+ return 1;
+ // check equivalent nodes
+ return Abc_NtkHaigCheckTfi_rec( pNode->pData, pOld );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pOld is in the TFI of pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkHaigCheckTfi( Abc_Ntk_t * pNtk, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
+{
+ assert( !Abc_ObjIsComplement(pOld) );
+ assert( !Abc_ObjIsComplement(pNew) );
+ Abc_NtkIncrementTravId(pNtk);
+ return Abc_NtkHaigCheckTfi_rec( pNew, pOld );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Abc_Obj_t * Hop_ObjChild0Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin0(pObj)->pNext, Hop_ObjFaninC0(pObj) ); }
+static inline Abc_Obj_t * Hop_ObjChild1Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin1(pObj)->pNext, Hop_ObjFaninC1(pObj) ); }
+
+/**Function*************************************************************
+
+ Synopsis [Stops history AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p )
+{
+ Abc_Ntk_t * pNtkAig;
+ Abc_Obj_t * pObjOld, * pObjAbcThis, * pObjAbcRepr;
+ Hop_Obj_t * pObj;
+ int i;
+ assert( p->nCreated == Vec_PtrSize(p->vObjs) );
+
+ // start the new network
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+
+ // transfer new nodes to the PIs of HOP
+ Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig );
+ Hop_ManForEachPi( p, pObj, i )
+ pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i );
+
+ // construct new nodes
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ if ( !Hop_ObjIsNode(pObj) )
+ continue;
+ pObj->pNext = (Hop_Obj_t *)Abc_AigAnd( pNtkAig->pManFunc, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) );
+ assert( !Hop_IsComplement(pObj->pNext) );
+ }
+
+ // set the COs
+ Abc_NtkForEachCo( pNtk, pObjOld, i )
+ Abc_ObjAddFanin( pObjOld->pCopy, Hop_ObjChild0Next(Hop_ManPo(p,i)) );
+
+ // construct choice nodes
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ // skip the node without choices
+ if ( pObj->pData == NULL )
+ continue;
+ // skip the representative of the class
+ if ( pObj->pData == pObj )
+ continue;
+ // do not create choices for constant 1 and PIs
+ if ( !Hop_ObjIsNode(pObj->pData) )
+ continue;
+ // get the corresponding new nodes
+ pObjAbcThis = (Abc_Obj_t *)pObj->pNext;
+ pObjAbcRepr = (Abc_Obj_t *)((Hop_Obj_t *)pObj->pData)->pNext;
+ // the new node cannot be already in the class
+ assert( pObjAbcThis->pData == NULL );
+ // the new node cannot have fanouts
+ assert( Abc_ObjFanoutNum(pObjAbcThis) == 0 );
+ // these should be different nodes
+ assert( pObjAbcRepr != pObjAbcThis );
+ // do not create choices if there is a path from pObjAbcThis to pObjAbcRepr
+ if ( !Abc_NtkHaigCheckTfi( pNtkAig, pObjAbcRepr, pObjAbcThis ) )
+ {
+ // find the last node in the class
+ while ( pObjAbcRepr->pData )
+ pObjAbcRepr = pObjAbcRepr->pData;
+ // add the new node at the end of the list
+ pObjAbcRepr->pData = pObjAbcThis;
+ }
+ }
+
+ // finish the new network
+// Abc_NtkFinalize( pNtk, pNtkAig );
+// Abc_AigCleanup( pNtkAig->pManFunc );
+ // check correctness of the network
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkHaigUse: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resets representatives.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkHaigResetReprsOld( Hop_Man_t * pMan )
+{
+ Vec_Ptr_t * vMembers, * vClasses;
+
+ // collect members of the classes and make them point to reprs
+ vMembers = Abc_NtkHaigCollectMembers( pMan );
+ printf( "Collected %6d class members.\n", Vec_PtrSize(vMembers) );
+
+ // create classes
+ vClasses = Abc_NtkHaigCreateClasses( vMembers );
+ printf( "Collected %6d classes. (Ave = %5.2f)\n", Vec_PtrSize(vClasses),
+ (float)(Vec_PtrSize(vMembers))/Vec_PtrSize(vClasses) );
+
+ Vec_PtrFree( vMembers );
+ Vec_PtrFree( vClasses );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resets representatives.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkHaigResetReprs( Hop_Man_t * p )
+{
+ Hop_Obj_t * pObj, * pRepr;
+ int i, nClasses, nMembers, nFanouts, nNormals;
+ // clear self-classes
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ // fix the strange situation of double-loop
+ pRepr = pObj->pData;
+ if ( pRepr && pRepr->pData == pObj )
+ pRepr->pData = pRepr;
+ // remove self-loops
+ if ( pObj->pData == pObj )
+ pObj->pData = NULL;
+ }
+ // set representatives
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ if ( pObj->pData == NULL )
+ continue;
+ // get representative of the node
+ pRepr = Hop_ObjRepr( pObj );
+ pRepr->pData = pRepr;
+ // set the representative
+ pObj->pData = pRepr;
+ }
+ // make each class point to the smallest topological order
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ if ( pObj->pData == NULL )
+ continue;
+ pRepr = Hop_ObjRepr( pObj );
+ if ( pRepr->Id > pObj->Id )
+ {
+ pRepr->pData = pObj;
+ pObj->pData = pObj;
+ }
+ else
+ pObj->pData = pRepr;
+ }
+ // count classes, members, and fanouts - and verify
+ nMembers = nClasses = nFanouts = nNormals = 0;
+ Vec_PtrForEachEntry( p->vObjs, pObj, i )
+ {
+ if ( pObj->pData == NULL )
+ continue;
+ // count members
+ nMembers++;
+ // count the classes and fanouts
+ if ( pObj->pData == pObj )
+ nClasses++;
+ else if ( Hop_ObjRefs(pObj) > 0 )
+ nFanouts++;
+ else
+ nNormals++;
+ // compare representatives
+ pRepr = Hop_ObjRepr( pObj );
+ assert( pObj->pData == pRepr );
+ assert( pRepr->Id <= pObj->Id );
+ }
+// printf( "Nodes = %7d. Member = %7d. Classes = %6d. Fanouts = %6d. Normals = %6d.\n",
+// Hop_ManNodeNum(p), nMembers, nClasses, nFanouts, nNormals );
+ return nFanouts;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops history AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk )
+{
+ Hop_Man_t * pMan, * pManTemp;
+ Abc_Ntk_t * pNtkAig;
+ Abc_Obj_t * pObj;
+ int i;
+
+ // check if HAIG is available
+ assert( Abc_NtkIsStrash(pNtk) );
+ if ( pNtk->pHaig == NULL )
+ {
+ printf( "Warning: History AIG is not available.\n" );
+ return NULL;
+ }
+ // convert HOP package into AIG with choices
+ // print HAIG stats
+// Hop_ManPrintStats( pMan ); // USES DATA!!!
+
+ // add the POs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Hop_ObjCreatePo( pNtk->pHaig, Abc_ObjChild0Equiv(pObj) );
+
+ // clean the old network
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pEquiv = NULL;
+ pMan = pNtk->pHaig;
+ pNtk->pHaig = 0;
+
+ // iteratively reconstruct the HOP manager to create choice nodes
+ while ( Abc_NtkHaigResetReprs( pMan ) )
+ {
+ pMan = Abc_NtkHaigReconstruct( pManTemp = pMan );
+ Hop_ManStop( pManTemp );
+ }
+
+ // traverse in the topological order and create new AIG
+ pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan );
+ Hop_ManStop( pMan );
+
+ // free HAIG
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transform HOP manager into the one without loops.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan )
+{
+ Abc_Ntk_t * pNtkAig;
+ Hop_Man_t * pManTemp;
+
+ // iteratively reconstruct the HOP manager to create choice nodes
+ while ( Abc_NtkHaigResetReprs( pMan ) )
+ {
+ pMan = Abc_NtkHaigReconstruct( pManTemp = pMan );
+ Hop_ManStop( pManTemp );
+ }
+
+ // traverse in the topological order and create new AIG
+ pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan );
+ Hop_ManStop( pMan );
+ return pNtkAig;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c
new file mode 100644
index 00000000..bb56c22c
--- /dev/null
+++ b/src/base/abci/abcIf.c
@@ -0,0 +1,497 @@
+/**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"
+#include "kit.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 );
+extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover );
+static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj );
+static Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk );
+
+extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// 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) );
+
+ // get timing information
+ pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk);
+ pPars->pTimesReq = NULL;
+
+ // set the latch paths
+ if ( pPars->fLatchPaths && pPars->pTimesArr )
+ {
+ int c;
+ for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ )
+ pPars->pTimesArr[c] = -ABC_INFINITY;
+ }
+
+ // 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 the new 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;
+ Vec_Ptr_t * vNodes;
+ int i;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+// vNodes = Abc_NtkFindGoodOrder( pNtk );
+ vNodes = Abc_AigDfs( pNtk, 0, 0 );
+
+ // start the mapping manager and set its parameters
+ pIfMan = If_ManStart( pPars );
+
+ // print warning about excessive memory usage
+ if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 )
+ printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n",
+ 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) );
+
+ // create PIs and remember them in the old nodes
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan );
+//printf( "AIG CI %2d -> IF CI %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id );
+ }
+
+ // load the AIG into the mapper
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+// Abc_AigForEachAnd( pNtk, pNode, i )
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, "Initial" );
+ // add the node to the mapper
+ pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan,
+ If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
+ If_NotCond( (If_Obj_t *)Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) );
+ // set up the choice node
+ if ( Abc_AigNodeIsChoice( pNode ) )
+ {
+ pIfMan->nChoices++;
+ for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
+ If_ObjSetChoice( (If_Obj_t *)pPrev->pCopy, (If_Obj_t *)pFanin->pCopy );
+ If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pCopy );
+ }
+//printf( "AIG node %2d -> IF node %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+
+ // set the primary outputs without copying the phase
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) );
+ 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;
+ Vec_Int_t * vCover;
+ int i, nDupGates;
+ // create the new network
+ if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+ else if ( pIfMan->pPars->fUseSops )
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+ else
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
+ // prepare the mapping manager
+ If_ManCleanNodeCopy( pIfMan );
+ If_ManCleanCutData( pIfMan );
+ // make the mapper point to the new network
+ If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ If_ObjSetCopy( If_ManCi(pIfMan, i), pNode->pCopy );
+ // process the nodes in topological order
+ vCover = Vec_IntAlloc( 1 << 16 );
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, "Final" );
+ pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManCo(pIfMan, i)), vCover );
+ pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManCo(pIfMan, i)) );
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_IntFree( vCover );
+ // remove the constant node if not used
+ pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) );
+ if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
+ Abc_NtkDeleteObj( pNodeNew );
+ // minimize the node
+ if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+ Abc_NtkSweep( pNtkNew, 0 );
+ if ( pIfMan->pPars->fUseBdds )
+ Abc_NtkBddReorder( pNtkNew, 0 );
+ // decouple the PO driver nodes to reduce the number of levels
+ nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 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, Vec_Int_t * vCover )
+{
+ Abc_Obj_t * pNodeNew;
+ If_Cut_t * pCutBest;
+ If_Obj_t * pIfLeaf;
+ int i;
+ // return if the result if known
+ pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj );
+ if ( pNodeNew )
+ return pNodeNew;
+ assert( pIfObj->Type == IF_AND );
+ // get the parameters of the best cut
+ // create a new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pCutBest = If_ObjCutBest( pIfObj );
+ if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+ {
+ If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i )
+ Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
+ }
+ else
+ {
+ If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
+ Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
+ }
+ // set the level of the new node
+ pNodeNew->Level = Abc_ObjLevelNew( pNodeNew );
+ // derive the function of this node
+ if ( pIfMan->pPars->fTruth )
+ {
+ if ( pIfMan->pPars->fUseBdds )
+ {
+ // transform truth table into the BDD
+ pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 0 ); Cudd_Ref(pNodeNew->pData);
+ }
+ else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
+ {
+ // transform truth table into the BDD
+ pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 1 ); Cudd_Ref(pNodeNew->pData);
+ }
+ else if ( pIfMan->pPars->fUseSops )
+ {
+ // transform truth table into the SOP
+ int RetValue = Kit_TruthIsop( If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 );
+ assert( RetValue == 0 || RetValue == 1 );
+ // check the case of constant cover
+ if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) )
+ {
+ assert( RetValue == 0 );
+ pNodeNew->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), NULL );
+ pNodeNew = (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew);
+ }
+ else
+ {
+ // derive the AIG for that tree
+ pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), vCover );
+ if ( RetValue )
+ Abc_SopComplement( pNodeNew->pData );
+ }
+ }
+ else
+ {
+ extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+ pNodeNew->pData = Kit_TruthToHop( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover );
+ }
+ // complement the node if the cut was complemented
+ if ( pCutBest->fCompl )
+ Abc_NodeComplement( pNodeNew );
+ }
+ else
+ pNodeNew->pData = Abc_NodeIfToHop( pNtkNew->pManFunc, pIfMan, pIfObj );
+ If_ObjSetCopy( pIfObj, pNodeNew );
+ return pNodeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively derives the truth table for the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
+{
+ If_Cut_t * pCut;
+ Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
+ // get the best cut
+ pCut = If_ObjCutBest(pIfObj);
+ // if the cut is visited, return the result
+ if ( If_CutData(pCut) )
+ return If_CutData(pCut);
+ // compute the functions of the children
+ gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited );
+ gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited );
+ // get the function of the cut
+ gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) );
+ assert( If_CutData(pCut) == NULL );
+ If_CutSetData( pCut, gFunc );
+ // add this cut to the visited list
+ Vec_PtrPush( vVisited, pCut );
+ return gFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the truth table for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj )
+{
+ If_Cut_t * pCut;
+ Hop_Obj_t * gFunc;
+ If_Obj_t * pLeaf;
+ int i;
+ // get the best cut
+ pCut = If_ObjCutBest(pIfObj);
+ assert( pCut->nLeaves > 1 );
+ // set the leaf variables
+ If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+ If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) );
+ // recursively compute the function while collecting visited cuts
+ Vec_PtrClear( pIfMan->vTemp );
+ gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp );
+// printf( "%d ", Vec_PtrSize(p->vTemp) );
+ // clean the cuts
+ If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+ If_CutSetData( If_ObjCutBest(pLeaf), NULL );
+ Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i )
+ If_CutSetData( pCut, NULL );
+ return gFunc;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Comparison for two nodes with the flow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjCompareFlow( Abc_Obj_t ** ppNode0, Abc_Obj_t ** ppNode1 )
+{
+ float Flow0 = Abc_Int2Float((int)(*ppNode0)->pCopy);
+ float Flow1 = Abc_Int2Float((int)(*ppNode1)->pCopy);
+ if ( Flow0 > Flow1 )
+ return -1;
+ if ( Flow0 < Flow1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Orders AIG nodes so that nodes from larger cones go first.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFindGoodOrder_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ if ( !Abc_ObjIsNode(pNode) )
+ return;
+ assert( Abc_ObjIsNode( pNode ) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pNode ) )
+ return;
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // visit the transitive fanin of the node
+ Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes );
+ Abc_NtkFindGoodOrder_rec( Abc_ObjFanin1(pNode), vNodes );
+ // add the node after the fanins have been added
+ Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Orders AIG nodes so that nodes from larger cones go first.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes, * vCos;
+ Abc_Obj_t * pNode, * pFanin0, * pFanin1;
+ float Flow0, Flow1;
+ int i;
+
+ // initialize the flow
+ Abc_AigConst1(pNtk)->pCopy = NULL;
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy = NULL;
+ // compute the flow
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ pFanin0 = Abc_ObjFanin0(pNode);
+ pFanin1 = Abc_ObjFanin1(pNode);
+ Flow0 = Abc_Int2Float((int)pFanin0->pCopy)/Abc_ObjFanoutNum(pFanin0);
+ Flow1 = Abc_Int2Float((int)pFanin1->pCopy)/Abc_ObjFanoutNum(pFanin1);
+ pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int(Flow0 + Flow1+(float)1.0);
+ }
+ // find the flow of the COs
+ vCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy;
+// pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int((float)Abc_ObjFanin0(pNode)->Level);
+ Vec_PtrPush( vCos, pNode );
+ }
+
+ // sort nodes in the increasing order of the flow
+ qsort( (Abc_Obj_t **)Vec_PtrArray(vCos), Abc_NtkCoNum(pNtk),
+ sizeof(Abc_Obj_t *), (int (*)(const void *, const void *))Abc_ObjCompareFlow );
+ // verify sorting
+ pFanin0 = Vec_PtrEntry(vCos, 0);
+ pFanin1 = Vec_PtrEntryLast(vCos);
+ assert( Abc_Int2Float((int)pFanin0->pCopy) >= Abc_Int2Float((int)pFanin1->pCopy) );
+
+ // collect the nodes in the topological order from the new array
+ Abc_NtkIncrementTravId( pNtk );
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( vCos, pNode, i )
+ {
+ Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes );
+// printf( "%.2f ", Abc_Int2Float((int)pNode->pCopy) );
+ }
+ Vec_PtrFree( vCos );
+ return vNodes;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c
new file mode 100644
index 00000000..a470448e
--- /dev/null
+++ b/src/base/abci/abcIvy.c
@@ -0,0 +1,1105 @@
+/**CFile****************************************************************
+
+ FileName [abcIvy.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Strashing of the current network.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcIvy.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+#include "ivy.h"
+#include "fraig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan );
+static Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig );
+static Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld );
+
+static void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan );
+static Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode );
+static Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+static Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+static Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop );
+extern char * Mio_GateReadSop( void * pGate );
+
+typedef int Abc_Edge_t;
+static inline Abc_Edge_t Abc_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; }
+static inline int Abc_EdgeId( Abc_Edge_t Edge ) { return Edge >> 1; }
+static inline int Abc_EdgeIsComplement( Abc_Edge_t Edge ) { return Edge & 1; }
+static inline Abc_Edge_t Abc_EdgeRegular( Abc_Edge_t Edge ) { return (Edge >> 1) << 1; }
+static inline Abc_Edge_t Abc_EdgeNot( Abc_Edge_t Edge ) { return Edge ^ 1; }
+static inline Abc_Edge_t Abc_EdgeNotCond( Abc_Edge_t Edge, int fCond ) { return Edge ^ fCond; }
+static inline Abc_Edge_t Abc_EdgeFromNode( Abc_Obj_t * pNode ) { return Abc_EdgeCreate( Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ); }
+static inline Abc_Obj_t * Abc_EdgeToNode( Abc_Ntk_t * p, Abc_Edge_t Edge ) { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_EdgeId(Edge)), Abc_EdgeIsComplement(Edge) ); }
+
+static inline Abc_Obj_t * Abc_ObjFanin0Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ); }
+static inline Abc_Obj_t * Abc_ObjFanin1Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ); }
+
+static Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs );
+
+extern int timeRetime;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the IVY package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc )
+{
+ Ivy_Man_t * pMan;
+ int fCleanup = 1;
+//timeRetime = clock();
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ if ( Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Abc_NtkIvyBefore(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
+ }
+ if ( fSeq && Abc_NtkCountSelfFeedLatches(pNtk) )
+ {
+ printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
+// return NULL;
+ }
+ // print warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" );
+ // convert to the AIG manager
+ pMan = Abc_NtkToIvy( pNtk );
+ if ( !Ivy_ManCheck( pMan ) )
+ {
+ printf( "AIG check has failed.\n" );
+ Ivy_ManStop( pMan );
+ return NULL;
+ }
+// Ivy_ManPrintStats( pMan );
+ if ( fSeq )
+ {
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, fUseDc );
+ Ivy_ManMakeSeq( pMan, nLatches, vInit->pArray );
+ Vec_IntFree( vInit );
+// Ivy_ManPrintStats( pMan );
+ }
+//timeRetime = clock() - timeRetime;
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the IVY package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyAfter( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan, int fSeq, int fHaig )
+{
+ Abc_Ntk_t * pNtkAig;
+ int nNodes, fCleanup = 1;
+ // convert from the AIG manager
+ if ( fSeq )
+ pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan, fHaig );
+ else
+ pNtkAig = Abc_NtkFromIvy( pNtk, pMan );
+ // report the cleanup results
+ if ( !fHaig && fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+ printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;
+ pMan = Abc_NtkIvyBefore( pNtk, 1, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;
+ int clk;
+// int i;
+/*
+extern int nMoves;
+extern int nMovesS;
+extern int nClauses;
+extern int timeInv;
+
+nMoves = 0;
+nMovesS = 0;
+nClauses = 0;
+timeInv = 0;
+*/
+ pMan = Abc_NtkIvyBefore( pNtk, 1, 1 );
+ if ( pMan == NULL )
+ return NULL;
+//timeRetime = clock();
+
+clk = clock();
+ Ivy_ManHaigStart( pMan, fVerbose );
+// Ivy_ManRewriteSeq( pMan, 0, 0 );
+// for ( i = 0; i < nIters; i++ )
+// Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 );
+
+//printf( "%d ", Ivy_ManNodeNum(pMan) );
+ Ivy_ManRewriteSeq( pMan, 0, 0 );
+ Ivy_ManRewriteSeq( pMan, 0, 0 );
+ Ivy_ManRewriteSeq( pMan, 1, 0 );
+//printf( "%d ", Ivy_ManNodeNum(pMan) );
+//printf( "%d ", Ivy_ManNodeNum(pMan->pHaig) );
+//PRT( " ", clock() - clk );
+//printf( "\n" );
+/*
+ printf( "Moves = %d. ", nMoves );
+ printf( "MovesS = %d. ", nMovesS );
+ printf( "Clauses = %d. ", nClauses );
+ PRT( "Time", timeInv );
+*/
+// 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 );
+ // write HAIG into the current network
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan->pHaig, 1, 1 );
+
+ Ivy_ManHaigStop( pMan );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs )
+{
+ extern void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs );
+ Ivy_Man_t * pMan;
+ pMan = Abc_NtkIvyBefore( pNtk, 1, 0 );
+ if ( pMan == NULL )
+ return;
+ Ivy_CutComputeAll( pMan, nInputs );
+ Ivy_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+//timeRetime = clock();
+ Ivy_ManRewritePre( pMan, fUpdateLevel, fUseZeroCost, fVerbose );
+//timeRetime = clock() - timeRetime;
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;
+ pMan = Abc_NtkIvyBefore( pNtk, 1, 1 );
+ if ( pMan == NULL )
+ return NULL;
+//timeRetime = 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 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyResyn0( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Ivy_ManResyn0( pTemp = pMan, fUpdateLevel, fVerbose );
+ Ivy_ManStop( pTemp );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Ivy_ManResyn( pTemp = pMan, fUpdateLevel, fVerbose );
+ Ivy_ManStop( pTemp );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose )
+{
+ Ivy_FraigParams_t Params, * pParams = &Params;
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ Ivy_FraigParamsDefault( pParams );
+ pParams->nBTLimitMiter = nConfLimit;
+ pParams->fVerbose = fVerbose;
+// pMan = Ivy_FraigPerform( pTemp = pMan, pParams );
+ pMan = Ivy_FraigMiter( pTemp = pMan, pParams );
+ Ivy_ManStop( pTemp );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the final nodes to point to the original nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig )
+{
+ Abc_Obj_t * pObj;
+ Ivy_Obj_t * pObjIvy, * pObjFraig;
+ int i;
+ pObj = Abc_AigConst1(pNtk);
+ pObj->pCopy = Abc_AigConst1(pNtkAig);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkCi(pNtkAig, i);
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkCo(pNtkAig, i);
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkBox(pNtkAig, i);
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ pObjIvy = (Ivy_Obj_t *)pObj->pCopy;
+ if ( pObjIvy == NULL )
+ continue;
+ pObjFraig = Ivy_ObjEquiv( pObjIvy );
+ if ( pObjFraig == NULL )
+ continue;
+ pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId );
+ pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose )
+{
+ Ivy_FraigParams_t Params, * pParams = &Params;
+ Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ Ivy_FraigParamsDefault( pParams );
+ pParams->nBTLimitNode = nConfLimit;
+ pParams->fVerbose = fVerbose;
+ pParams->fProve = fProve;
+ pParams->fDoSparse = fDoSparse;
+ pMan = Ivy_FraigPerform( pTemp = pMan, pParams );
+ // transfer the pointers
+ if ( fTransfer == 1 )
+ {
+ Vec_Ptr_t * vCopies;
+ vCopies = Abc_NtkSaveCopy( pNtk );
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Abc_NtkLoadCopy( pNtk, vCopies );
+ Vec_PtrFree( vCopies );
+ Abc_NtkTransferPointers( pNtk, pNtkAig );
+ }
+ else
+ pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 );
+ Ivy_ManStop( pTemp );
+ Ivy_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars )
+{
+ Prove_Params_t * pParams = pPars;
+ Abc_Ntk_t * pNtk = *ppNtk, * pNtkTemp;
+ Abc_Obj_t * pObj, * pFanin;
+ Ivy_Man_t * pMan;
+ int RetValue;
+ assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
+ // experiment with various parameters settings
+// pParams->fUseBdds = 1;
+// pParams->fBddReorder = 1;
+// pParams->nTotalBacktrackLimit = 10000;
+
+ // strash the network if it is not strashed already
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk = Abc_NtkStrash( pNtkTemp = pNtk, 0, 1, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ }
+
+ // check the case when the 0000 simulation pattern detect the bug
+ pObj = Abc_NtkPo(pNtk,0);
+ pFanin = Abc_ObjFanin0(pObj);
+ if ( Abc_ObjFanin0(pObj)->fPhase != (unsigned)Abc_ObjFaninC0(pObj) )
+ {
+ pNtk->pModel = ALLOC( int, Abc_NtkPiNum(pNtk) );
+ memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkPiNum(pNtk) );
+ return 0;
+ }
+
+ // if SAT only, solve without iteration
+ RetValue = Abc_NtkMiterSat( pNtk, 2*(sint64)pParams->nMiteringLimitStart, (sint64)0, 0, NULL, NULL );
+ if ( RetValue >= 0 )
+ return RetValue;
+
+ // apply AIG rewriting
+ if ( pParams->fUseRewriting && Abc_NtkNodeNum(pNtk) > 500 )
+ {
+// int clk = clock();
+//printf( "Before rwsat = %d. ", Abc_NtkNodeNum(pNtk) );
+ pParams->fUseRewriting = 0;
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+//printf( "After rwsat = %d. ", Abc_NtkNodeNum(pNtk) );
+//PRT( "Time", clock() - clk );
+ }
+
+ // convert ABC network into IVY network
+ pMan = Abc_NtkIvyBefore( pNtk, 0, 0 );
+
+ // solve the CEC problem
+ RetValue = Ivy_FraigProve( &pMan, pParams );
+ // convert IVY network into ABC network
+ pNtk = Abc_NtkIvyAfter( pNtkTemp = pNtk, pMan, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ // transfer model if given
+ pNtk->pModel = pMan->pData; pMan->pData = NULL;
+ Ivy_ManStop( pMan );
+
+ // try to prove it using brute force SAT
+ if ( RetValue < 0 && pParams->fUseBdds )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit );
+ fflush( stdout );
+ }
+ pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 );
+ if ( pNtk )
+ {
+ Abc_NtkDelete( pNtkTemp );
+ RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) );
+ }
+ else
+ pNtk = pNtkTemp;
+ }
+
+ // return the result
+ *ppNtk = pNtk;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk )
+{
+// Abc_Ntk_t * pNtkAig;
+ Ivy_Man_t * pMan;//, * pTemp;
+ int fCleanup = 1;
+// int nNodes;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, 0 );
+
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ if ( Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ Vec_IntFree( vInit );
+ printf( "Abc_NtkIvy(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
+ }
+ if ( Abc_NtkCountSelfFeedLatches(pNtk) )
+ {
+ printf( "Warning: The network has %d self-feeding latches. Quitting.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
+ return NULL;
+ }
+
+ // print warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" );
+
+ // convert to the AIG manager
+ pMan = Abc_NtkToIvy( pNtk );
+ if ( !Ivy_ManCheck( pMan ) )
+ {
+ Vec_IntFree( vInit );
+ printf( "AIG check has failed.\n" );
+ Ivy_ManStop( pMan );
+ return NULL;
+ }
+
+// Ivy_MffcTest( pMan );
+// Ivy_ManPrintStats( pMan );
+
+// pMan = Ivy_ManBalance( pTemp = pMan, 1 );
+// Ivy_ManStop( pTemp );
+
+// Ivy_ManSeqRewrite( pMan, 0, 0 );
+// Ivy_ManTestCutsAlg( pMan );
+// Ivy_ManTestCutsBool( pMan );
+// Ivy_ManRewriteAlg( pMan, 1, 1 );
+
+// pMan = Ivy_ManResyn( pTemp = pMan, 1, 0 );
+// Ivy_ManStop( pTemp );
+
+// Ivy_ManTestCutsAll( pMan );
+// Ivy_ManTestCutsTravAll( pMan );
+
+// Ivy_ManPrintStats( pMan );
+
+// Ivy_ManPrintStats( pMan );
+// Ivy_ManRewritePre( pMan, 1, 0, 0 );
+// Ivy_ManPrintStats( pMan );
+// printf( "\n" );
+
+// Ivy_ManPrintStats( pMan );
+// Ivy_ManMakeSeq( pMan, nLatches, pInit );
+// Ivy_ManPrintStats( pMan );
+
+// Ivy_ManRequiredLevels( pMan );
+
+// Ivy_FastMapPerform( pMan, 8 );
+ Ivy_ManStop( pMan );
+ return NULL;
+
+
+/*
+ // convert from the AIG manager
+ pNtkAig = Abc_NtkFromIvy( pNtk, pMan );
+// pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan );
+ Ivy_ManStop( pMan );
+
+ // report the cleanup results
+ if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+ printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ FREE( pInit );
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+
+ FREE( pInit );
+ return pNtkAig;
+*/
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan )
+{
+ Vec_Int_t * vNodes;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+ Ivy_Obj_t * pNode;
+ int i;
+ // perform strashing
+ pNtk = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) );
+ Abc_NtkForEachCi( pNtkOld, pObj, i )
+ Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy );
+ // rebuild the AIG
+ vNodes = Ivy_ManDfs( pMan );
+ Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i )
+ {
+ // add the first fanin
+ pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode );
+ if ( Ivy_ObjIsBuf(pNode) )
+ {
+ pNode->TravId = Abc_EdgeFromNode( pFaninNew0 );
+ continue;
+ }
+ // add the second fanin
+ pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode );
+ // create the new node
+ if ( Ivy_ObjIsExor(pNode) )
+ pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+ else
+ pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+ pNode->TravId = Abc_EdgeFromNode( pObjNew );
+ }
+ // connect the PO nodes
+ Abc_NtkForEachCo( pNtkOld, pObj, i )
+ {
+ pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+ Vec_IntFree( vNodes );
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkFromIvy(): Network check has failed.\n" );
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig )
+{
+ Vec_Int_t * vNodes, * vLatches;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1;
+ Ivy_Obj_t * pNode, * pTemp;
+ int i;
+// assert( Ivy_ManLatchNum(pMan) > 0 );
+ // perform strashing
+ pNtk = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // transfer the pointers to the basic nodes
+ Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) );
+ Abc_NtkForEachPi( pNtkOld, pObj, i )
+ Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy );
+ // create latches of the new network
+ vNodes = Ivy_ManDfsSeq( pMan, &vLatches );
+ Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i )
+ {
+ pObjNew = Abc_NtkCreateLatch( pNtk );
+ pFaninNew0 = Abc_NtkCreateBi( pNtk );
+ pFaninNew1 = Abc_NtkCreateBo( pNtk );
+ Abc_ObjAddFanin( pObjNew, pFaninNew0 );
+ Abc_ObjAddFanin( pFaninNew1, pObjNew );
+ if ( fHaig || Ivy_ObjInit(pNode) == IVY_INIT_DC )
+ Abc_LatchSetInitDc( pObjNew );
+ else if ( Ivy_ObjInit(pNode) == IVY_INIT_1 )
+ Abc_LatchSetInit1( pObjNew );
+ else if ( Ivy_ObjInit(pNode) == IVY_INIT_0 )
+ Abc_LatchSetInit0( pObjNew );
+ else assert( 0 );
+ pNode->TravId = Abc_EdgeFromNode( pFaninNew1 );
+ }
+ Abc_NtkAddDummyBoxNames( pNtk );
+ // rebuild the AIG
+ Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i )
+ {
+ // add the first fanin
+ pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode );
+ if ( Ivy_ObjIsBuf(pNode) )
+ {
+ pNode->TravId = Abc_EdgeFromNode( pFaninNew0 );
+ continue;
+ }
+ // add the second fanin
+ pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode );
+ // create the new node
+ if ( Ivy_ObjIsExor(pNode) )
+ pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+ else
+ pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 );
+ pNode->TravId = Abc_EdgeFromNode( pObjNew );
+ // process the choice nodes
+ if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 )
+ {
+ pFaninNew = Abc_EdgeToNode( pNtk, pNode->TravId );
+// pFaninNew->fPhase = 0;
+ assert( !Ivy_IsComplement(pNode->pEquiv) );
+ for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) )
+ {
+ pFaninNew1 = Abc_EdgeToNode( pNtk, pTemp->TravId );
+// pFaninNew1->fPhase = Ivy_IsComplement( pTemp->pEquiv );
+ pFaninNew->pData = pFaninNew1;
+ pFaninNew = pFaninNew1;
+ }
+ pFaninNew->pData = NULL;
+// printf( "Writing choice node %d.\n", pNode->Id );
+ }
+ }
+ // connect the PO nodes
+ Abc_NtkForEachPo( pNtkOld, pObj, i )
+ {
+ pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) );
+ Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
+ }
+ // connect the latches
+ Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i )
+ {
+ pFaninNew = Abc_ObjFanin0Ivy( pNtk, pNode );
+ Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(pNtk, i)), pFaninNew );
+ }
+ Vec_IntFree( vLatches );
+ Vec_IntFree( vNodes );
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" );
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld )
+{
+ Ivy_Man_t * pMan;
+ Abc_Obj_t * pObj;
+ Ivy_Obj_t * pFanin;
+ int i;
+ // create the manager
+ assert( Abc_NtkHasSop(pNtkOld) || Abc_NtkIsStrash(pNtkOld) );
+ pMan = Ivy_ManStart();
+ // create the PIs
+ if ( Abc_NtkIsStrash(pNtkOld) )
+ Abc_AigConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Ivy_ManConst1(pMan);
+ Abc_NtkForEachCi( pNtkOld, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Ivy_ObjCreatePi(pMan);
+ // perform the conversion of the internal nodes
+ Abc_NtkStrashPerformAig( pNtkOld, pMan );
+ // create the POs
+ Abc_NtkForEachCo( pNtkOld, pObj, i )
+ {
+ pFanin = (Ivy_Obj_t *)Abc_ObjFanin0(pObj)->pCopy;
+ pFanin = Ivy_NotCond( pFanin, Abc_ObjFaninC0(pObj) );
+ Ivy_ObjCreatePo( pMan, pFanin );
+ }
+ Ivy_ManCleanup( pMan );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the network for strashing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan )
+{
+// ProgressBar * pProgress;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
+ int i;
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+// pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+// Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNode->pCopy = (Abc_Obj_t *)Abc_NodeStrashAig( pMan, pNode );
+ }
+// Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode )
+{
+ int fUseFactor = 1;
+ char * pSop;
+ Ivy_Obj_t * pFanin0, * pFanin1;
+
+ assert( Abc_ObjIsNode(pNode) );
+
+ // consider the case when the graph is an AIG
+ if ( Abc_NtkIsStrash(pNode->pNtk) )
+ {
+ if ( Abc_AigNodeIsConst(pNode) )
+ return Ivy_ManConst1(pMan);
+ pFanin0 = (Ivy_Obj_t *)Abc_ObjFanin0(pNode)->pCopy;
+ pFanin0 = Ivy_NotCond( pFanin0, Abc_ObjFaninC0(pNode) );
+ pFanin1 = (Ivy_Obj_t *)Abc_ObjFanin1(pNode)->pCopy;
+ pFanin1 = Ivy_NotCond( pFanin1, Abc_ObjFaninC1(pNode) );
+ return Ivy_And( pMan, pFanin0, pFanin1 );
+ }
+
+ // get the SOP of the node
+ if ( Abc_NtkHasMapping(pNode->pNtk) )
+ pSop = Mio_GateReadSop(pNode->pData);
+ else
+ pSop = pNode->pData;
+
+ // consider the constant node
+ if ( Abc_NodeIsConst(pNode) )
+ return Ivy_NotCond( Ivy_ManConst1(pMan), Abc_SopIsConst0(pSop) );
+
+ // consider the special case of EXOR function
+ if ( Abc_SopIsExorType(pSop) )
+ return Abc_NodeStrashAigExorAig( pMan, pNode, pSop );
+
+ // decide when to use factoring
+ if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 )
+ return Abc_NodeStrashAigFactorAig( pMan, pNode, pSop );
+ return Abc_NodeStrashAigSopAig( pMan, pNode, pSop );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop )
+{
+ Abc_Obj_t * pFanin;
+ Ivy_Obj_t * pAnd, * pSum;
+ char * pCube;
+ int i, nFanins;
+
+ // get the number of node's fanins
+ nFanins = Abc_ObjFaninNum( pNode );
+ assert( nFanins == Abc_SopGetVarNum(pSop) );
+ // go through the cubes of the node's SOP
+ pSum = Ivy_Not( Ivy_ManConst1(pMan) );
+ Abc_SopForEachCube( pSop, nFanins, pCube )
+ {
+ // create the AND of literals
+ pAnd = Ivy_ManConst1(pMan);
+ Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net
+ {
+ if ( pCube[i] == '1' )
+ pAnd = Ivy_And( pMan, pAnd, (Ivy_Obj_t *)pFanin->pCopy );
+ else if ( pCube[i] == '0' )
+ pAnd = Ivy_And( pMan, pAnd, Ivy_Not((Ivy_Obj_t *)pFanin->pCopy) );
+ }
+ // add to the sum of cubes
+ pSum = Ivy_Or( pMan, pSum, pAnd );
+ }
+ // decide whether to complement the result
+ if ( Abc_SopIsComplement(pSop) )
+ pSum = Ivy_Not(pSum);
+ return pSum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashed n-input XOR function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop )
+{
+ Abc_Obj_t * pFanin;
+ Ivy_Obj_t * pSum;
+ int i, nFanins;
+ // get the number of node's fanins
+ nFanins = Abc_ObjFaninNum( pNode );
+ assert( nFanins == Abc_SopGetVarNum(pSop) );
+ // go through the cubes of the node's SOP
+ pSum = Ivy_Not( Ivy_ManConst1(pMan) );
+ for ( i = 0; i < nFanins; i++ )
+ {
+ pFanin = Abc_ObjFanin( pNode, i );
+ pSum = Ivy_Exor( pMan, pSum, (Ivy_Obj_t *)pFanin->pCopy );
+ }
+ if ( Abc_SopIsComplement(pSop) )
+ pSum = Ivy_Not(pSum);
+ return pSum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pRoot, char * pSop )
+{
+ Dec_Graph_t * pFForm;
+ Dec_Node_t * pNode;
+ Ivy_Obj_t * pAnd;
+ int i;
+
+// extern Ivy_Obj_t * Dec_GraphToNetworkAig( Ivy_Man_t * pMan, Dec_Graph_t * pGraph );
+ extern Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph );
+
+// assert( 0 );
+
+ // perform factoring
+ pFForm = Dec_Factor( pSop );
+ // collect the fanins
+ Dec_GraphForEachLeaf( pFForm, pNode, i )
+ pNode->pFunc = Abc_ObjFanin(pRoot,i)->pCopy;
+ // perform strashing
+// pAnd = Dec_GraphToNetworkAig( pMan, pFForm );
+ pAnd = Dec_GraphToNetworkIvy( pMan, pFForm );
+// pAnd = NULL;
+
+ Dec_GraphFree( pFForm );
+ return pAnd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs )
+{
+ Abc_Obj_t * pLatch;
+ Vec_Int_t * vArray;
+ int i;
+ vArray = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( fUseDcs || Abc_LatchIsInitDc(pLatch) )
+ Vec_IntPush( vArray, IVY_INIT_DC );
+ else if ( Abc_LatchIsInit1(pLatch) )
+ Vec_IntPush( vArray, IVY_INIT_1 );
+ else if ( Abc_LatchIsInit0(pLatch) )
+ Vec_IntPush( vArray, IVY_INIT_0 );
+ else assert( 0 );
+ }
+ return vArray;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcLut.c b/src/base/abci/abcLut.c
new file mode 100644
index 00000000..afa76cc8
--- /dev/null
+++ b/src/base/abci/abcLut.c
@@ -0,0 +1,786 @@
+/**CFile****************************************************************
+
+ FileName [abcLut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Superchoicing for K-LUTs.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "cut.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define SCL_LUT_MAX 6 // the maximum LUT size
+#define SCL_VARS_MAX 15 // the maximum number of variables
+#define SCL_NODE_MAX 1000 // the maximum number of nodes
+
+typedef struct Abc_ManScl_t_ Abc_ManScl_t;
+struct Abc_ManScl_t_
+{
+ // paramers
+ int nLutSize; // the LUT size
+ int nCutSizeMax; // the max number of leaves of the cone
+ int nNodesMax; // the max number of divisors in the cone
+ int nWords; // the number of machine words in sim info
+ // structural representation of the cone
+ Vec_Ptr_t * vLeaves; // leaves of the cut
+ Vec_Ptr_t * vVolume; // volume of the cut
+ int pBSet[SCL_VARS_MAX]; // bound set
+ // functional representation of the cone
+ unsigned * uTruth; // truth table of the cone
+ // representation of truth tables
+ unsigned ** uVars; // elementary truth tables
+ unsigned ** uSims; // truth tables of the nodes
+ unsigned ** uCofs; // truth tables of the cofactors
+};
+
+static Vec_Ptr_t * s_pLeaves = NULL;
+
+static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize );
+static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax );
+static void Abc_ManSclStop( Abc_ManScl_t * p );
+static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj );
+
+static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj );
+static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for K-LUTs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_ManCut_t * pManCut;
+ Abc_ManScl_t * pManScl;
+ Cut_Man_t * pManCuts;
+ Abc_Obj_t * pObj, * pFanin, * pObjTop;
+ int i, LevelMax, nNodes;
+ int nNodesTried, nNodesDec, nNodesExist, nNodesUsed;
+
+ assert( Abc_NtkIsSopLogic(pNtk) );
+ if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX )
+ {
+ printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX );
+ return 0;
+ }
+ if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX )
+ {
+ printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX );
+ return 0;
+ }
+
+ assert( nLutSize <= SCL_LUT_MAX );
+ assert( nCutSizeMax <= SCL_VARS_MAX );
+ nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0;
+
+ // set the delays of the CIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->Level = 0;
+
+//Abc_NtkLevel( pNtk );
+
+ // start the managers
+ pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 );
+ pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize );
+ pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 );
+ s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut );
+ pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut );
+
+ // process each internal node (assuming topological order of nodes!!!)
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+// if ( i != nNodes-1 )
+// continue;
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ if ( i >= nNodes )
+ break;
+ if ( Abc_ObjFaninNum(pObj) != 2 )
+ continue;
+ nNodesTried++;
+
+ // map this node using regular cuts
+// pObj->Level = 0;
+ Abc_NodeLutMap( pManCuts, pObj );
+ // compute the cut
+ pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 );
+ if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize )
+ continue;
+ // get the volume of the cut
+ if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX )
+ continue;
+ nNodesDec++;
+
+ // decompose the cut
+ pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj );
+ if ( pObjTop == NULL )
+ continue;
+ nNodesExist++;
+
+ // if there is no delay improvement, skip; otherwise, update level
+ if ( pObjTop->Level >= pObj->Level )
+ {
+ Abc_NtkDeleteObj_rec( pObjTop, 1 );
+ continue;
+ }
+ pObj->Level = pObjTop->Level;
+ nNodesUsed++;
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // delete the managers
+ Abc_ManSclStop( pManScl );
+ Abc_NtkManCutStop( pManCut );
+ Cut_ManStop( pManCuts );
+
+ // get the largest arrival time
+ LevelMax = 0;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ pFanin = Abc_ObjFanin0( pObj );
+ // skip inv/buf
+ if ( Abc_ObjFaninNum(pFanin) == 1 )
+ pFanin = Abc_ObjFanin0( pFanin );
+ // get the new level
+ LevelMax = ABC_MAX( LevelMax, (int)pFanin->Level );
+ }
+
+ if ( fVerbose )
+ printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n",
+ nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize );
+// if ( fVerbose )
+// printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize );
+
+ // clean the data field
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pNext = NULL;
+
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs LUT mapping of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj )
+{
+ Cut_Cut_t * pCut;
+ Abc_Obj_t * pFanin;
+ int i, DelayMax;
+ pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 );
+ assert( pCut != NULL );
+ assert( pObj->Level == 0 );
+ // go through the cuts
+ pObj->Level = ABC_INFINITY;
+ for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
+ {
+ DelayMax = 0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] );
+// assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological
+ if ( DelayMax < (int)pFanin->Level )
+ DelayMax = pFanin->Level;
+ }
+ if ( (int)pObj->Level > DelayMax )
+ pObj->Level = DelayMax;
+ }
+ assert( pObj->Level < ABC_INFINITY );
+ pObj->Level++;
+// printf( "%d(%d) ", pObj->Id, pObj->Level );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize )
+{
+ static Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pManCut;
+ Abc_Obj_t * pObj;
+ int i;
+ // start the cut manager
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = nLutSize; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 500; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 0; // compute sequential cuts
+ pParams->fDrop = 0; // drop cuts on the fly
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pManCut = Cut_ManStart( pParams );
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( pManCut, pObj->Id );
+ return pManCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax )
+{
+ Abc_ManScl_t * p;
+ int i, k;
+ assert( sizeof(unsigned) == 4 );
+ p = ALLOC( Abc_ManScl_t, 1 );
+ memset( p, 0, sizeof(Abc_ManScl_t) );
+ p->nLutSize = nLutSize;
+ p->nCutSizeMax = nCutSizeMax;
+ p->nNodesMax = nNodesMax;
+ p->nWords = Extra_TruthWordNum(nCutSizeMax);
+ // allocate simulation info
+ p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 );
+ p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 );
+ p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 );
+ memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 );
+ // assign elementary truth tables
+ for ( k = 0; k < p->nCutSizeMax; k++ )
+ for ( i = 0; i < p->nWords * 32; i++ )
+ if ( i & (1 << k) )
+ p->uVars[k][i>>5] |= (1 << (i&31));
+ // other data structures
+// p->vBound = Vec_IntAlloc( nCutSizeMax );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManSclStop( Abc_ManScl_t * p )
+{
+// Vec_IntFree( p->vBound );
+ free( p->uVars );
+ free( p->uSims );
+ free( p->uCofs );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData0, * puData1, * puData;
+ char * pSop;
+ int i, k;
+ // set elementary truth tables
+ Vec_PtrForEachEntry( pManScl->vLeaves, pObj, i )
+ pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i];
+ // compute truth tables for internal nodes
+ Vec_PtrForEachEntry( pManScl->vVolume, pObj, i )
+ {
+ // set storage for the node's simulation info
+ pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i];
+ // get pointer to the simulation info
+ puData = (unsigned *)pObj->pNext;
+ puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext;
+ puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext;
+ // simulate
+ pSop = pObj->pData;
+ if ( pSop[0] == '0' && pSop[1] == '0' )
+ for ( k = 0; k < pManScl->nWords; k++ )
+ puData[k] = ~puData0[k] & ~puData1[k];
+ else if ( pSop[0] == '0' )
+ for ( k = 0; k < pManScl->nWords; k++ )
+ puData[k] = ~puData0[k] & puData1[k];
+ else if ( pSop[1] == '0' )
+ for ( k = 0; k < pManScl->nWords; k++ )
+ puData[k] = puData0[k] & ~puData1[k];
+ else
+ for ( k = 0; k < pManScl->nWords; k++ )
+ puData[k] = puData0[k] & puData1[k];
+ }
+ return puData;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume )
+{
+ if ( pObj->fMarkC )
+ return;
+ pObj->fMarkC = 1;
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume );
+ Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume );
+ Vec_PtrPush( vVolume, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkC = 1;
+ Vec_PtrClear( vVolume );
+ Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkC = 0;
+ Vec_PtrForEachEntry( vVolume, pObj, i )
+ pObj->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+ if ( pObj->fMarkB )
+ {
+ Vec_PtrPush( vLeaves, pObj );
+ pObj->fMarkB = 0;
+ }
+ if ( pObj->fMarkC )
+ return;
+ pObj->fMarkC = 1;
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume );
+ Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume );
+ Vec_PtrPush( vVolume, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description [Orders the leaves topologically.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
+{
+ Abc_Obj_t * pObj;
+ int i, nLeaves;
+ nLeaves = Vec_PtrSize(vLeaves);
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkB = pObj->fMarkC = 1;
+ Vec_PtrClear( vVolume );
+ Vec_PtrClear( vLeaves );
+ Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume );
+ assert( Vec_PtrSize(vLeaves) == nLeaves );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkC = 0;
+ Vec_PtrForEachEntry( vVolume, pObj, i )
+ pObj->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars )
+{
+ int i;
+ for ( i = nVars - 1; i >= 0; i-- )
+ if ( uPhase & (1 << i) )
+ Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeGetLevel( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i, Level;
+ Level = 0;
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Level = ABC_MAX( Level, (int)pFanin->Level );
+ return Level + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin, * pObjNew;
+ int i, nVars, uSupport, nSuppVars;
+ // collect the cone using DFS (excluding leaves)
+ Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume );
+ assert( Vec_PtrEntryLast(p->vVolume) == pObj );
+ // compute the truth table
+ p->uTruth = Abc_NodeSuperChoiceTruth( p );
+ // get the support of this truth table
+ nVars = Vec_PtrSize(p->vLeaves);
+ uSupport = Extra_TruthSupport(p->uTruth, nVars);
+ nSuppVars = Extra_WordCountOnes(uSupport);
+ assert( nSuppVars <= nVars );
+ if ( nSuppVars == 0 )
+ {
+ pObj->Level = 0;
+ return NULL;
+ }
+ if ( nSuppVars == 1 )
+ {
+ // find the variable
+ for ( i = 0; i < nVars; i++ )
+ if ( uSupport & (1 << i) )
+ break;
+ assert( i < nVars );
+ pFanin = Vec_PtrEntry( p->vLeaves, i );
+ pObj->Level = pFanin->Level;
+ return NULL;
+ }
+ // support-minimize the truth table
+ if ( nSuppVars != nVars )
+ {
+ Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport );
+ Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars );
+ Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars );
+ }
+// return NULL;
+ // decompose the truth table recursively
+ while ( Vec_PtrSize(p->vLeaves) > p->nLutSize )
+ if ( !Abc_NodeDecomposeStep( p ) )
+ {
+ Vec_PtrForEachEntry( p->vLeaves, pFanin, i )
+ if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 )
+ Abc_NtkDeleteObj_rec( pFanin, 1 );
+ return NULL;
+ }
+ // create the topmost node
+ pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pFanin, i )
+ Abc_ObjAddFanin( pObjNew, pFanin );
+ // create the function
+ pObjNew->pData = Abc_SopCreateFromTruth( pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP
+ pObjNew->Level = Abc_NodeGetLevel( pObjNew );
+ return pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Procedure used for sorting the nodes in increasing order of levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 )
+{
+ Abc_Obj_t * pNode1, * pNode2;
+ pNode1 = Vec_PtrEntry(s_pLeaves, *pp1);
+ pNode2 = Vec_PtrEntry(s_pLeaves, *pp2);
+ if ( pNode1->Level < pNode2->Level )
+ return -1;
+ if ( pNode1->Level > pNode2->Level )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Selects the earliest arriving nodes from the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize )
+{
+ Abc_Obj_t * pTemp[SCL_VARS_MAX];
+ int i, k, kBest, LevelMin;
+ assert( nLutSize < nVars );
+ assert( nVars <= SCL_VARS_MAX );
+ // copy nodes into the internal storage
+// printf( "(" );
+ for ( i = 0; i < nVars; i++ )
+ {
+ pTemp[i] = pLeaves[i];
+// printf( " %d", pLeaves[i]->Level );
+ }
+// printf( " )\n" );
+ // choose one node at a time
+ for ( i = 0; i < nLutSize; i++ )
+ {
+ kBest = -1;
+ LevelMin = ABC_INFINITY;
+ for ( k = 0; k < nVars; k++ )
+ if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level )
+ {
+ LevelMin = pTemp[k]->Level;
+ kBest = k;
+ }
+ pBSet[i] = kBest;
+ pTemp[kBest] = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs superchoicing for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeDecomposeStep( Abc_ManScl_t * p )
+{
+ static char pCofClasses[1<<SCL_LUT_MAX][1<<SCL_LUT_MAX];
+ static char nCofClasses[1<<SCL_LUT_MAX];
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pObjNew, * pFanin, * pNodesNew[SCL_LUT_MAX];
+ unsigned * pTruthCof, * pTruthClass, * pTruth, uPhase;
+ int i, k, c, v, w, nVars, nVarsNew, nClasses, nCofs;
+ // set the network
+ pNtk = ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, 0))->pNtk;
+ // find the earliest nodes
+ nVars = Vec_PtrSize(p->vLeaves);
+ assert( nVars > p->nLutSize );
+/*
+ for ( v = 0; v < nVars; v++ )
+ p->pBSet[v] = v;
+ qsort( (void *)p->pBSet, nVars, sizeof(int),
+ (int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc );
+*/
+ Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize );
+ assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <=
+ ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level );
+ // cofactor w.r.t. the selected variables
+ Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars );
+ c = 2;
+ for ( v = 0; v < p->nLutSize; v++ )
+ for ( k = 0; k < (1<<v); k++ )
+ {
+ Extra_TruthCopy( p->uCofs[c], p->uCofs[c/2], nVars );
+ Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars );
+ Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] );
+ Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] );
+ c += 2;
+ }
+ assert( c == (2 << p->nLutSize) );
+ // count unique cofactors
+ nClasses = 0;
+ nCofs = (1 << p->nLutSize);
+ for ( i = 0; i < nCofs; i++ )
+ {
+ pTruthCof = p->uCofs[ nCofs + i ];
+ for ( k = 0; k < nClasses; k++ )
+ {
+ pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ];
+ if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) )
+ {
+ pCofClasses[k][ nCofClasses[k]++ ] = i;
+ break;
+ }
+ }
+ if ( k != nClasses )
+ continue;
+ // not found
+ pCofClasses[nClasses][0] = i;
+ nCofClasses[nClasses] = 1;
+ nClasses++;
+ if ( nClasses > nCofs/2 )
+ return 0;
+ }
+ // the number of cofactors is acceptable
+ nVarsNew = Extra_Base2Log( nClasses );
+ assert( nVarsNew < p->nLutSize );
+ // create the remainder truth table
+ // for each class of cofactors, multiply cofactor truth table by its code
+ Extra_TruthClear( p->uTruth, nVars );
+ for ( k = 0; k < nClasses; k++ )
+ {
+ pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ];
+ for ( v = 0; v < nVarsNew; v++ )
+ if ( k & (1 << v) )
+ Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars );
+ else
+ Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars );
+ Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars );
+ }
+ // create nodes
+ pTruth = p->uCofs[0];
+ for ( v = 0; v < nVarsNew; v++ )
+ {
+ Extra_TruthClear( pTruth, p->nLutSize );
+ for ( k = 0; k < nClasses; k++ )
+ if ( k & (1 << v) )
+ for ( i = 0; i < nCofClasses[k]; i++ )
+ {
+ pTruthCof = p->uCofs[1];
+ Extra_TruthFill( pTruthCof, p->nLutSize );
+ for ( w = 0; w < p->nLutSize; w++ )
+ if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) )
+ Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize );
+ else
+ Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize );
+ Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize );
+ }
+ // implement the node
+ pObjNew = Abc_NtkCreateNode( pNtk );
+ for ( i = 0; i < p->nLutSize; i++ )
+ {
+ pFanin = Vec_PtrEntry( p->vLeaves, p->pBSet[i] );
+ Abc_ObjAddFanin( pObjNew, pFanin );
+ }
+ // create the function
+ pObjNew->pData = Abc_SopCreateFromTruth( pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP
+ pObjNew->Level = Abc_NodeGetLevel( pObjNew );
+ pNodesNew[v] = pObjNew;
+ }
+ // put the new nodes back into the list
+ for ( v = 0; v < nVarsNew; v++ )
+ Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] );
+ // compute the variables that should be removed
+ uPhase = 0;
+ for ( v = nVarsNew; v < p->nLutSize; v++ )
+ uPhase |= (1 << p->pBSet[v]);
+ // remove entries from the array
+ Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars );
+ // update truth table
+ Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase );
+ Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars );
+ assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c
new file mode 100644
index 00000000..d4d50923
--- /dev/null
+++ b/src/base/abci/abcMap.c
@@ -0,0 +1,657 @@
+/**CFile****************************************************************
+
+ FileName [abcMap.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface with the SC mapping package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "main.h"
+#include "mio.h"
+#include "mapper.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose );
+static Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk );
+static Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase );
+static Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase );
+static Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis );
+
+static Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk );
+static void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode );
+static void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase );
+static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Interface with the mapping package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose )
+{
+ int fShowSwitching = 1;
+ Abc_Ntk_t * pNtkNew;
+ Map_Man_t * pMan;
+ Vec_Int_t * vSwitching;
+ float * pSwitching = NULL;
+ int clk;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // check that the library is available
+ if ( Abc_FrameReadLibGen() == NULL )
+ {
+ printf( "The current library is not available.\n" );
+ return 0;
+ }
+
+ // derive the supergate library
+ if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
+ {
+ printf( "A simple supergate library is derived from gate library \"%s\".\n",
+ Mio_LibraryReadName(Abc_FrameReadLibGen()) );
+ Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() );
+ }
+
+ // print a warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Performing mapping with choices.\n" );
+
+ // compute switching activity
+ fShowSwitching |= fSwitching;
+ if ( fShowSwitching )
+ {
+ extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns );
+ vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 );
+ pSwitching = (float *)vSwitching->pArray;
+ }
+
+ // perform the mapping
+ pMan = Abc_NtkToMap( pNtk, DelayTarget, fRecovery, pSwitching, fVerbose );
+ if ( pSwitching ) Vec_IntFree( vSwitching );
+ if ( pMan == NULL )
+ return NULL;
+clk = clock();
+ Map_ManSetSwitching( pMan, fSwitching );
+ if ( !Map_Mapping( pMan ) )
+ {
+ Map_ManFree( pMan );
+ return NULL;
+ }
+// Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), clock()-clk );
+
+ // reconstruct the network after mapping
+ pNtkNew = Abc_NtkFromMap( pMan, pNtk );
+ if ( pNtkNew == NULL )
+ return NULL;
+ Map_ManFree( pMan );
+
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkMap: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Load the network into manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose )
+{
+ Map_Man_t * pMan;
+ ProgressBar * pProgress;
+ Map_Node_t * pNodeMap;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode, * pFanin, * pPrev;
+ int i;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // start the mapping manager and set its parameters
+ pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk), Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk), fVerbose );
+ if ( pMan == NULL )
+ return NULL;
+ Map_ManSetAreaRecovery( pMan, fRecovery );
+ Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) );
+ Map_ManSetDelayTarget( pMan, (float)DelayTarget );
+ Map_ManSetInputArrivals( pMan, (Map_Time_t *)Abc_NtkGetCiArrivalTimes(pNtk) );
+
+ // create PIs and remember them in the old nodes
+ Abc_NtkCleanCopy( pNtk );
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan);
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ pNodeMap = Map_ManReadInputs(pMan)[i];
+ pNode->pCopy = (Abc_Obj_t *)pNodeMap;
+ if ( pSwitching )
+ Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] );
+ }
+
+ // load the AIG into the mapper
+ vNodes = Abc_AigDfs( pNtk, 0, 0 );
+ pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // add the node to the mapper
+ pNodeMap = Map_NodeAnd( pMan,
+ Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
+ Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) );
+ assert( pNode->pCopy == NULL );
+ // remember the node
+ pNode->pCopy = (Abc_Obj_t *)pNodeMap;
+ if ( pSwitching )
+ Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] );
+ // set up the choice node
+ if ( Abc_AigNodeIsChoice( pNode ) )
+ for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
+ {
+ Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy );
+ Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy );
+ }
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+
+ // set the primary outputs in the required phase
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the mapped network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkNew;
+ Map_Node_t * pNodeMap;
+ Abc_Obj_t * pNode, * pNodeNew;
+ int i, nDupGates;
+ // create the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP );
+ // make the mapper point to the new network
+ Map_ManCleanData( pMan );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy );
+ // assign the mapping of the required phase to the POs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNodeMap = Map_ManReadOutputs(pMan)[i];
+ pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) );
+ assert( !Abc_ObjIsComplement(pNodeNew) );
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ }
+ Extra_ProgressBarStop( pProgress );
+ // decouple the PO driver nodes to reduce the number of levels
+ nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+// if ( nDupGates && Map_ManReadVerbose(pMan) )
+// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the nodes corrresponding to one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase )
+{
+ Abc_Obj_t * pNodeNew, * pNodeInv;
+
+ // check the case of constant node
+ if ( Map_NodeIsConst(pNodeMap) )
+ return fPhase? Abc_NtkCreateNodeConst1(pNtkNew) : Abc_NtkCreateNodeConst0(pNtkNew);
+
+ // check if the phase is already implemented
+ pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase );
+ if ( pNodeNew )
+ return pNodeNew;
+
+ // implement the node if the best cut is assigned
+ if ( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL )
+ return Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, fPhase );
+
+ // if the cut is not assigned, implement the node
+ assert( Map_NodeReadCutBest(pNodeMap, !fPhase) != NULL || Map_NodeIsConst(pNodeMap) );
+ pNodeNew = Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, !fPhase );
+
+ // add the inverter
+ pNodeInv = Abc_NtkCreateNode( pNtkNew );
+ Abc_ObjAddFanin( pNodeInv, pNodeNew );
+ pNodeInv->pData = Mio_LibraryReadInv(Map_ManReadGenLib(Map_NodeReadMan(pNodeMap)));
+
+ // set the inverter
+ Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeInv );
+ return pNodeInv;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the nodes corrresponding to one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase )
+{
+ Abc_Obj_t * pNodePIs[10];
+ Abc_Obj_t * pNodeNew;
+ Map_Node_t ** ppLeaves;
+ Map_Cut_t * pCutBest;
+ Map_Super_t * pSuperBest;
+ unsigned uPhaseBest;
+ int i, fInvPin, nLeaves;
+
+ // make sure the node can be implemented in this phase
+ assert( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL || Map_NodeIsConst(pNodeMap) );
+ // check if the phase is already implemented
+ pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase );
+ if ( pNodeNew )
+ return pNodeNew;
+
+ // get the information about the best cut
+ pCutBest = Map_NodeReadCutBest( pNodeMap, fPhase );
+ pSuperBest = Map_CutReadSuperBest( pCutBest, fPhase );
+ uPhaseBest = Map_CutReadPhaseBest( pCutBest, fPhase );
+ nLeaves = Map_CutReadLeavesNum( pCutBest );
+ ppLeaves = Map_CutReadLeaves( pCutBest );
+
+ // collect the PI nodes
+ for ( i = 0; i < nLeaves; i++ )
+ {
+ fInvPin = ((uPhaseBest & (1 << i)) > 0);
+ pNodePIs[i] = Abc_NodeFromMap_rec( pNtkNew, ppLeaves[i], !fInvPin );
+ assert( pNodePIs[i] != NULL );
+ }
+
+ // implement the supergate
+ pNodeNew = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, pSuperBest, pNodePIs, nLeaves );
+ Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeNew );
+ return pNodeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the nodes corrresponding to one supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis )
+{
+ Mio_Gate_t * pRoot;
+ Map_Super_t ** ppFanins;
+ Abc_Obj_t * pNodeNew, * pNodeFanin;
+ int nFanins, Number, i;
+
+ // get the parameters of the supergate
+ pRoot = Map_SuperReadRoot(pSuper);
+ if ( pRoot == NULL )
+ {
+ Number = Map_SuperReadNum(pSuper);
+ if ( Number < nNodePis )
+ {
+ return pNodePis[Number];
+ }
+ else
+ {
+// assert( 0 );
+ /* It might happen that a super gate with 5 inputs is constructed that
+ * actually depends only on the first four variables; i.e the fifth is a
+ * don't care -- in that case we connect constant node for the fifth
+ * (since the cut only has 4 variables). An interesting question is what
+ * if the first variable (and not the fifth one is the redundant one;
+ * can that happen?) */
+ return Abc_NtkCreateNodeConst0(pNtkNew);
+ }
+ }
+
+ // get information about the fanins of the supergate
+ nFanins = Map_SuperReadFaninNum( pSuper );
+ ppFanins = Map_SuperReadFanins( pSuper );
+ // create a new node with these fanins
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ for ( i = 0; i < nFanins; i++ )
+ {
+ pNodeFanin = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, ppFanins[i], pNodePis, nNodePis );
+ Abc_ObjAddFanin( pNodeNew, pNodeFanin );
+ }
+ pNodeNew->pData = pRoot;
+ return pNodeNew;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Interface with the mapping package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+
+ Map_Man_t * pMan;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // check that the library is available
+ if ( Abc_FrameReadLibGen() == NULL )
+ {
+ printf( "The current library is not available.\n" );
+ return 0;
+ }
+
+ // derive the supergate library
+ if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
+ {
+ printf( "A simple supergate library is derived from gate library \"%s\".\n",
+ Mio_LibraryReadName(Abc_FrameReadLibGen()) );
+ Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() );
+ }
+
+ // print a warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Performing mapping with choices.\n" );
+
+ // perform the mapping
+ pMan = Abc_NtkToMap( pNtk, -1, 1, NULL, 0 );
+ if ( pMan == NULL )
+ return NULL;
+ if ( !Map_Mapping( pMan ) )
+ {
+ Map_ManFree( pMan );
+ return NULL;
+ }
+
+ // reconstruct the network after mapping
+ pNtkNew = Abc_NtkFromMapSuperChoice( pMan, pNtk );
+ if ( pNtkNew == NULL )
+ return NULL;
+ Map_ManFree( pMan );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkMap: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates the mapped network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkNew, * pNtkNew2;
+ Abc_Obj_t * pNode;
+ int i;
+
+ // save the pointer to the mapped nodes
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pNext = pNode->pCopy;
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ pNode->pNext = pNode->pCopy;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->pNext = pNode->pCopy;
+
+ // duplicate the network
+ pNtkNew2 = Abc_NtkDup( pNtk );
+ pNtkNew = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 );
+ if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
+ {
+ printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
+
+ // set the old network to point to the new network
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy = pNode->pCopy->pCopy;
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ pNode->pCopy = pNode->pCopy->pCopy;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->pCopy = pNode->pCopy->pCopy;
+ Abc_NtkDelete( pNtkNew2 );
+
+ // set the pointers from the mapper to the new nodes
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) );
+ Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy );
+ }
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) );
+ Map_NodeSetData( (Map_Node_t *)pNode->pNext, 1, (char *)pNode->pCopy );
+ }
+
+ // assign the mapping of the required phase to the POs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ Abc_NodeSuperChoice( pNtkNew, pNode );
+ }
+ Extra_ProgressBarStop( pProgress );
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates the mapped network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode )
+{
+ Map_Node_t * pMapNode = (Map_Node_t *)pNode->pNext;
+ Map_Cut_t * pCuts, * pTemp;
+
+ pCuts = Map_NodeReadCuts(pMapNode);
+ for ( pTemp = Map_CutReadNext(pCuts); pTemp; pTemp = Map_CutReadNext(pTemp) )
+ {
+ Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 0 );
+ Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 1 );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the nodes corrresponding to one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase )
+{
+ Abc_Obj_t * pNodePIs[10];
+ Map_Node_t ** ppLeaves;
+ Map_Super_t * pSuperBest;
+ unsigned uPhaseBest;
+ int i, fInvPin, nLeaves;
+
+ pSuperBest = Map_CutReadSuperBest( pCut, fPhase );
+ if ( pSuperBest == NULL )
+ return;
+
+ // get the information about the best cut
+ uPhaseBest = Map_CutReadPhaseBest( pCut, fPhase );
+ nLeaves = Map_CutReadLeavesNum( pCut );
+ ppLeaves = Map_CutReadLeaves( pCut );
+
+ // collect the PI nodes
+ for ( i = 0; i < nLeaves; i++ )
+ {
+ fInvPin = ((uPhaseBest & (1 << i)) > 0);
+ pNodePIs[i] = (Abc_Obj_t *)Map_NodeReadData( ppLeaves[i], !fInvPin );
+ assert( pNodePIs[i] != NULL );
+ }
+
+ // implement the supergate
+ Abc_NodeFromMapSuperChoice_rec( pNtkNew, pSuperBest, pNodePIs, nLeaves );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the nodes corrresponding to one supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis )
+{
+ Mio_Gate_t * pRoot;
+ Map_Super_t ** ppFanins;
+ Abc_Obj_t * pNodeNew, * pNodeFanin;
+ int nFanins, Number, i;
+
+ // get the parameters of the supergate
+ pRoot = Map_SuperReadRoot(pSuper);
+ if ( pRoot == NULL )
+ {
+ Number = Map_SuperReadNum(pSuper);
+ if ( Number < nNodePis )
+ {
+ return pNodePis[Number];
+ }
+ else
+ {
+// assert( 0 );
+ /* It might happen that a super gate with 5 inputs is constructed that
+ * actually depends only on the first four variables; i.e the fifth is a
+ * don't care -- in that case we connect constant node for the fifth
+ * (since the cut only has 4 variables). An interesting question is what
+ * if the first variable (and not the fifth one is the redundant one;
+ * can that happen?) */
+ return Abc_NtkCreateNodeConst0(pNtkNew);
+ }
+ }
+
+ // get information about the fanins of the supergate
+ nFanins = Map_SuperReadFaninNum( pSuper );
+ ppFanins = Map_SuperReadFanins( pSuper );
+ // create a new node with these fanins
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ for ( i = 0; i < nFanins; i++ )
+ {
+ pNodeFanin = Abc_NodeFromMapSuperChoice_rec( pNtkNew, ppFanins[i], pNodePis, nNodePis );
+ Abc_ObjAddFanin( pNodeNew, pNodeFanin );
+ }
+ pNodeNew->pData = Abc_SopRegister( pNtkNew->pManFunc, Mio_GateReadSop(pRoot) );
+ return pNodeNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMeasure.c b/src/base/abci/abcMeasure.c
new file mode 100644
index 00000000..6604a0c4
--- /dev/null
+++ b/src/base/abci/abcMeasure.c
@@ -0,0 +1,478 @@
+/**CFile****************************************************************
+
+ FileName [abc_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintMeasures( unsigned * pTruth, int nVars )
+{
+ unsigned uCofs[10][32];
+ int i, k, nOnes;
+
+ // total pairs
+ nOnes = Kit_TruthCountOnes( uCofs[0], nVars );
+ printf( "Total = %d.\n", nOnes * ((1 << nVars) - nOnes) );
+
+ // print measures for individual variables
+ for ( i = 0; i < nVars; i++ )
+ {
+ Kit_TruthUniqueNew( uCofs[0], pTruth, nVars, i );
+ nOnes = Kit_TruthCountOnes( uCofs[0], nVars );
+ printf( "%7d ", nOnes );
+ }
+ printf( "\n" );
+
+ // consider pairs
+ for ( i = 0; i < nVars; i++ )
+ for ( k = 0; k < nVars; k++ )
+ {
+ if ( i == k )
+ {
+ printf( " " );
+ continue;
+ }
+ Kit_TruthCofactor0New( uCofs[0], pTruth, nVars, i );
+ Kit_TruthCofactor1New( uCofs[1], pTruth, nVars, i );
+
+ Kit_TruthCofactor0New( uCofs[2], uCofs[0], nVars, k ); // 00
+ Kit_TruthCofactor1New( uCofs[3], uCofs[0], nVars, k ); // 01
+ Kit_TruthCofactor0New( uCofs[4], uCofs[1], nVars, k ); // 10
+ Kit_TruthCofactor1New( uCofs[5], uCofs[1], nVars, k ); // 11
+
+ Kit_TruthAndPhase( uCofs[6], uCofs[2], uCofs[5], nVars, 0, 1 ); // 00 & 11'
+ Kit_TruthAndPhase( uCofs[7], uCofs[2], uCofs[5], nVars, 1, 0 ); // 00' & 11
+ Kit_TruthAndPhase( uCofs[8], uCofs[3], uCofs[4], nVars, 0, 1 ); // 01 & 10'
+ Kit_TruthAndPhase( uCofs[9], uCofs[3], uCofs[4], nVars, 1, 0 ); // 01' & 10
+
+ nOnes = Kit_TruthCountOnes( uCofs[6], nVars ) +
+ Kit_TruthCountOnes( uCofs[7], nVars ) +
+ Kit_TruthCountOnes( uCofs[8], nVars ) +
+ Kit_TruthCountOnes( uCofs[9], nVars );
+
+ printf( "%7d ", nOnes );
+ if ( k == nVars - 1 )
+ printf( "\n" );
+ }
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj )
+{
+ if ( pObj == Abc_AigConst1(pObj->pNtk) )
+ {
+ printf( "1" );
+ return;
+ }
+ if ( Abc_ObjIsPi(pObj) )
+ {
+ printf( "%c", pObj->Id - 1 + 'a' );
+ return;
+ }
+
+ printf( "(" );
+ Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) );
+ if ( Abc_ObjFaninC0(pObj) )
+ printf( "\'" );
+ Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) );
+ if ( Abc_ObjFaninC1(pObj) )
+ printf( "\'" );
+ printf( ")" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pObj;
+ unsigned uTruth0, uTruth1;
+ int i;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy);
+ uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy);
+ if ( Abc_ObjFaninC0(pObj) )
+ uTruth0 = ~uTruth0;
+ if ( Abc_ObjFaninC1(pObj) )
+ uTruth1 = ~uTruth1;
+ pObj->pCopy = (void *)(uTruth0 & uTruth1);
+ }
+ return uTruth0 & uTruth1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_Ntk4VarTable( Abc_Ntk_t * pNtk )
+{
+ static unsigned u4VarTruths[4] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00 };
+ static unsigned u4VarTts[222] = {
+ 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019,
+ 0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e,
+ 0x007f, 0x00ff, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f,
+ 0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016a,
+ 0x016b, 0x016e, 0x016f, 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186,
+ 0x0187, 0x0189, 0x018b, 0x018f, 0x0196, 0x0197, 0x0198, 0x0199, 0x019a, 0x019b,
+ 0x019e, 0x019f, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af,
+ 0x01bc, 0x01bd, 0x01be, 0x01bf, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef,
+ 0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b,
+ 0x035e, 0x035f, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f,
+ 0x037c, 0x037d, 0x037e, 0x03c0, 0x03c1, 0x03c3, 0x03c5, 0x03c6, 0x03c7, 0x03cf,
+ 0x03d4, 0x03d5, 0x03d6, 0x03d7, 0x03d8, 0x03d9, 0x03db, 0x03dc, 0x03dd, 0x03de,
+ 0x03fc, 0x0660, 0x0661, 0x0662, 0x0663, 0x0666, 0x0667, 0x0669, 0x066b, 0x066f,
+ 0x0672, 0x0673, 0x0676, 0x0678, 0x0679, 0x067a, 0x067b, 0x067e, 0x0690, 0x0691,
+ 0x0693, 0x0696, 0x0697, 0x069f, 0x06b0, 0x06b1, 0x06b2, 0x06b3, 0x06b4, 0x06b5,
+ 0x06b6, 0x06b7, 0x06b9, 0x06bd, 0x06f0, 0x06f1, 0x06f2, 0x06f6, 0x06f9, 0x0776,
+ 0x0778, 0x0779, 0x077a, 0x077e, 0x07b0, 0x07b1, 0x07b4, 0x07b5, 0x07b6, 0x07bc,
+ 0x07e0, 0x07e1, 0x07e2, 0x07e3, 0x07e6, 0x07e9, 0x07f0, 0x07f1, 0x07f2, 0x07f8,
+ 0x0ff0, 0x1668, 0x1669, 0x166a, 0x166b, 0x166e, 0x167e, 0x1681, 0x1683, 0x1686,
+ 0x1687, 0x1689, 0x168b, 0x168e, 0x1696, 0x1697, 0x1698, 0x1699, 0x169a, 0x169b,
+ 0x169e, 0x16a9, 0x16ac, 0x16ad, 0x16bc, 0x16e9, 0x177e, 0x178e, 0x1796, 0x1798,
+ 0x179a, 0x17ac, 0x17e8, 0x18e7, 0x19e1, 0x19e3, 0x19e6, 0x1bd8, 0x1be4, 0x1ee1,
+ 0x3cc3, 0x6996
+ };
+ int Counters[222] = {0};
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ unsigned uTruth;
+ int i, k, Count = 0;
+
+ unsigned short * puCanons = NULL;
+ unsigned char * puMap = NULL;
+ Extra_Truth4VarNPN( &puCanons, NULL, NULL, &puMap );
+
+ // set elementary truth tables
+ assert( Abc_NtkPiNum(pNtk) == 4 );
+ Abc_AigConst1(pNtk)->pCopy = (void *)0xFFFFFFFF;
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->pCopy = (void *)u4VarTruths[i];
+
+ // create truth tables
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+ if ( Vec_PtrSize(vNodes) == 0 )
+ uTruth = (unsigned)Abc_ObjFanin0(pObj)->pCopy;
+ else
+ uTruth = Abc_Ntk4VarObj( vNodes );
+
+ if ( (uTruth & 0xFFFF) < (~uTruth & 0xFFFF) )
+ uTruth = uTruth & 0xFFFF;
+ else
+ uTruth = ~uTruth & 0xFFFF;
+
+ for ( k = 0; k < 222; k++ )
+ if ( u4VarTts[k] == uTruth )
+ break;
+ if ( k == 222 )
+ continue;
+/*
+// if ( uTruth == 1725 )
+ if ( k == 96 )
+ {
+ printf( "%d : ", Vec_PtrSize(vNodes) );
+ Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) );
+ printf( "\n" );
+ }
+*/
+ Counters[k]++;
+
+// Counters[ puMap[uTruth & 0xFFFF] ]++;
+ Vec_PtrFree( vNodes );
+ }
+ free( puCanons );
+ free( puMap );
+
+ Count = 0;
+ for ( k = 0; k < 222; k++ )
+ {
+ printf( "%d/%x/%d ", k, u4VarTts[k], Counters[k] );
+ Count += Counters[k];
+ }
+ printf( " Total = %d\n", Count );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if there are no more than 2 unique cofactors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkPrintOneDecompCheckCofList( unsigned * uCofs, int nCofs )
+{
+ int i, Ind = -1;
+ assert( nCofs > 2 );
+ for ( i = 1; i < nCofs; i++ )
+ {
+ if ( uCofs[i] == uCofs[0] )
+ continue;
+ if ( Ind == -1 )
+ {
+ Ind = i;
+ continue;
+ }
+ if ( uCofs[i] == uCofs[Ind] )
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks all cofactors with the given mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkPrintOneDecompCheck( unsigned * uCofs, int nCofs, unsigned uMask )
+{
+ unsigned pCofs[32][32];
+ int nCofNums[32] = {0};
+ int uMasks[32];
+ int nGroups = 0;
+ int i, k;
+ for ( i = 0; i < nCofs; i++ )
+ {
+ // find group of this cof
+ for ( k = 0; k < nGroups; k++ )
+ if ( (int)(i & uMask) == uMasks[k] )
+ break;
+ if ( k == nGroups )
+ {
+ uMasks[k] = (i & uMask);
+ nGroups++;
+ }
+ // save cof in the group
+ pCofs[k][ nCofNums[k]++ ] = uCofs[i];
+ assert( nCofNums[k] <= 32 );
+ assert( nGroups <= 32 );
+ }
+ // check the groups
+ for ( i = 0; i < nGroups; i++ )
+ if ( !Abc_NtkPrintOneDecompCheckCofList(pCofs[i], nCofNums[i]) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintOneDecomp_rec( unsigned * uCofs, int nCofs, int nVars, unsigned uMask, int * pBestSize, unsigned * puBestMask )
+{
+ unsigned uMaskNew;
+ int v, last, Counter = 0;
+ // find the last variable in the mask
+ for ( v = 0; v < nVars; v++ )
+ if ( uMask & (1<<v) )
+ {
+ last = v;
+ Counter++;
+ }
+ if ( Counter > 3 )
+ return;
+ // try adding one variable after the last
+ for ( v = last + 1; v < nVars; v++ )
+ {
+ uMaskNew = uMask | (1 << v);
+ if ( !Abc_NtkPrintOneDecompCheck( uCofs, nCofs, uMaskNew ) )
+ continue;
+ if ( *pBestSize < Counter + 1 )
+ {
+ *pBestSize = Counter + 1;
+ *puBestMask = uMaskNew;
+ }
+ // try other masks
+ Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, uMaskNew, pBestSize, puBestMask );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintOneDecomp( unsigned * pTruth, int nVars )
+{
+ int BoundSet = 6;
+ unsigned uCofs[64], uMask, uBestMask = 0;
+ int i, nCofs, nMints, nMintShift, BestSize = 1;
+
+ assert( nVars > BoundSet );
+ assert( nVars <= BoundSet + 5 ); // at most 5 variable cofactors
+
+ // collect the cofactors
+ nCofs = (1 << BoundSet);
+ nMints = (1 << (nVars-BoundSet));
+ nMintShift = 0;
+ uMask = Kit_CubeMask( nMints );
+ for ( i = 0; i < nCofs; i++ )
+ {
+ uCofs[i] = (pTruth[nMintShift/32] >> (nMintShift % 32)) & uMask;
+ nMintShift += nMints;
+ }
+
+ // try removing variables
+ for ( i = 0; i < BoundSet; i++ )
+ Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, (1 << i), &BestSize, &uBestMask );
+
+ printf( "Best size = %d ", BestSize );
+ printf( "Best mask = " );
+ Extra_PrintBinary( stdout, &uBestMask, nVars );
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintOneDec( unsigned * pTruth, int nVars )
+{
+ unsigned uCof[(1<<11)], * pOut = uCof, * pIn = pTruth, * pTemp;
+ int nDiffs[16];
+ int Order[16];
+ int i, fChange, Temp, Counter;
+
+ // find the ordering
+ for ( i = 0; i < nVars; i++ )
+ {
+ Kit_TruthUniqueNew( uCof, pTruth, nVars, i );
+ nDiffs[i] = Kit_TruthCountOnes( uCof, nVars );
+ Order[i] = i;
+ }
+
+ // permute truth table to least active variable first
+ Counter = 0;
+ do {
+ fChange = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ if ( nDiffs[i] <= nDiffs[i+1] )
+ continue;
+ fChange = 1;
+ Counter++;
+
+ Temp = nDiffs[i];
+ nDiffs[i] = nDiffs[i+1];
+ nDiffs[i+1] = Temp;
+
+ Temp = Order[i];
+ Order[i] = Order[i+1];
+ Order[i+1] = Temp;
+
+ Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ } while ( fChange );
+
+ // swap if it was moved an even number of times
+ if ( Counter & 1 )
+ Extra_TruthCopy( pOut, pIn, nVars );
+
+ // call the decomposition
+ Abc_NtkPrintOneDecomp( pTruth, nVars );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c
new file mode 100644
index 00000000..92985423
--- /dev/null
+++ b/src/base/abci/abcMini.c
@@ -0,0 +1,153 @@
+/**CFile****************************************************************
+
+ FileName [abcMini.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface to the minimalistic AIG package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk );
+static Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtkOld, Hop_Man_t * pMan );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkAig;
+ Hop_Man_t * pMan, * pTemp;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // convert to the AIG manager
+ pMan = Abc_NtkToMini( pNtk );
+ if ( pMan == NULL )
+ return NULL;
+ if ( !Hop_ManCheck( pMan ) )
+ {
+ printf( "AIG check has failed.\n" );
+ Hop_ManStop( pMan );
+ return NULL;
+ }
+ // perform balance
+ 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_NtkFromMini( pNtk, pMan );
+ if ( pNtkAig == NULL )
+ return NULL;
+ Hop_ManStop( pMan );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk )
+{
+ Hop_Man_t * pMan;
+ Abc_Obj_t * pObj;
+ int i;
+ // create the manager
+ pMan = Hop_ManStart();
+ // transfer the pointers to the basic nodes
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ 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 *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) );
+ // create the POs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) );
+ Hop_ManCleanup( pMan );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtk, Hop_Man_t * pMan )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew;
+ 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
+ Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+ Hop_ManForEachPi( pMan, pObj, i )
+ pObj->pData = Abc_NtkCi(pNtkNew, i);
+ // rebuild the AIG
+ vNodes = Hop_ManDfs( pMan );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ 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
+ Hop_ManForEachPo( pMan, pObj, i )
+ Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c
new file mode 100644
index 00000000..257d930f
--- /dev/null
+++ b/src/base/abci/abcMiter.c
@@ -0,0 +1,1146 @@
+/**CFile****************************************************************
+
+ FileName [abcMiter.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures to derive the miter of two circuits.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize );
+static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize );
+static void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter );
+static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize );
+static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame );
+
+// to be exported
+typedef void (*AddFrameMapping)( Abc_Obj_t*, Abc_Obj_t*, int, void*);
+extern Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg );
+static void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives the miter of two networks.]
+
+ Description [Preprocesses the networks to make sure that they are strashed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize )
+{
+ Abc_Ntk_t * pTemp = NULL;
+ int fRemove1, fRemove2;
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
+ // check that the networks have the same PIs/POs/latches
+ if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 0, fComb ) )
+ return NULL;
+ // make sure the circuits are strashed
+ fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0));
+ fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0));
+ if ( pNtk1 && pNtk2 )
+ pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize );
+ if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+ if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
+ return pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the miter of two sequential networks.]
+
+ Description [Assumes that the networks are strashed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize )
+{
+ char Buffer[1000];
+ Abc_Ntk_t * pNtkMiter;
+
+ assert( Abc_NtkIsStrash(pNtk1) );
+ assert( Abc_NtkIsStrash(pNtk2) );
+
+ // start the new network
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+ // perform strashing
+ Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize );
+ Abc_NtkMiterAddOne( pNtk1, pNtkMiter );
+ Abc_NtkMiterAddOne( pNtk2, pNtkMiter );
+ Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize );
+ Abc_AigCleanup(pNtkMiter->pManFunc);
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkMiter ) )
+ {
+ printf( "Abc_NtkMiter: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkMiter );
+ return NULL;
+ }
+ return pNtkMiter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the network for mitering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize )
+{
+ Abc_Obj_t * pObj, * pObjNew;
+ int i;
+ // clean the copy field in all objects
+// Abc_NtkCleanCopy( pNtk1 );
+// Abc_NtkCleanCopy( pNtk2 );
+ Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter);
+ Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter);
+
+ if ( fComb )
+ {
+ // create new PIs and remember them in the old PIs
+ Abc_NtkForEachCi( pNtk1, pObj, i )
+ {
+ pObjNew = Abc_NtkCreatePi( pNtkMiter );
+ // remember this PI in the old PIs
+ pObj->pCopy = pObjNew;
+ pObj = Abc_NtkCi(pNtk2, i);
+ pObj->pCopy = pObjNew;
+ // add name
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+ }
+ if ( nPartSize <= 0 )
+ {
+ // create the only PO
+ pObjNew = Abc_NtkCreatePo( pNtkMiter );
+ // add the PO name
+ Abc_ObjAssignName( pObjNew, "miter", NULL );
+ }
+ }
+ else
+ {
+ // create new PIs and remember them in the old PIs
+ Abc_NtkForEachPi( pNtk1, pObj, i )
+ {
+ pObjNew = Abc_NtkCreatePi( pNtkMiter );
+ // remember this PI in the old PIs
+ pObj->pCopy = pObjNew;
+ pObj = Abc_NtkPi(pNtk2, i);
+ pObj->pCopy = pObjNew;
+ // add name
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL );
+ }
+ if ( nPartSize <= 0 )
+ {
+ // create the only PO
+ pObjNew = Abc_NtkCreatePo( pNtkMiter );
+ // add the PO name
+ Abc_ObjAssignName( pObjNew, "miter", NULL );
+ }
+ // create the latches
+ Abc_NtkForEachLatch( pNtk1, pObj, i )
+ {
+ pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 );
+ // add names
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_1" );
+ Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_1" );
+ Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_1" );
+ }
+ Abc_NtkForEachLatch( pNtk2, pObj, i )
+ {
+ pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 );
+ // add name
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_2" );
+ Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_2" );
+ Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_2" );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs mitering for one network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs mitering for one network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
+ int i;
+ // map the constant nodes
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter);
+ // perform strashing
+ vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ if ( Abc_AigNodeIsAnd(pNode) )
+ pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+ Vec_PtrFree( vNodes );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finalizes the miter by adding the output part.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize )
+{
+ Vec_Ptr_t * vPairs;
+ Abc_Obj_t * pMiter, * pNode;
+ int i;
+ // collect the PO pairs from both networks
+ vPairs = Vec_PtrAlloc( 100 );
+ if ( fComb )
+ {
+ // collect the CO nodes for the miter
+ Abc_NtkForEachCo( pNtk1, pNode, i )
+ {
+ Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+ pNode = Abc_NtkCo( pNtk2, i );
+ Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+ }
+ }
+ else
+ {
+ // collect the PO nodes for the miter
+ Abc_NtkForEachPo( pNtk1, pNode, i )
+ {
+ Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+ pNode = Abc_NtkPo( pNtk2, i );
+ Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) );
+ }
+ // connect new latches
+ Abc_NtkForEachLatch( pNtk1, pNode, i )
+ Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) );
+ Abc_NtkForEachLatch( pNtk2, pNode, i )
+ Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) );
+ }
+ // add the miter
+ if ( nPartSize <= 0 )
+ {
+ pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairs );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+ Vec_PtrFree( vPairs );
+ }
+ else
+ {
+ char Buffer[1024];
+ Vec_Ptr_t * vPairsPart;
+ int nParts, i, k, iCur;
+ assert( Vec_PtrSize(vPairs) == 2 * Abc_NtkCoNum(pNtk1) );
+ // create partitions
+ nParts = Abc_NtkCoNum(pNtk1) / nPartSize + (int)((Abc_NtkCoNum(pNtk1) % nPartSize) > 0);
+ vPairsPart = Vec_PtrAlloc( nPartSize );
+ for ( i = 0; i < nParts; i++ )
+ {
+ Vec_PtrClear( vPairsPart );
+ for ( k = 0; k < nPartSize; k++ )
+ {
+ iCur = i * nPartSize + k;
+ if ( iCur >= Abc_NtkCoNum(pNtk1) )
+ break;
+ Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur ) );
+ Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur+1) );
+ }
+ pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairsPart );
+ pNode = Abc_NtkCreatePo( pNtkMiter );
+ Abc_ObjAddFanin( pNode, pMiter );
+ // assign the name to the node
+ if ( nPartSize == 1 )
+ sprintf( Buffer, "%s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) );
+ else
+ sprintf( Buffer, "%d", i );
+ Abc_ObjAssignName( pNode, "miter_", Buffer );
+ }
+ Vec_PtrFree( vPairsPart );
+ Vec_PtrFree( vPairs );
+ }
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the AND of two miters.]
+
+ Description [The network should have the same names of PIs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 )
+{
+ char Buffer[1000];
+ Abc_Ntk_t * pNtkMiter;
+ Abc_Obj_t * pOutput1, * pOutput2;
+ Abc_Obj_t * pRoot1, * pRoot2, * pMiter;
+
+ assert( Abc_NtkIsStrash(pNtk1) );
+ assert( Abc_NtkIsStrash(pNtk2) );
+ assert( 1 == Abc_NtkCoNum(pNtk1) );
+ assert( 1 == Abc_NtkCoNum(pNtk2) );
+ assert( 0 == Abc_NtkLatchNum(pNtk1) );
+ assert( 0 == Abc_NtkLatchNum(pNtk2) );
+ assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
+
+ // start the new network
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+// sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
+ sprintf( Buffer, "product" );
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+ // perform strashing
+ Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1, -1 );
+ Abc_NtkMiterAddOne( pNtk1, pNtkMiter );
+ Abc_NtkMiterAddOne( pNtk2, pNtkMiter );
+// Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 );
+ pRoot1 = Abc_NtkPo(pNtk1,0);
+ pRoot2 = Abc_NtkPo(pNtk2,0);
+ pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) );
+ pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, Abc_ObjFaninC0(pRoot2) ^ fCompl2 );
+
+ // create the miter of the two outputs
+ if ( fOr )
+ pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 );
+ else
+ pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkMiter ) )
+ {
+ printf( "Abc_NtkMiterAnd: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkMiter );
+ return NULL;
+ }
+ return pNtkMiter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the cofactor of the miter w.r.t. the set of vars.]
+
+ Description [The array of variable values contains -1/0/1 for each PI.
+ -1 means this PI remains, 0/1 means this PI is set to 0/1.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues )
+{
+ char Buffer[1000];
+ Abc_Ntk_t * pNtkMiter;
+ Abc_Obj_t * pRoot, * pOutput1;
+ int Value, i;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( 1 == Abc_NtkCoNum(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+ // start the new network
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ sprintf( Buffer, "%s_miter", pNtk->pName );
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+ // get the root output
+ pRoot = Abc_NtkCo( pNtk, 0 );
+
+ // perform strashing
+ Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 );
+ // set the first cofactor
+ Vec_IntForEachEntry( vPiValues, Value, i )
+ {
+ if ( Value == -1 )
+ continue;
+ if ( Value == 0 )
+ {
+ Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+ continue;
+ }
+ if ( Value == 1 )
+ {
+ Abc_NtkCi(pNtk, i)->pCopy = Abc_AigConst1(pNtkMiter);
+ continue;
+ }
+ assert( 0 );
+ }
+ // add the first cofactor
+ Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+
+ // save the output
+ pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+ // create the miter of the two outputs
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkMiter ) )
+ {
+ printf( "Abc_NtkMiterCofactor: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkMiter );
+ return NULL;
+ }
+ return pNtkMiter;
+}
+/**Function*************************************************************
+
+ Synopsis [Derives the miter of two cofactors of one output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 )
+{
+ char Buffer[1000];
+ Abc_Ntk_t * pNtkMiter;
+ Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Out < Abc_NtkCoNum(pNtk) );
+ assert( In1 < Abc_NtkCiNum(pNtk) );
+ assert( In2 < Abc_NtkCiNum(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+ // start the new network
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) );
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
+
+ // get the root output
+ pRoot = Abc_NtkCo( pNtk, Out );
+
+ // perform strashing
+ Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 );
+ // set the first cofactor
+ Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+ if ( In2 >= 0 )
+ Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter);
+ // add the first cofactor
+ Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+
+ // save the output
+ pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
+
+ // set the second cofactor
+ Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter);
+ if ( In2 >= 0 )
+ Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+ // add the second cofactor
+ Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+
+ // save the output
+ pOutput2 = Abc_ObjFanin0(pRoot)->pCopy;
+
+ // create the miter of the two outputs
+ pMiter = Abc_AigXor( pNtkMiter->pManFunc, pOutput1, pOutput2 );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkMiter ) )
+ {
+ printf( "Abc_NtkMiter: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkMiter );
+ return NULL;
+ }
+ return pNtkMiter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the miter of two cofactors of one output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist )
+{
+ Abc_Ntk_t * pNtkMiter;
+ Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( 1 == Abc_NtkCoNum(pNtk) );
+ assert( In < Abc_NtkCiNum(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+ // start the new network
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) );
+
+ // get the root output
+ pRoot = Abc_NtkCo( pNtk, 0 );
+
+ // perform strashing
+ Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 );
+ // set the first cofactor
+ Abc_NtkCi(pNtk, In)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
+ // add the first cofactor
+ Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+ // save the output
+// pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
+ pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+ // set the second cofactor
+ Abc_NtkCi(pNtk, In)->pCopy = Abc_AigConst1(pNtkMiter);
+ // add the second cofactor
+ Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
+ // save the output
+// pOutput2 = Abc_ObjFanin0(pRoot)->pCopy;
+ pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
+
+ // create the miter of the two outputs
+ if ( fExist )
+ pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 );
+ else
+ pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkMiter ) )
+ {
+ printf( "Abc_NtkMiter: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkMiter );
+ return NULL;
+ }
+ return pNtkMiter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies all the PIs existentially from the only PO of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkTemp;
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ if ( Abc_ObjFanoutNum(pObj) == 0 )
+ continue;
+ pNtk = Abc_NtkMiterQuantify( pNtkTemp = pNtk, i, 1 );
+ Abc_NtkDelete( pNtkTemp );
+ }
+
+ return pNtk;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks the status of the miter.]
+
+ Description [Return 0 if the miter is sat for at least one output.
+ Return 1 if the miter is unsat for all its outputs. Returns -1 if the
+ miter is undecided for some outputs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter )
+{
+ Abc_Obj_t * pNodePo, * pChild;
+ int i;
+ assert( Abc_NtkIsStrash(pMiter) );
+ Abc_NtkForEachPo( pMiter, pNodePo, i )
+ {
+ pChild = Abc_ObjChild0( pNodePo );
+ // check if the output is constant 1
+ if ( Abc_AigNodeIsConst(pChild) )
+ {
+ assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) );
+ if ( !Abc_ObjIsComplement(pChild) )
+ {
+ // if the miter is constant 1, return immediately
+// printf( "MITER IS CONSTANT 1!\n" );
+ return 0;
+ }
+ }
+/*
+ // check if the output is not constant 0
+ else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) )
+ {
+ return 0;
+ }
+*/
+ // if the miter is undecided (or satisfiable), return immediately
+ else
+ return -1;
+ }
+ // return 1, meaning all outputs are constant zero
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports the status of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMiterReport( Abc_Ntk_t * pMiter )
+{
+ Abc_Obj_t * pChild, * pNode;
+ int i;
+ if ( Abc_NtkPoNum(pMiter) == 1 )
+ {
+ pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) );
+ if ( Abc_AigNodeIsConst(pChild) )
+ {
+ if ( Abc_ObjIsComplement(pChild) )
+ printf( "Unsatisfiable.\n" );
+ else
+ printf( "Satisfiable. (Constant 1).\n" );
+ }
+ else
+ printf( "Satisfiable.\n" );
+ }
+ else
+ {
+ Abc_NtkForEachPo( pMiter, pNode, i )
+ {
+ pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) );
+ printf( "Output #%2d : ", i );
+ if ( Abc_AigNodeIsConst(pChild) )
+ {
+ if ( Abc_ObjIsComplement(pChild) )
+ printf( "Unsatisfiable.\n" );
+ else
+ printf( "Satisfiable. (Constant 1).\n" );
+ }
+ else
+ printf( "Satisfiable.\n" );
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the timeframes of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
+{
+ char Buffer[1000];
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkFrames;
+ Abc_Obj_t * pLatch, * pLatchOut;
+ int i, Counter;
+ assert( nFrames > 0 );
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+ assert( Abc_NtkHasOnlyLatchBoxes(pNtk) );
+ // start the new network
+ pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
+ pNtkFrames->pName = Extra_UtilStrsav(Buffer);
+ // map the constant nodes
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames);
+ // create new latches (or their initial values) and remember them in the new latches
+ if ( !fInitial )
+ {
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ Abc_NtkDupBox( pNtkFrames, pLatch, 1 );
+ }
+ else
+ {
+ Counter = 0;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ pLatchOut = Abc_ObjFanout0(pLatch);
+ if ( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI
+ {
+ pLatchOut->pCopy = Abc_NtkCreatePi(pNtkFrames);
+ Abc_ObjAssignName( pLatchOut->pCopy, Abc_ObjName(pLatchOut), NULL );
+ Counter++;
+ }
+ else
+ pLatchOut->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) );
+ }
+ if ( Counter )
+ printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter );
+ }
+
+ // create the timeframes
+ pProgress = Extra_ProgressBarStart( stdout, nFrames );
+ for ( i = 0; i < nFrames; i++ )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Abc_NtkAddFrame( pNtkFrames, pNtk, i );
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // connect the new latches to the outputs of the last frame
+ if ( !fInitial )
+ {
+ // we cannot use pLatch->pCopy here because pLatch->pCopy is used for temporary storage of strashed values
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ Abc_ObjAddFanin( Abc_ObjFanin0(pLatch)->pCopy, Abc_ObjFanout0(pLatch)->pCopy );
+ }
+
+ // remove dangling nodes
+ Abc_AigCleanup( pNtkFrames->pManFunc );
+ // reorder the latches
+ Abc_NtkOrderCisCos( pNtkFrames );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkFrames ) )
+ {
+ printf( "Abc_NtkFrames: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkFrames );
+ return NULL;
+ }
+ return pNtkFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one time frame to the new network.]
+
+ Description [Assumes that the latches of the old network point
+ to the outputs of the previous frame of the new network (pLatch->pCopy).
+ In the end, updates the latches of the old network to point to the
+ outputs of the current frame of the new network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame )
+{
+ char Buffer[10];
+ Abc_Obj_t * pNode, * pLatch;
+ int i;
+ // create the prefix to be added to the node names
+ sprintf( Buffer, "_%02d", iFrame );
+ // add the new PI nodes
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer );
+ // add the internal nodes
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ pNode->pCopy = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+ // add the new POs
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ {
+ Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer );
+ Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+ }
+ // add the new asserts
+ Abc_NtkForEachAssert( pNtk, pNode, i )
+ {
+ Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer );
+ Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+ }
+ // transfer the implementation of the latch inputs to the latch outputs
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pCopy = Abc_ObjChild0Copy(Abc_ObjFanin0(pLatch));
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ Abc_ObjFanout0(pLatch)->pCopy = pLatch->pCopy;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the timeframes of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg )
+{
+/*
+ char Buffer[1000];
+ ProgressBar * pProgress;
+ Abc_Ntk_t * pNtkFrames;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pLatch, * pLatchNew;
+ int i, Counter;
+ assert( nFrames > 0 );
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the new network
+ pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
+ pNtkFrames->pName = Extra_UtilStrsav(Buffer);
+ // create new latches (or their initial values) and remember them in the new latches
+ if ( !fInitial )
+ {
+ Abc_NtkForEachLatch( pNtk, pLatch, i ) {
+ Abc_NtkDupObj( pNtkFrames, pLatch );
+ if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg);
+ }
+ }
+ else
+ {
+ Counter = 0;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI
+ {
+ pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames);
+ Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL );
+ Counter++;
+ }
+ else {
+ pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) );
+ }
+
+ if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg);
+ }
+ if ( Counter )
+ printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter );
+ }
+
+ // create the timeframes
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ pProgress = Extra_ProgressBarStart( stdout, nFrames );
+ for ( i = 0; i < nFrames; i++ )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+
+ // connect the new latches to the outputs of the last frame
+ if ( !fInitial )
+ {
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ pLatchNew = Abc_NtkBox(pNtkFrames, i);
+ Abc_ObjAddFanin( pLatchNew, pLatch->pCopy );
+ Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL );
+ }
+ }
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pNext = NULL;
+
+ // remove dangling nodes
+ Abc_AigCleanup( pNtkFrames->pManFunc );
+
+ // reorder the latches
+ Abc_NtkOrderCisCos( pNtkFrames );
+
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtkFrames ) )
+ {
+ printf( "Abc_NtkFrames: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkFrames );
+ return NULL;
+ }
+ return pNtkFrames;
+*/
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one time frame to the new network.]
+
+ Description [Assumes that the latches of the old network point
+ to the outputs of the previous frame of the new network (pLatch->pCopy).
+ In the end, updates the latches of the old network to point to the
+ outputs of the current frame of the new network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg )
+{
+/*
+ char Buffer[10];
+ Abc_Obj_t * pNode, * pNodeNew, * pLatch;
+ Abc_Obj_t * pConst1, * pConst1New;
+ int i;
+ // get the constant nodes
+ pConst1 = Abc_AigConst1(pNtk);
+ pConst1New = Abc_AigConst1(pNtkFrames);
+ // create the prefix to be added to the node names
+ sprintf( Buffer, "_%02d", iFrame );
+ // add the new PI nodes
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ {
+ pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode );
+ Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer );
+ if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
+ }
+ // add the internal nodes
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ if ( pNode == pConst1 )
+ pNodeNew = pConst1New;
+ else
+ pNodeNew = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+ pNode->pCopy = pNodeNew;
+ if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
+ }
+ // add the new POs
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ {
+ pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode );
+ Abc_ObjAddFanin( pNodeNew, Abc_ObjChild0Copy(pNode) );
+ Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer );
+ if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
+ }
+ // transfer the implementation of the latch drivers to the latches
+
+ // it is important that these two steps are performed it two loops
+ // and not in the same loop
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pNext = Abc_ObjChild0Copy(pLatch);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ pLatch->pCopy = pLatch->pNext;
+
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if (addFrameMapping) {
+ // don't give Mike complemented pointers because he doesn't like it
+ if (Abc_ObjIsComplement(pLatch->pCopy)) {
+ pNodeNew = Abc_NtkCreateNode( pNtkFrames );
+ Abc_ObjAddFanin( pNodeNew, pLatch->pCopy );
+ assert(Abc_ObjFaninNum(pNodeNew) == 1);
+ pNodeNew->Level = 1 + Abc_ObjRegular(pLatch->pCopy)->Level;
+
+ pLatch->pNext = pNodeNew;
+ pLatch->pCopy = pNodeNew;
+ }
+ addFrameMapping(pLatch->pCopy, pLatch, iFrame+1, arg);
+ }
+ }
+*/
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Splits the miter into two logic cones combined by an EXOR]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDemiter( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode;
+ Abc_Obj_t * pPoNew;
+ Vec_Ptr_t * vNodes1, * vNodes2;
+ int nCommon, i;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+ if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) )
+ {
+ printf( "The root of the miter is not an EXOR gate.\n" );
+ return 0;
+ }
+ pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB );
+ assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) );
+ if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) )
+ {
+ pNodeA = Abc_ObjNot(pNodeA);
+ pNodeB = Abc_ObjNot(pNodeB);
+ }
+
+ // add the PO corresponding to control input
+ pPoNew = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAddFanin( pPoNew, pNodeC );
+ Abc_ObjAssignName( pPoNew, "addOut1", NULL );
+
+ // add the PO corresponding to other input
+ pPoNew = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAddFanin( pPoNew, pNodeB );
+ Abc_ObjAssignName( pPoNew, "addOut2", NULL );
+
+ // mark the nodes in the first cone
+ pNodeB = Abc_ObjRegular(pNodeB);
+ vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 );
+ vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 );
+
+ Vec_PtrForEachEntry( vNodes1, pNode, i )
+ pNode->fMarkA = 1;
+ nCommon = 0;
+ Vec_PtrForEachEntry( vNodes2, pNode, i )
+ nCommon += pNode->fMarkA;
+ Vec_PtrForEachEntry( vNodes1, pNode, i )
+ pNode->fMarkA = 0;
+
+ printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon );
+ Vec_PtrFree( vNodes1 );
+ Vec_PtrFree( vNodes2 );
+
+ // reorder the latches
+ Abc_NtkOrderCisCos( pNtk );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtk ) )
+ printf( "Abc_NtkDemiter: The network check has failed.\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes OR or AND of the POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd )
+{
+ Abc_Obj_t * pNode, * pMiter;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+// assert( Abc_NtkLatchNum(pNtk) == 0 );
+ if ( Abc_NtkPoNum(pNtk) == 1 )
+ return 1;
+ // start the result
+ if ( fAnd )
+ pMiter = Abc_AigConst1(pNtk);
+ else
+ pMiter = Abc_ObjNot( Abc_AigConst1(pNtk) );
+ // perform operations on the POs
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ if ( fAnd )
+ pMiter = Abc_AigAnd( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) );
+ else
+ pMiter = Abc_AigOr( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) );
+ // remove the POs and their names
+ for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- )
+ Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) );
+ assert( Abc_NtkPoNum(pNtk) == 0 );
+ // create the new PO
+ pNode = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAddFanin( pNode, pMiter );
+ Abc_ObjAssignName( pNode, "miter", NULL );
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkOrPos: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMulti.c b/src/base/abci/abcMulti.c
new file mode 100644
index 00000000..e93360a0
--- /dev/null
+++ b/src/base/abci/abcMulti.c
@@ -0,0 +1,643 @@
+/**CFile****************************************************************
+
+ FileName [abcMulti.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures which transform an AIG into multi-input AND-graph.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld );
+
+static DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins );
+static DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld );
+
+static void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax );
+static void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk );
+static void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh );
+static void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk );
+static void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk );
+static void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the AIG into nodes.]
+
+ Description [Threhold is the max number of nodes duplicated at a node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor )
+{
+ Abc_Ntk_t * pNtkNew;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( nThresh >= 0 );
+ assert( nFaninMax > 1 );
+
+ // print a warning about choice nodes
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" );
+
+ // define the boundary
+ if ( fCnf )
+ Abc_NtkMultiSetBoundsCnf( pNtk );
+ else if ( fMulti )
+ Abc_NtkMultiSetBoundsMulti( pNtk, nThresh );
+ else if ( fSimple )
+ Abc_NtkMultiSetBoundsSimple( pNtk );
+ else if ( fFactor )
+ Abc_NtkMultiSetBoundsFactor( pNtk );
+ else
+ Abc_NtkMultiSetBounds( pNtk, nThresh, nFaninMax );
+
+ // perform renoding for this boundary
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
+ Abc_NtkMultiInt( pNtk, pNtkNew );
+ Abc_NtkFinalize( pNtk, pNtkNew );
+
+ // make the network minimum base
+ Abc_NtkMinimumBase( pNtkNew );
+
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+
+ // report the number of CNF objects
+ if ( fCnf )
+ {
+// int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew);
+// printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses );
+ }
+//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) );
+
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkMulti: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the AIG into nodes.]
+
+ Description [Threhold is the max number of nodes duplicated at a node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+ ProgressBar * pProgress;
+ Abc_Obj_t * pNode, * pConst1, * pNodeNew;
+ int i;
+
+ // set the constant node
+ pConst1 = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pConst1) > 0 )
+ {
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData );
+ pConst1->pCopy = pNodeNew;
+ }
+
+ // perform renoding for POs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+ continue;
+ Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) );
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // clean the boundaries and data field in the old network
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ {
+ pNode->fMarkA = 0;
+ pNode->pData = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the best multi-input node rooted at the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld )
+{
+ Vec_Ptr_t * vCone;
+ Abc_Obj_t * pNodeNew;
+ int i;
+
+ assert( !Abc_ObjIsComplement(pNodeOld) );
+ // return if the result if known
+ if ( pNodeOld->pCopy )
+ return pNodeOld->pCopy;
+ assert( Abc_ObjIsNode(pNodeOld) );
+ assert( !Abc_AigNodeIsConst(pNodeOld) );
+ assert( pNodeOld->fMarkA );
+
+//printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) );
+
+ // collect the renoding cone
+ vCone = Vec_PtrAlloc( 10 );
+ Abc_NtkMultiCone( pNodeOld, vCone );
+
+ // create a new node
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ for ( i = 0; i < vCone->nSize; i++ )
+ Abc_ObjAddFanin( pNodeNew, Abc_NtkMulti_rec(pNtkNew, vCone->pArray[i]) );
+
+ // derive the function of this node
+ pNodeNew->pData = Abc_NtkMultiDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone );
+ Cudd_Ref( pNodeNew->pData );
+ Vec_PtrFree( vCone );
+
+ // remember the node
+ pNodeOld->pCopy = pNodeNew;
+ return pNodeOld->pCopy;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the local BDD of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld )
+{
+ Abc_Obj_t * pFaninOld;
+ DdNode * bFunc;
+ int i;
+ assert( !Abc_AigNodeIsConst(pNodeOld) );
+ assert( Abc_ObjIsNode(pNodeOld) );
+ // set the elementary BDD variables for the input nodes
+ for ( i = 0; i < vFaninsOld->nSize; i++ )
+ {
+ pFaninOld = vFaninsOld->pArray[i];
+ pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFaninOld->pData );
+ pFaninOld->fMarkC = 1;
+ }
+ // call the recursive BDD computation
+ bFunc = Abc_NtkMultiDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc );
+ // dereference the intermediate nodes
+ for ( i = 0; i < vFaninsOld->nSize; i++ )
+ {
+ pFaninOld = vFaninsOld->pArray[i];
+ Cudd_RecursiveDeref( dd, pFaninOld->pData );
+ pFaninOld->fMarkC = 0;
+ }
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the local BDD of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins )
+{
+ DdNode * bFunc, * bFunc0, * bFunc1;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // if the result is available return
+ if ( pNode->fMarkC )
+ {
+ assert( pNode->pData ); // network has a cycle
+ return pNode->pData;
+ }
+ // mark the node as visited
+ pNode->fMarkC = 1;
+ Vec_PtrPush( vFanins, pNode );
+ // compute the result for both branches
+ bFunc0 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 );
+ bFunc1 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 );
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) );
+ // get the final result
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ // set the result
+ pNode->pData = bFunc;
+ assert( pNode->pData );
+ return bFunc;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Limits the cones to be no more than the given size.]
+
+ Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMultiLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst )
+{
+ int nNodes0, nNodes1;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // check if the node should be added to the fanins
+ if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) )
+ {
+ Vec_PtrPushUnique( vCone, pNode );
+ return 0;
+ }
+ // if we cannot stop in this branch, collect all nodes
+ if ( !fCanStop )
+ {
+ Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 );
+ Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+ return 0;
+ }
+ // if we can stop, try the left branch first, and return if we stopped
+ assert( vCone->nSize == 0 );
+ if ( Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) )
+ return 1;
+ // save the number of nodes in the left branch and call for the right branch
+ nNodes0 = vCone->nSize;
+ assert( nNodes0 <= nFaninMax );
+ Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+ // check the number of nodes
+ if ( vCone->nSize <= nFaninMax )
+ return 0;
+ // the number of nodes exceeds the limit
+
+ // get the number of nodes in the right branch
+ vCone->nSize = 0;
+ Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
+ // if this number exceeds the limit, solve the problem for this branch
+ if ( vCone->nSize > nFaninMax )
+ {
+ int RetValue;
+ vCone->nSize = 0;
+ RetValue = Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 );
+ assert( RetValue == 1 );
+ return 1;
+ }
+
+ nNodes1 = vCone->nSize;
+ assert( nNodes1 <= nFaninMax );
+ if ( nNodes0 >= nNodes1 )
+ { // the left branch is larger - cut it
+ assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 );
+ Abc_ObjFanin(pNode,0)->fMarkA = 1;
+ }
+ else
+ { // the right branch is larger - cut it
+ assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 );
+ Abc_ObjFanin(pNode,1)->fMarkA = 1;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Limits the cones to be no more than the given size.]
+
+ Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMultiLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax )
+{
+ vCone->nSize = 0;
+ return Abc_NtkMultiLimit_rec( pNode, vCone, nFaninMax, 1, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the expansion boundary for multi-input nodes.]
+
+ Description [The boundary includes the set of PIs and all nodes such that
+ when expanding over the node we duplicate no more than nThresh nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax )
+{
+ Vec_Ptr_t * vCone = Vec_PtrAlloc(10);
+ Abc_Obj_t * pNode;
+ int i, nFanouts, nConeSize;
+
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // mark the nodes with multiple fanouts
+ nFanouts = Abc_ObjFanoutNum(pNode);
+ nConeSize = Abc_NodeMffcSize(pNode);
+ if ( (nFanouts - 1) * nConeSize > nThresh )
+ pNode->fMarkA = 1;
+ }
+
+ // mark the PO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+
+ // make sure the fanin limit is met
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ if ( pNode->fMarkA == 0 )
+ continue;
+ // continue cutting branches until it meets the fanin limit
+ while ( Abc_NtkMultiLimit(pNode, vCone, nFaninMax) );
+ assert( vCone->nSize <= nFaninMax );
+ }
+ Vec_PtrFree(vCone);
+/*
+ // make sure the fanin limit is met
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ if ( pNode->fMarkA == 0 )
+ continue;
+ Abc_NtkMultiCone( pNode, vCone );
+ assert( vCone->nSize <= nFaninMax );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the expansion boundary for conversion into CNF.]
+
+ Description [The boundary includes the set of PIs, the roots of MUXes,
+ the nodes with multiple fanouts and the nodes with complemented outputs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, nMuxes;
+
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // mark the nodes with multiple fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1 )
+ pNode->fMarkA = 1;
+ // mark the nodes that are roots of MUXes
+ if ( Abc_NodeIsMuxType( pNode ) )
+ {
+ pNode->fMarkA = 1;
+ Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1;
+ Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1;
+ Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1;
+ Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1;
+ }
+ else // mark the complemented edges
+ {
+ if ( Abc_ObjFaninC0(pNode) )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+ if ( Abc_ObjFaninC1(pNode) )
+ Abc_ObjFanin1(pNode)->fMarkA = 1;
+ }
+ }
+
+ // mark the PO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+
+ // count the number of MUXes
+ nMuxes = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ if ( Abc_NodeIsMuxType(pNode) &&
+ Abc_ObjFanin0(pNode)->fMarkA == 0 &&
+ Abc_ObjFanin1(pNode)->fMarkA == 0 )
+ nMuxes++;
+ }
+// printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
+{
+ Abc_Obj_t * pNode;
+ int i, nFanouts, nConeSize;
+
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip PI/PO nodes
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // mark the nodes with multiple fanouts
+// if ( Abc_ObjFanoutNum(pNode) > 1 )
+// pNode->fMarkA = 1;
+ // mark the nodes with multiple fanouts
+ nFanouts = Abc_ObjFanoutNum(pNode);
+ nConeSize = Abc_NodeMffcSizeStop(pNode);
+ if ( (nFanouts - 1) * nConeSize > nThresh )
+ pNode->fMarkA = 1;
+ // mark the children if they are pointed by the complemented edges
+ if ( Abc_ObjFaninC0(pNode) )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+ if ( Abc_ObjFaninC1(pNode) )
+ Abc_ObjFanin1(pNode)->fMarkA = 1;
+ }
+
+ // mark the PO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets a simple boundary.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets a factor-cut boundary.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ // make sure the mark is not set
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ assert( pNode->fMarkA == 0 );
+ // mark the nodes where expansion stops using pNode->fMarkA
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode));
+ // mark the PO drivers
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ Abc_ObjFanin0(pNode)->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the fanins of a large node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+{
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) )
+ {
+ Vec_PtrPushUnique( vCone, pNode );
+ return;
+ }
+ Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone );
+ Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the fanins of a large node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+{
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ vCone->nSize = 0;
+ Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone );
+ Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcMv.c b/src/base/abci/abcMv.c
new file mode 100644
index 00000000..2858b8a7
--- /dev/null
+++ b/src/base/abci/abcMv.c
@@ -0,0 +1,369 @@
+/**CFile****************************************************************
+
+ FileName [abcMv.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Multi-valued decomposition.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Mv_Man_t_ Mv_Man_t;
+struct Mv_Man_t_
+{
+ int nInputs; // the number of 4-valued input variables
+ int nFuncs; // the number of 4-valued functions
+ DdManager * dd; // representation of functions
+ DdNode * bValues[15][4]; // representation of i-sets
+ DdNode * bValueDcs[15][4]; // representation of i-sets don't-cares
+ DdNode * bFuncs[15]; // representation of functions
+};
+
+static void Abc_MvDecompose( Mv_Man_t * p );
+static void Abc_MvPrintStats( Mv_Man_t * p );
+static void Abc_MvRead( Mv_Man_t * p );
+static void Abc_MvDeref( Mv_Man_t * p );
+static DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvExperiment()
+{
+ Mv_Man_t * p;
+ // get the functions
+ p = ALLOC( Mv_Man_t, 1 );
+ memset( p, 0, sizeof(Mv_Man_t) );
+ p->dd = Cudd_Init( 32, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->nFuncs = 15;
+ p->nInputs = 9;
+ Abc_MvRead( p );
+ // process the functions
+ Abc_MvPrintStats( p );
+// Cudd_ReduceHeap( p->dd, CUDD_REORDER_SYMM_SIFT, 1 );
+// Abc_MvPrintStats( p );
+ // try detecting support reducing bound set
+ Abc_MvDecompose( p );
+
+ // remove the manager
+ Abc_MvDeref( p );
+ Extra_StopManager( p->dd );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvPrintStats( Mv_Man_t * p )
+{
+ int i, v;
+ for ( i = 0; i < 15; i++ )
+ {
+ printf( "%2d : ", i );
+ printf( "%3d (%2d) ", Cudd_DagSize(p->bFuncs[i])-1, Cudd_SupportSize(p->dd, p->bFuncs[i]) );
+ for ( v = 0; v < 4; v++ )
+ printf( "%d = %3d (%2d) ", v, Cudd_DagSize(p->bValues[i][v])-1, Cudd_SupportSize(p->dd, p->bValues[i][v]) );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars )
+{
+ DdNode * bCube, * bVar, * bTemp;
+ int i;
+ bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube );
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pLine[i] == '-' )
+ continue;
+ else if ( pLine[i] == '0' ) // 0
+ bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) );
+ else if ( pLine[i] == '1' ) // 1
+ bVar = Cudd_bddIthVar(dd, 29-i);
+ else assert(0);
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bCube );
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvRead( Mv_Man_t * p )
+{
+ FILE * pFile;
+ char Buffer[1000], * pLine;
+ DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum;
+ int i, v;
+
+ // start the cube
+ bCubeSum = Cudd_ReadLogicZero(p->dd); Cudd_Ref( bCubeSum );
+
+ // start the values
+ for ( i = 0; i < 15; i++ )
+ for ( v = 0; v < 4; v++ )
+ {
+ p->bValues[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValues[i][v] );
+ p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValueDcs[i][v] );
+ }
+
+ // read the file
+ pFile = fopen( "input.pla", "r" );
+ while ( fgets( Buffer, 1000, pFile ) )
+ {
+ if ( Buffer[0] == '#' )
+ continue;
+ if ( Buffer[0] == '.' )
+ {
+ if ( Buffer[1] == 'e' )
+ break;
+ continue;
+ }
+
+ // get the cube
+ bCube = Abc_MvReadCube( p->dd, Buffer, 18 ); Cudd_Ref( bCube );
+
+ // add it to the values of the output functions
+ pLine = Buffer + 19;
+ for ( i = 0; i < 15; i++ )
+ {
+ if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' )
+ {
+ for ( v = 0; v < 4; v++ )
+ {
+ p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube ); Cudd_Ref( p->bValueDcs[i][v] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ continue;
+ }
+ else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0
+ v = 0;
+ else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1
+ v = 1;
+ else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2
+ v = 2;
+ else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3
+ v = 3;
+ else assert( 0 );
+ // add the value
+ p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube ); Cudd_Ref( p->bValues[i][v] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+
+ // add the cube
+ bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube ); Cudd_Ref( bCubeSum );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ }
+
+ // add the complement of the domain to all values
+ for ( i = 0; i < 15; i++ )
+ for ( v = 0; v < 4; v++ )
+ {
+ if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) )
+ continue;
+ p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] ); Cudd_Ref( p->bValues[i][v] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) ); Cudd_Ref( p->bValues[i][v] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) );
+ Cudd_RecursiveDeref( p->dd, bCubeSum );
+
+ // create each output function
+ for ( i = 0; i < 15; i++ )
+ {
+ p->bFuncs[i] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bFuncs[i] );
+ for ( v = 0; v < 4; v++ )
+ {
+ bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) );
+ bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) );
+ bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube );
+ bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ // add the value
+ p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd ); Cudd_Ref( p->bFuncs[i] );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bProd );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvDeref( Mv_Man_t * p )
+{
+ int i, v;
+ for ( i = 0; i < 15; i++ )
+ for ( v = 0; v < 4; v++ )
+ {
+ Cudd_RecursiveDeref( p->dd, p->bValues[i][v] );
+ Cudd_RecursiveDeref( p->dd, p->bValueDcs[i][v] );
+ }
+ for ( i = 0; i < 15; i++ )
+ Cudd_RecursiveDeref( p->dd, p->bFuncs[i] );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_MvDecompose( Mv_Man_t * p )
+{
+ DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes;
+ int k, i1, i2, v1, v2;//, c1, c2, Counter;
+
+ bVar0 = Cudd_bddIthVar(p->dd, 30);
+ bVar1 = Cudd_bddIthVar(p->dd, 31);
+ bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube );
+
+ for ( k = 0; k < p->nFuncs; k++ )
+ {
+ printf( "FUNCTION %d\n", k );
+ for ( i1 = 0; i1 < p->nFuncs; i1++ )
+ for ( i2 = i1+1; i2 < p->nFuncs; i2++ )
+ {
+ Vec_Ptr_t * vCofs;
+
+ for ( v1 = 0; v1 < 4; v1++ )
+ {
+ bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1 ), ((v1 & 1) == 0) );
+ bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) );
+ bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube1 );
+ for ( v2 = 0; v2 < 4; v2++ )
+ {
+ bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2 ), ((v2 & 1) == 0) );
+ bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) );
+ bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube2 );
+ bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 ); Cudd_Ref( bVarCube );
+ bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube ); Cudd_Ref( bCofs[v1 * 4 + v2] );
+ Cudd_RecursiveDeref( p->dd, bVarCube );
+ Cudd_RecursiveDeref( p->dd, bVarCube2 );
+ }
+ Cudd_RecursiveDeref( p->dd, bVarCube1 );
+ }
+/*
+ // check the compatibility of cofactors
+ Counter = 0;
+ for ( c1 = 0; c1 < 16; c1++ )
+ {
+ for ( c2 = 0; c2 <= c1; c2++ )
+ printf( " " );
+ for ( c2 = c1+1; c2 < 16; c2++ )
+ {
+ bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube ); Cudd_Ref( bRes );
+ if ( bRes == Cudd_ReadOne(p->dd) )
+ {
+ printf( "+" );
+ Counter++;
+ }
+ else
+ {
+ printf( " " );
+ }
+ Cudd_RecursiveDeref( p->dd, bRes );
+ }
+ printf( "\n" );
+ }
+*/
+
+ vCofs = Vec_PtrAlloc( 16 );
+ for ( v1 = 0; v1 < 4; v1++ )
+ for ( v2 = 0; v2 < 4; v2++ )
+ Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] );
+ printf( "%d ", Vec_PtrSize(vCofs) );
+ Vec_PtrFree( vCofs );
+
+ // free the cofactors
+ for ( v1 = 0; v1 < 4; v1++ )
+ for ( v2 = 0; v2 < 4; v2++ )
+ Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] );
+
+ printf( "\n" );
+// printf( "%2d, %2d : %3d\n", i1, i2, Counter );
+ }
+ }
+
+ Cudd_RecursiveDeref( p->dd, bCube );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c
new file mode 100644
index 00000000..f127811e
--- /dev/null
+++ b/src/base/abci/abcNtbdd.c
@@ -0,0 +1,582 @@
+/**CFile****************************************************************
+
+ FileName [abcNtbdd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures to translate between the BDD and the network.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew );
+static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node );
+static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the network isomorphic to the given BDD.]
+
+ Description [Assumes that the BDD depends on the variables whose indexes
+ correspond to the names in the array (pNamesPi). Otherwise, returns NULL.
+ The resulting network comes with one node, whose functionality is
+ equal to the given BDD. To decompose this BDD into the network of
+ multiplexers use Abc_NtkBddToMuxes(). To decompose this BDD into
+ an And-Inverter Graph, use Abc_NtkStrash().]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi )
+{
+ Abc_Ntk_t * pNtk;
+ Vec_Ptr_t * vNamesPiFake = NULL;
+ Abc_Obj_t * pNode, * pNodePi, * pNodePo;
+ DdNode * bSupp, * bTemp;
+ char * pName;
+ int i;
+
+ // supply fake names if real names are not given
+ if ( pNamePo == NULL )
+ pNamePo = "F";
+ if ( vNamesPi == NULL )
+ {
+ vNamesPiFake = Abc_NodeGetFakeNames( dd->size );
+ vNamesPi = vNamesPiFake;
+ }
+
+ // make sure BDD depends on the variables whose index
+ // does not exceed the size of the array with PI names
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) )
+ if ( (int)Cudd_NodeReadIndex(bTemp) >= Vec_PtrSize(vNamesPi) )
+ break;
+ Cudd_RecursiveDeref( dd, bSupp );
+ if ( bTemp != Cudd_ReadOne(dd) )
+ return NULL;
+
+ // start the network
+ pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
+ pNtk->pName = Extra_UtilStrsav(pNamePo);
+ // make sure the new manager has enough inputs
+ Cudd_bddIthVar( pNtk->pManFunc, Vec_PtrSize(vNamesPi) );
+ // add the PIs corresponding to the names
+ Vec_PtrForEachEntry( vNamesPi, pName, i )
+ Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), pName, NULL );
+ // create the node
+ pNode = Abc_NtkCreateNode( pNtk );
+ pNode->pData = Cudd_bddTransfer( dd, pNtk->pManFunc, bFunc ); Cudd_Ref(pNode->pData);
+ Abc_NtkForEachPi( pNtk, pNodePi, i )
+ Abc_ObjAddFanin( pNode, pNodePi );
+ // create the only PO
+ pNodePo = Abc_NtkCreatePo( pNtk );
+ Abc_ObjAddFanin( pNodePo, pNode );
+ Abc_ObjAssignName( pNodePo, pNamePo, NULL );
+ // make the network minimum base
+ Abc_NtkMinimumBase( pNtk );
+ if ( vNamesPiFake )
+ Abc_NodeFreeNames( vNamesPiFake );
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkDeriveFromBdd(): Network check has failed.\n" );
+ return pNtk;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates the network isomorphic to the union of local BDDs of the nodes.]
+
+ Description [The nodes of the local BDDs are converted into the network nodes
+ with logic functions equal to the MUX.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ assert( Abc_NtkIsBddLogic(pNtk) );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
+ Abc_NtkBddToMuxesPerform( pNtk, pNtkNew );
+ Abc_NtkFinalize( pNtk, pNtkNew );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkBddToMuxes: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network to MUXes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
+{
+ ProgressBar * pProgress;
+ Abc_Obj_t * pNode, * pNodeNew;
+ Vec_Ptr_t * vNodes;
+ int i;
+ // perform conversion in the topological order
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // convert one node
+ assert( Abc_ObjIsNode(pNode) );
+ pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew );
+ // mark the old node with the new one
+ assert( pNode->pCopy == NULL );
+ pNode->pCopy = pNodeNew;
+ }
+ Vec_PtrFree( vNodes );
+ Extra_ProgressBarStop( pProgress );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the node to MUXes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
+{
+ DdManager * dd = pNodeOld->pNtk->pManFunc;
+ DdNode * bFunc = pNodeOld->pData;
+ Abc_Obj_t * pFaninOld, * pNodeNew;
+ st_table * tBdd2Node;
+ int i;
+ // create the table mapping BDD nodes into the ABC nodes
+ tBdd2Node = st_init_table( st_ptrcmp, st_ptrhash );
+ // add the constant and the elementary vars
+ Abc_ObjForEachFanin( pNodeOld, pFaninOld, i )
+ st_insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pFaninOld->pCopy );
+ // create the new nodes recursively
+ pNodeNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node );
+ st_free_table( tBdd2Node );
+ if ( Cudd_IsComplement(bFunc) )
+ pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew );
+ return pNodeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the node to MUXes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node )
+{
+ Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC;
+ assert( !Cudd_IsComplement(bFunc) );
+ if ( bFunc == b1 )
+ return Abc_NtkCreateNodeConst1(pNtkNew);
+ if ( st_lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) )
+ return pNodeNew;
+ // solve for the children nodes
+ pNodeNew0 = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNtkNew, tBdd2Node );
+ if ( Cudd_IsComplement(cuddE(bFunc)) )
+ pNodeNew0 = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew0 );
+ pNodeNew1 = Abc_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNtkNew, tBdd2Node );
+ if ( !st_lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeNewC ) )
+ assert( 0 );
+ // create the MUX node
+ pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 );
+ st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew );
+ return pNodeNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives global BDDs for the COs of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_Obj_t * pObj, * pFanin;
+ Vec_Att_t * pAttMan;
+ DdManager * dd;
+ DdNode * bFunc;
+ int i, k, Counter;
+
+ // remove dangling nodes
+ Abc_AigCleanup( pNtk->pManFunc );
+
+ // start the manager
+ assert( Abc_NtkGlobalBdd(pNtk) == NULL );
+ dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ pAttMan = Vec_AttAlloc( 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 );
+
+ // assign the constant node BDD
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ {
+ bFunc = dd->one;
+ Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc );
+ }
+ // set the elementary variables
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ {
+ bFunc = dd->vars[i];
+// bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i];
+ Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc );
+ }
+
+ // collect the global functions of the COs
+ Counter = 0;
+ // construct the BDDs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose );
+ if ( bFunc == NULL )
+ {
+ if ( fVerbose )
+ printf( "Constructing global BDDs is aborted.\n" );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
+ Cudd_Quit( dd );
+ return NULL;
+ }
+ 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 )
+ if ( pObj->pCopy )
+ {
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pCopy );
+ pObj->pCopy = NULL;
+ }
+*/
+/*
+ // make sure all nodes are derefed
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( pObj->pCopy != NULL )
+ printf( "Abc_NtkBuildGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id );
+ if ( pObj->vFanouts.nSize > 0 )
+ printf( "Abc_NtkBuildGlobalBdds() error: Node %d has refs assigned\n", pObj->Id );
+ }
+*/
+ // reset references
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ pFanin->vFanouts.nSize++;
+
+ // reorder one more time
+ if ( fReorder )
+ {
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+ Cudd_AutodynDisable( dd );
+ }
+// Cudd_PrintInfo( dd, stdout );
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the global BDD for one AIG node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose )
+{
+ DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC;
+ int fDetectMuxes = 1;
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax )
+ {
+ Extra_ProgressBarStop( pProgress );
+ if ( fVerbose )
+ printf( "The number of live nodes reached %d.\n", nBddSizeMax );
+ fflush( stdout );
+ return NULL;
+ }
+ // if the result is available return
+ if ( Abc_ObjGlobalBdd(pNode) == NULL )
+ {
+ Abc_Obj_t * pNodeC, * pNode0, * pNode1;
+ pNode0 = Abc_ObjFanin0(pNode);
+ pNode1 = Abc_ObjFanin1(pNode);
+ // check for the special case when it is MUX/EXOR
+ if ( fDetectMuxes &&
+ Abc_ObjGlobalBdd(pNode0) == NULL && Abc_ObjGlobalBdd(pNode1) == NULL &&
+ Abc_ObjIsNode(pNode0) && Abc_ObjFanoutNum(pNode0) == 1 &&
+ Abc_ObjIsNode(pNode1) && Abc_ObjFanoutNum(pNode1) == 1 &&
+ Abc_NodeIsMuxType(pNode) )
+ {
+ // deref the fanins
+ pNode0->vFanouts.nSize--;
+ pNode1->vFanouts.nSize--;
+ // recognize the MUX
+ pNodeC = Abc_NodeRecognizeMux( pNode, &pNode1, &pNode0 );
+ assert( Abc_ObjFanoutNum(pNodeC) > 1 );
+ // dereference the control once (the second time it will be derefed when BDDs are computed)
+ pNodeC->vFanouts.nSize--;
+
+ // compute the result for all branches
+ bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFuncC == NULL )
+ return NULL;
+ Cudd_Ref( bFuncC );
+ bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc0 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc0 );
+ bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc1 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc1 );
+
+ // complement the branch BDDs
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjIsComplement(pNode0) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjIsComplement(pNode1) );
+ // get the final result
+ bFunc = Cudd_bddIte( dd, bFuncC, bFunc1, bFunc0 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ Cudd_RecursiveDeref( dd, bFuncC );
+ // add the number of used nodes
+ (*pCounter) += 3;
+ }
+ else
+ {
+ // compute the result for both branches
+ bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc0 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc0 );
+ bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc1 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc1 );
+ bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) );
+ bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) );
+ // get the final result
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ // add the number of used nodes
+ (*pCounter)++;
+ }
+ // set the result
+ assert( Abc_ObjGlobalBdd(pNode) == NULL );
+ Abc_ObjSetGlobalBdd( pNode, bFunc );
+ // increment the progress bar
+ if ( pProgress )
+ Extra_ProgressBarUpdate( pProgress, *pCounter, NULL );
+ }
+ // prepare the return value
+ bFunc = Abc_ObjGlobalBdd(pNode);
+ // dereference BDD at the node
+ if ( --pNode->vFanouts.nSize == 0 && fDropInternal )
+ {
+ Cudd_Deref( bFunc );
+ Abc_ObjSetGlobalBdd( pNode, NULL );
+ }
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the global BDDs of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan )
+{
+ return Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, fFreeMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the shared size of global BDDs of the COs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vFuncsGlob;
+ Abc_Obj_t * pObj;
+ int RetValue, i;
+ // complement the global functions
+ vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) );
+ RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) );
+ Vec_PtrFree( vFuncsGlob );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the BDD of the logic cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+double Abc_NtkSpacePercentage( Abc_Obj_t * pNode )
+{
+ /*
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pNodeR;
+ DdManager * dd;
+ DdNode * bFunc;
+ double Result;
+ int i;
+ pNodeR = Abc_ObjRegular(pNode);
+ assert( Abc_NtkIsStrash(pNodeR->pNtk) );
+ Abc_NtkCleanCopy( pNodeR->pNtk );
+ // get the CIs in the support of the node
+ vNodes = Abc_NtkNodeSupport( pNodeR->pNtk, &pNodeR, 1 );
+ // start the manager
+ dd = Cudd_Init( Vec_PtrSize(vNodes), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ // assign elementary BDDs for the CIs
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)dd->vars[i];
+ // build the BDD of the cone
+ bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, 1, NULL, NULL, 1 ); Cudd_Ref( bFunc );
+ bFunc = Cudd_NotCond( bFunc, pNode != pNodeR );
+ // count minterms
+ Result = Cudd_CountMinterm( dd, bFunc, dd->size );
+ // get the percentagle
+ Result *= 100.0;
+ for ( i = 0; i < dd->size; i++ )
+ Result /= 2;
+ // clean up
+ Cudd_Quit( dd );
+ Vec_PtrFree( vNodes );
+ return Result;
+ */
+ return 0.0;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Experiment with BDD-based representation of implications.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBddImplicationTest()
+{
+ DdManager * dd;
+ DdNode * bImp, * bSum, * bTemp;
+ int nVars = 200;
+ int nImps = 200;
+ int i, clk;
+clk = clock();
+ dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SIFT );
+ bSum = b0; Cudd_Ref( bSum );
+ for ( i = 0; i < nImps; i++ )
+ {
+ printf( "." );
+ bImp = Cudd_bddAnd( dd, dd->vars[rand()%nVars], dd->vars[rand()%nVars] ); Cudd_Ref( bImp );
+ bSum = Cudd_bddOr( dd, bTemp = bSum, bImp ); Cudd_Ref( bSum );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bImp );
+ }
+ printf( "The BDD before = %d.\n", Cudd_DagSize(bSum) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SIFT, 1 );
+ printf( "The BDD after = %d.\n", Cudd_DagSize(bSum) );
+PRT( "Time", clock() - clk );
+ Cudd_RecursiveDeref( dd, bSum );
+ Cudd_Quit( dd );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcOdc.c b/src/base/abci/abcOdc.c
new file mode 100644
index 00000000..d6e59328
--- /dev/null
+++ b/src/base/abci/abcOdc.c
@@ -0,0 +1,1134 @@
+/**CFile****************************************************************
+
+ FileName [abcOdc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Scalable computation of observability don't-cares.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcOdc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_DC_MAX_NODES (1<<15)
+
+typedef unsigned short Odc_Lit_t;
+
+typedef struct Odc_Obj_t_ Odc_Obj_t; // 16 bytes
+struct Odc_Obj_t_
+{
+ Odc_Lit_t iFan0; // first fanin
+ Odc_Lit_t iFan1; // second fanin
+ Odc_Lit_t iNext; // next node in the hash table
+ unsigned short TravId; // the traversal ID
+ unsigned uData; // the computed data
+ unsigned uMask; // the variable mask
+};
+
+typedef struct Odc_Man_t_ Odc_Man_t;
+struct Odc_Man_t_
+{
+ // dont'-care parameters
+ int nVarsMax; // the max number of cut variables
+ int nLevels; // the number of ODC levels
+ int fVerbose; // the verbosiness flag
+ int fVeryVerbose;// the verbosiness flag to print per-node stats
+ int nPercCutoff; // cutoff percentage
+
+ // windowing
+ Abc_Obj_t * pNode; // the node for windowing
+ Vec_Ptr_t * vLeaves; // the number of the cut
+ Vec_Ptr_t * vRoots; // the roots of the cut
+ Vec_Ptr_t * vBranches; // additional inputs
+
+ // internal AIG package
+ // objects
+ int nPis; // number of PIs (nVarsMax + 32)
+ int nObjs; // number of objects (Const1, PIs, ANDs)
+ int nObjsAlloc; // number of objects allocated
+ Odc_Obj_t * pObjs; // objects
+ Odc_Lit_t iRoot; // the root object
+ unsigned short nTravIds; // the number of travIDs
+ // structural hashing
+ Odc_Lit_t * pTable; // hash table
+ int nTableSize; // hash table size
+ Vec_Int_t * vUsedSpots; // the used spots
+
+ // truth tables
+ int nBits; // the number of bits
+ int nWords; // the number of words
+ Vec_Ptr_t * vTruths; // truth tables for each node
+ Vec_Ptr_t * vTruthsElem; // elementary truth tables for the PIs
+ unsigned * puTruth; // the place where the resulting truth table does
+
+ // statistics
+ int nWins; // the number of windows processed
+ int nWinsEmpty; // the number of empty windows
+ int nSimsEmpty; // the number of empty simulation infos
+ int nQuantsOver; // the number of quantification overflows
+ int nWinsFinish; // the number of windows that finished
+ int nTotalDcs; // total percentage of DCs
+
+ // runtime
+ int timeClean; // windowing
+ int timeWin; // windowing
+ int timeMiter; // computing the miter
+ int timeSim; // simulation
+ int timeQuant; // quantification
+ int timeTruth; // truth table
+ int timeTotal; // useful runtime
+ int timeAbort; // aborted runtime
+};
+
+
+// quantity of different objects
+static inline int Odc_PiNum( Odc_Man_t * p ) { return p->nPis; }
+static inline int Odc_NodeNum( Odc_Man_t * p ) { return p->nObjs - p->nPis - 1; }
+static inline int Odc_ObjNum( Odc_Man_t * p ) { return p->nObjs; }
+
+// complemented attributes of objects
+static inline int Odc_IsComplement( Odc_Lit_t Lit ) { return Lit & (Odc_Lit_t)1; }
+static inline Odc_Lit_t Odc_Regular( Odc_Lit_t Lit ) { return Lit & ~(Odc_Lit_t)1; }
+static inline Odc_Lit_t Odc_Not( Odc_Lit_t Lit ) { return Lit ^ (Odc_Lit_t)1; }
+static inline Odc_Lit_t Odc_NotCond( Odc_Lit_t Lit, int c ) { return Lit ^ (Odc_Lit_t)(c!=0); }
+
+// specialized Literals
+static inline Odc_Lit_t Odc_Const0() { return 1; }
+static inline Odc_Lit_t Odc_Const1() { return 0; }
+static inline Odc_Lit_t Odc_Var( Odc_Man_t * p, int i ) { assert( i >= 0 && i < p->nPis ); return (i+1) << 1; }
+static inline int Odc_IsConst( Odc_Lit_t Lit ) { return Lit < (Odc_Lit_t)2; }
+static inline int Odc_IsTerm( Odc_Man_t * p, Odc_Lit_t Lit ) { return (int)(Lit>>1) <= p->nPis; }
+
+// accessing internal storage
+static inline Odc_Obj_t * Odc_ObjNew( Odc_Man_t * p ) { assert( p->nObjs < p->nObjsAlloc ); return p->pObjs + p->nObjs++; }
+static inline Odc_Lit_t Odc_Obj2Lit( Odc_Man_t * p, Odc_Obj_t * pObj ) { assert( pObj ); return (pObj - p->pObjs) << 1; }
+static inline Odc_Obj_t * Odc_Lit2Obj( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) && (int)(Lit>>1) < p->nObjs ); return p->pObjs + (Lit>>1); }
+
+// fanins and their complements
+static inline Odc_Lit_t Odc_ObjChild0( Odc_Obj_t * pObj ) { return pObj->iFan0; }
+static inline Odc_Lit_t Odc_ObjChild1( Odc_Obj_t * pObj ) { return pObj->iFan1; }
+static inline Odc_Lit_t Odc_ObjFanin0( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan0); }
+static inline Odc_Lit_t Odc_ObjFanin1( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan1); }
+static inline int Odc_ObjFaninC0( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan0); }
+static inline int Odc_ObjFaninC1( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan1); }
+
+// traversal IDs
+static inline void Odc_ManIncrementTravId( Odc_Man_t * p ) { p->nTravIds++; }
+static inline void Odc_ObjSetTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { pObj->TravId = p->nTravIds; }
+static inline int Odc_ObjIsTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); }
+
+// truth tables
+static inline unsigned * Odc_ObjTruth( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) ); return Vec_PtrEntry(p->vTruths, Lit >> 1); }
+
+// iterators
+#define Odc_ForEachPi( p, Lit, i ) \
+ for ( i = 0; (i < Odc_PiNum(p)) && (((Lit) = Odc_Var(p, i)), 1); i++ )
+#define Odc_ForEachAnd( p, pObj, i ) \
+ for ( i = 1 + Odc_CiNum(p); (i < Odc_ObjNum(p)) && ((pObj) = (p)->pObjs + i); i++ )
+
+
+// exported functions
+extern Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose );
+extern void Abc_NtkDontCareClear( Odc_Man_t * p );
+extern void Abc_NtkDontCareFree( Odc_Man_t * p );
+extern int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the don't-care manager.]
+
+ Description [The parameters are the max number of cut variables,
+ the number of fanout levels used for the ODC computation, and verbosiness.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose )
+{
+ Odc_Man_t * p;
+ unsigned * pData;
+ int i, k;
+ p = ALLOC( Odc_Man_t, 1 );
+ memset( p, 0, sizeof(Odc_Man_t) );
+ assert( nVarsMax > 4 && nVarsMax < 16 );
+ assert( nLevels > 0 && nLevels < 10 );
+
+ srand( 0xABC );
+
+ // dont'-care parameters
+ p->nVarsMax = nVarsMax;
+ p->nLevels = nLevels;
+ p->fVerbose = fVerbose;
+ p->fVeryVerbose = fVeryVerbose;
+ p->nPercCutoff = 10;
+
+ // windowing
+ p->vRoots = Vec_PtrAlloc( 128 );
+ p->vBranches = Vec_PtrAlloc( 128 );
+
+ // internal AIG package
+ // allocate room for objects
+ p->nObjsAlloc = ABC_DC_MAX_NODES;
+ p->pObjs = ALLOC( Odc_Obj_t, p->nObjsAlloc * sizeof(Odc_Obj_t) );
+ p->nPis = nVarsMax + 32;
+ p->nObjs = 1 + p->nPis;
+ memset( p->pObjs, 0, p->nObjs * sizeof(Odc_Obj_t) );
+ // set the PI masks
+ for ( i = 0; i < 32; i++ )
+ p->pObjs[1 + p->nVarsMax + i].uMask = (1 << i);
+ // allocate hash table
+ p->nTableSize = p->nObjsAlloc/3 + 1;
+ p->pTable = ALLOC( Odc_Lit_t, p->nTableSize * sizeof(Odc_Lit_t) );
+ memset( p->pTable, 0, p->nTableSize * sizeof(Odc_Lit_t) );
+ p->vUsedSpots = Vec_IntAlloc( 1000 );
+
+ // truth tables
+ p->nWords = Abc_TruthWordNum( p->nVarsMax );
+ p->nBits = p->nWords * 8 * sizeof(unsigned);
+ p->vTruths = Vec_PtrAllocSimInfo( p->nObjsAlloc, p->nWords );
+ p->vTruthsElem = Vec_PtrAllocSimInfo( p->nVarsMax, p->nWords );
+
+ // set elementary truth tables
+ Abc_InfoFill( Vec_PtrEntry(p->vTruths, 0), p->nWords );
+ for ( k = 0; k < p->nVarsMax; k++ )
+ {
+// pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ pData = Vec_PtrEntry( p->vTruthsElem, k );
+ Abc_InfoClear( pData, p->nWords );
+ for ( i = 0; i < p->nBits; i++ )
+ if ( i & (1 << k) )
+ pData[i>>5] |= (1 << (i&31));
+ }
+
+ // set random truth table for the additional inputs
+ for ( k = p->nVarsMax; k < p->nPis; k++ )
+ {
+ pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ Abc_InfoRandom( pData, p->nWords );
+ }
+
+ // set the miter to the unused value
+ p->iRoot = 0xffff;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareClear( Odc_Man_t * p )
+{
+ int clk = clock();
+ // clean the structural hashing table
+ if ( Vec_IntSize(p->vUsedSpots) > p->nTableSize/3 ) // more than one third
+ memset( p->pTable, 0, sizeof(Odc_Lit_t) * p->nTableSize );
+ else
+ {
+ int iSpot, i;
+ Vec_IntForEachEntry( p->vUsedSpots, iSpot, i )
+ p->pTable[iSpot] = 0;
+ }
+ Vec_IntClear( p->vUsedSpots );
+ // reset the number of nodes
+ p->nObjs = 1 + p->nPis;
+ // reset the root node
+ p->iRoot = 0xffff;
+
+p->timeClean += clock() - clk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the don't-care manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareFree( Odc_Man_t * p )
+{
+ if ( p->fVerbose )
+ {
+ printf( "Wins = %5d. Empty = %5d. SimsEmpty = %5d. QuantOver = %5d. WinsFinish = %5d.\n",
+ p->nWins, p->nWinsEmpty, p->nSimsEmpty, p->nQuantsOver, p->nWinsFinish );
+ printf( "Ave DCs per window = %6.2f %%. Ave DCs per finished window = %6.2f %%.\n",
+ 1.0*p->nTotalDcs/p->nWins, 1.0*p->nTotalDcs/p->nWinsFinish );
+ printf( "Runtime stats of the ODC manager:\n" );
+ PRT( "Cleaning ", p->timeClean );
+ PRT( "Windowing ", p->timeWin );
+ PRT( "Miter ", p->timeMiter );
+ PRT( "Simulation ", p->timeSim );
+ PRT( "Quantifying ", p->timeQuant );
+ PRT( "Truth table ", p->timeTruth );
+ PRT( "TOTAL ", p->timeTotal );
+ PRT( "Aborted ", p->timeAbort );
+ }
+ Vec_PtrFree( p->vRoots );
+ Vec_PtrFree( p->vBranches );
+ Vec_PtrFree( p->vTruths );
+ Vec_PtrFree( p->vTruthsElem );
+ Vec_IntFree( p->vUsedSpots );
+ free( p->pObjs );
+ free( p->pTable );
+ free( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFO of the collected nodes up to the given level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit || pObj == pNode )
+ return;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent( pObj );
+ ////////////////////////////////////////
+ // try to reduce the runtime
+ if ( Abc_ObjFanoutNum(pObj) > 100 )
+ return;
+ ////////////////////////////////////////
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Abc_NtkDontCareWinSweepLeafTfo_rec( pFanout, nLevelLimit, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFO of the collected nodes up to the given level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareWinSweepLeafTfo( Odc_Man_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NtkDontCareWinSweepLeafTfo_rec( pObj, p->pNode->Level + p->nLevels, p->pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively collects the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareWinCollectRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( Abc_ObjIsNode(pObj) );
+ assert( Abc_NodeIsTravIdCurrent(pObj) );
+ // check if the node has all fanouts marked
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( !Abc_NodeIsTravIdCurrent(pFanout) )
+ break;
+ // if some of the fanouts are unmarked, add the node to the root
+ if ( i < Abc_ObjFanoutNum(pObj) )
+ {
+ Vec_PtrPushUnique( vRoots, pObj );
+ return;
+ }
+ // otherwise, call recursively
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Abc_NtkDontCareWinCollectRoots_rec( pFanout, vRoots );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the roots of the window.]
+
+ Description [Roots of the window are the nodes that have at least
+ one fanout that it not in the TFO of the leaves.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareWinCollectRoots( Odc_Man_t * p )
+{
+ assert( !Abc_NodeIsTravIdCurrent(p->pNode) );
+ // mark the node with the old traversal ID
+ Abc_NodeSetTravIdCurrent( p->pNode );
+ // collect the roots
+ Vec_PtrClear( p->vRoots );
+ Abc_NtkDontCareWinCollectRoots_rec( p->pNode, p->vRoots );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively adds missing nodes and leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareWinAddMissing_rec( Odc_Man_t * p, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip the already collected leaves and branches
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 1;
+ // if this is not an internal node - make it a new branch
+ if ( !Abc_NodeIsTravIdPrevious(pObj) || Abc_ObjIsCi(pObj) ) //|| (int)pObj->Level <= p->nLevLeaves )
+ {
+ Abc_NodeSetTravIdCurrent( pObj );
+ Vec_PtrPush( p->vBranches, pObj );
+ return Vec_PtrSize(p->vBranches) <= 32;
+ }
+ // visit the fanins of the node
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ if ( !Abc_NtkDontCareWinAddMissing_rec( p, pFanin ) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds to the window nodes and leaves in the TFI of the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareWinAddMissing( Odc_Man_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // set the leaves
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // explore from the roots
+ Vec_PtrClear( p->vBranches );
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ if ( !Abc_NtkDontCareWinAddMissing_rec( p, pObj ) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes window for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareWindow( Odc_Man_t * p )
+{
+ // mark the TFO of the collected nodes up to the given level (p->pNode->Level + p->nWinTfoMax)
+ Abc_NtkDontCareWinSweepLeafTfo( p );
+ // find the roots of the window
+ Abc_NtkDontCareWinCollectRoots( p );
+ if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+ {
+// printf( "Empty window\n" );
+ return 0;
+ }
+ // add the nodes in the TFI of the roots that are not yet in the window
+ if ( !Abc_NtkDontCareWinAddMissing( p ) )
+ {
+// printf( "Too many branches (%d)\n", Vec_PtrSize(p->vBranches) );
+ return 0;
+ }
+ return 1;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performing hashing of two AIG Literals.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Odc_HashKey( Odc_Lit_t iFan0, Odc_Lit_t iFan1, int TableSize )
+{
+ unsigned Key = 0;
+ Key ^= Odc_Regular(iFan0) * 7937;
+ Key ^= Odc_Regular(iFan1) * 2971;
+ Key ^= Odc_IsComplement(iFan0) * 911;
+ Key ^= Odc_IsComplement(iFan1) * 353;
+ return Key % TableSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the given name node already exists in the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Odc_Lit_t * Odc_HashLookup( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+ Odc_Obj_t * pObj;
+ Odc_Lit_t * pEntry;
+ unsigned uHashKey;
+ assert( iFan0 < iFan1 );
+ // get the hash key for this node
+ uHashKey = Odc_HashKey( iFan0, iFan1, p->nTableSize );
+ // remember the spot in the hash table that will be used
+ if ( p->pTable[uHashKey] == 0 )
+ Vec_IntPush( p->vUsedSpots, uHashKey );
+ // find the entry
+ for ( pEntry = p->pTable + uHashKey; *pEntry; pEntry = &pObj->iNext )
+ {
+ pObj = Odc_Lit2Obj( p, *pEntry );
+ if ( pObj->iFan0 == iFan0 && pObj->iFan1 == iFan1 )
+ return pEntry;
+ }
+ return pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds node by structural hashing or creates a new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_And( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+ Odc_Obj_t * pObj;
+ Odc_Lit_t * pEntry;
+ unsigned uMask0, uMask1;
+ int Temp;
+ // consider trivial cases
+ if ( iFan0 == iFan1 )
+ return iFan0;
+ if ( iFan0 == Odc_Not(iFan1) )
+ return Odc_Const0();
+ if ( Odc_Regular(iFan0) == Odc_Const1() )
+ return iFan0 == Odc_Const1() ? iFan1 : Odc_Const0();
+ if ( Odc_Regular(iFan1) == Odc_Const1() )
+ return iFan1 == Odc_Const1() ? iFan0 : Odc_Const0();
+ // canonicize the fanin order
+ if ( iFan0 > iFan1 )
+ Temp = iFan0, iFan0 = iFan1, iFan1 = Temp;
+ // check if a node with these fanins exists
+ pEntry = Odc_HashLookup( p, iFan0, iFan1 );
+ if ( *pEntry )
+ return *pEntry;
+ // create a new node
+ pObj = Odc_ObjNew( p );
+ pObj->iFan0 = iFan0;
+ pObj->iFan1 = iFan1;
+ pObj->iNext = 0;
+ pObj->TravId = 0;
+ // set the mask
+ uMask0 = Odc_Lit2Obj(p, Odc_Regular(iFan0))->uMask;
+ uMask1 = Odc_Lit2Obj(p, Odc_Regular(iFan1))->uMask;
+ pObj->uMask = uMask0 | uMask1;
+ // add to the table
+ *pEntry = Odc_Obj2Lit( p, pObj );
+ return *pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Boolean OR.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_Or( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+ return Odc_Not( Odc_And(p, Odc_Not(iFan0), Odc_Not(iFan1)) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Boolean XOR.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Odc_Lit_t Odc_Xor( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 )
+{
+ return Odc_Or( p, Odc_And(p, iFan0, Odc_Not(iFan1)), Odc_And(p, Odc_Not(iFan0), iFan1) );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the window into the AIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NtkDontCareTransfer_rec( Odc_Man_t * p, Abc_Obj_t * pNode, Abc_Obj_t * pPivot )
+{
+ unsigned uData0, uData1;
+ Odc_Lit_t uLit0, uLit1, uRes0, uRes1;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // skip visited objects
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return pNode->pCopy;
+ Abc_NodeSetTravIdCurrent(pNode);
+ assert( Abc_ObjIsNode(pNode) );
+ // consider the case when the node is the pivot
+ if ( pNode == pPivot )
+ return pNode->pCopy = (void *)((Odc_Const1() << 16) | Odc_Const0());
+ // compute the cofactors
+ uData0 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin0(pNode), pPivot );
+ uData1 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin1(pNode), pPivot );
+ // find the 0-cofactor
+ uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Abc_ObjFaninC0(pNode) );
+ uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Abc_ObjFaninC1(pNode) );
+ uRes0 = Odc_And( p, uLit0, uLit1 );
+ // find the 1-cofactor
+ uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Abc_ObjFaninC0(pNode) );
+ uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Abc_ObjFaninC1(pNode) );
+ uRes1 = Odc_And( p, uLit0, uLit1 );
+ // find the result
+ return pNode->pCopy = (void *)((uRes1 << 16) | uRes0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the window into the AIG package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareTransfer( Odc_Man_t * p )
+{
+ Abc_Obj_t * pObj;
+ Odc_Lit_t uRes0, uRes1;
+ Odc_Lit_t uLit;
+ unsigned uData;
+ int i;
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ // set elementary variables at the leaves
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ {
+ uLit = Odc_Var( p, i );
+ pObj->pCopy = (void *)((uLit << 16) | uLit);
+ Abc_NodeSetTravIdCurrent(pObj);
+ }
+ // set elementary variables at the branched
+ Vec_PtrForEachEntry( p->vBranches, pObj, i )
+ {
+ uLit = Odc_Var( p, i+p->nVarsMax );
+ pObj->pCopy = (void *)((uLit << 16) | uLit);
+ Abc_NodeSetTravIdCurrent(pObj);
+ }
+ // compute the AIG for the window
+ p->iRoot = Odc_Const0();
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ {
+ uData = (unsigned)Abc_NtkDontCareTransfer_rec( p, pObj, p->pNode );
+ // get the cofactors
+ uRes0 = uData & 0xffff;
+ uRes1 = uData >> 16;
+ // compute the miter
+// assert( uRes0 != uRes1 ); // may be false if the node is redundant w.r.t. this root
+ uLit = Odc_Xor( p, uRes0, uRes1 );
+ p->iRoot = Odc_Or( p, p->iRoot, uLit );
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the pair of cofactors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uMask )
+{
+ Odc_Obj_t * pObj;
+ unsigned uData0, uData1;
+ Odc_Lit_t uLit0, uLit1, uRes0, uRes1;
+ assert( !Odc_IsComplement(Lit) );
+ // skip visited objects
+ pObj = Odc_Lit2Obj( p, Lit );
+ if ( Odc_ObjIsTravIdCurrent(p, pObj) )
+ return pObj->uData;
+ Odc_ObjSetTravIdCurrent(p, pObj);
+ // skip objects out of the cone
+ if ( (pObj->uMask & uMask) == 0 )
+ return pObj->uData = ((Lit << 16) | Lit);
+ // consider the case when the node is the var
+ if ( pObj->uMask == uMask && Odc_IsTerm(p, Lit) )
+ return pObj->uData = ((Odc_Const1() << 16) | Odc_Const0());
+ // compute the cofactors
+ uData0 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin0(pObj), uMask );
+ uData1 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin1(pObj), uMask );
+ // find the 0-cofactor
+ uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Odc_ObjFaninC0(pObj) );
+ uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Odc_ObjFaninC1(pObj) );
+ uRes0 = Odc_And( p, uLit0, uLit1 );
+ // find the 1-cofactor
+ uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Odc_ObjFaninC0(pObj) );
+ uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Odc_ObjFaninC1(pObj) );
+ uRes1 = Odc_And( p, uLit0, uLit1 );
+ // find the result
+ return pObj->uData = ((uRes1 << 16) | uRes0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies the branch variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareQuantify( Odc_Man_t * p )
+{
+ Odc_Lit_t uRes0, uRes1;
+ unsigned uData;
+ int i;
+ assert( p->iRoot < 0xffff );
+ assert( Vec_PtrSize(p->vBranches) <= 32 ); // the mask size
+ for ( i = 0; i < Vec_PtrSize(p->vBranches); i++ )
+ {
+ // compute the cofactors w.r.t. this variable
+ Odc_ManIncrementTravId( p );
+ uData = Abc_NtkDontCareCofactors_rec( p, Odc_Regular(p->iRoot), (1 << i) );
+ uRes0 = Odc_NotCond( (Odc_Lit_t)(uData & 0xffff), Odc_IsComplement(p->iRoot) );
+ uRes1 = Odc_NotCond( (Odc_Lit_t)(uData >> 16), Odc_IsComplement(p->iRoot) );
+ // quantify this variable existentially
+ p->iRoot = Odc_Or( p, uRes0, uRes1 );
+ // check the limit
+ if ( Odc_ObjNum(p) > ABC_DC_MAX_NODES/2 )
+ return 0;
+ }
+ assert( p->nObjs <= p->nObjsAlloc );
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Set elementary truth tables for PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetElem2( Odc_Man_t * p )
+{
+ unsigned * pData;
+ int i, k;
+ for ( k = 0; k < p->nVarsMax; k++ )
+ {
+ pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ Abc_InfoClear( pData, p->nWords );
+ for ( i = 0; i < p->nBits; i++ )
+ if ( i & (1 << k) )
+ pData[i>>5] |= (1 << (i&31));
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Set elementary truth tables for PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetElem( Odc_Man_t * p )
+{
+ unsigned * pData, * pData2;
+ int k;
+ for ( k = 0; k < p->nVarsMax; k++ )
+ {
+ pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ pData2 = Vec_PtrEntry( p->vTruthsElem, k );
+ Abc_InfoCopy( pData, pData2, p->nWords );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Set random simulation words for PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulateSetRand( Odc_Man_t * p )
+{
+ unsigned * pData;
+ int w, k, Number;
+ for ( w = 0; w < p->nWords; w++ )
+ {
+ Number = rand();
+ for ( k = 0; k < p->nVarsMax; k++ )
+ {
+ pData = Odc_ObjTruth( p, Odc_Var(p, k) );
+ pData[w] = (Number & (1<<k)) ? ~0 : 0;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Set random simulation words for PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareCountMintsWord( Odc_Man_t * p, unsigned * puTruth )
+{
+ int w, Counter = 0;
+ for ( w = 0; w < p->nWords; w++ )
+ if ( puTruth[w] )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareTruthOne( Odc_Man_t * p, Odc_Lit_t Lit )
+{
+ Odc_Obj_t * pObj;
+ unsigned * pInfo, * pInfo1, * pInfo2;
+ int k, fComp1, fComp2;
+ assert( !Odc_IsComplement( Lit ) );
+ assert( !Odc_IsTerm( p, Lit ) );
+ // get the truth tables
+ pObj = Odc_Lit2Obj( p, Lit );
+ pInfo = Odc_ObjTruth( p, Lit );
+ pInfo1 = Odc_ObjTruth( p, Odc_ObjFanin0(pObj) );
+ pInfo2 = Odc_ObjTruth( p, Odc_ObjFanin1(pObj) );
+ fComp1 = Odc_ObjFaninC0( pObj );
+ fComp2 = Odc_ObjFaninC1( pObj );
+ // simulate
+ if ( fComp1 && fComp2 )
+ for ( k = 0; k < p->nWords; k++ )
+ pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+ else if ( fComp1 && !fComp2 )
+ for ( k = 0; k < p->nWords; k++ )
+ pInfo[k] = ~pInfo1[k] & pInfo2[k];
+ else if ( !fComp1 && fComp2 )
+ for ( k = 0; k < p->nWords; k++ )
+ pInfo[k] = pInfo1[k] & ~pInfo2[k];
+ else // if ( fComp1 && fComp2 )
+ for ( k = 0; k < p->nWords; k++ )
+ pInfo[k] = pInfo1[k] & pInfo2[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDontCareSimulate_rec( Odc_Man_t * p, Odc_Lit_t Lit )
+{
+ Odc_Obj_t * pObj;
+ assert( !Odc_IsComplement(Lit) );
+ // skip terminals
+ if ( Odc_IsTerm(p, Lit) )
+ return;
+ // skip visited objects
+ pObj = Odc_Lit2Obj( p, Lit );
+ if ( Odc_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Odc_ObjSetTravIdCurrent(p, pObj);
+ // call recursively
+ Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin0(pObj) );
+ Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin1(pObj) );
+ // construct the truth table
+ Abc_NtkDontCareTruthOne( p, Lit );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of the care set.]
+
+ Description [Returns the number of ones in the simulation info.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareSimulate( Odc_Man_t * p, unsigned * puTruth )
+{
+ Odc_ManIncrementTravId( p );
+ Abc_NtkDontCareSimulate_rec( p, Odc_Regular(p->iRoot) );
+ Abc_InfoCopy( puTruth, Odc_ObjTruth(p, Odc_Regular(p->iRoot)), p->nWords );
+ if ( Odc_IsComplement(p->iRoot) )
+ Abc_InfoNot( puTruth, p->nWords );
+ return Extra_TruthCountOnes( puTruth, p->nVarsMax );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of the care set.]
+
+ Description [Returns the number of ones in the simulation info.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareSimulateBefore( Odc_Man_t * p, unsigned * puTruth )
+{
+ int nIters = 2;
+ int nRounds, Counter, r;
+ // decide how many rounds to simulate
+ nRounds = p->nBits / p->nWords;
+ Counter = 0;
+ for ( r = 0; r < nIters; r++ )
+ {
+ Abc_NtkDontCareSimulateSetRand( p );
+ Abc_NtkDontCareSimulate( p, puTruth );
+ Counter += Abc_NtkDontCareCountMintsWord( p, puTruth );
+ }
+ // normalize
+ Counter = Counter * nRounds / nIters;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes ODCs for the node in terms of the cut variables.]
+
+ Description [Returns the number of don't care minterms in the truth table.
+ In particular, this procedure returns 0 if there is no don't-cares.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth )
+{
+ int nMints, RetValue;
+ int clk, clkTotal = clock();
+
+ p->nWins++;
+
+ // set the parameters
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ assert( Vec_PtrSize(vLeaves) <= p->nVarsMax );
+ p->vLeaves = vLeaves;
+ p->pNode = pNode;
+
+ // compute the window
+clk = clock();
+ RetValue = Abc_NtkDontCareWindow( p );
+p->timeWin += clock() - clk;
+ if ( !RetValue )
+ {
+p->timeAbort += clock() - clkTotal;
+ Abc_InfoFill( puTruth, p->nWords );
+ p->nWinsEmpty++;
+ return 0;
+ }
+
+ if ( p->fVeryVerbose )
+ {
+ printf( " %5d : ", pNode->Id );
+ printf( "Leaf = %2d ", Vec_PtrSize(p->vLeaves) );
+ printf( "Root = %2d ", Vec_PtrSize(p->vRoots) );
+ printf( "Bran = %2d ", Vec_PtrSize(p->vBranches) );
+ printf( " | " );
+ }
+
+ // transfer the window into the AIG package
+clk = clock();
+ Abc_NtkDontCareTransfer( p );
+p->timeMiter += clock() - clk;
+
+ // simulate to estimate the amount of don't-cares
+clk = clock();
+ nMints = Abc_NtkDontCareSimulateBefore( p, puTruth );
+p->timeSim += clock() - clk;
+ if ( p->fVeryVerbose )
+ {
+ printf( "AIG = %5d ", Odc_NodeNum(p) );
+ printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits );
+ }
+
+ // if there is less then the given percentage of don't-cares, skip
+ if ( 100.0 * (p->nBits - nMints) / p->nBits < 1.0 * p->nPercCutoff )
+ {
+p->timeAbort += clock() - clkTotal;
+ if ( p->fVeryVerbose )
+ printf( "Simulation cutoff.\n" );
+ Abc_InfoFill( puTruth, p->nWords );
+ p->nSimsEmpty++;
+ return 0;
+ }
+
+ // quantify external variables
+clk = clock();
+ RetValue = Abc_NtkDontCareQuantify( p );
+p->timeQuant += clock() - clk;
+ if ( !RetValue )
+ {
+p->timeAbort += clock() - clkTotal;
+ if ( p->fVeryVerbose )
+ printf( "=== Overflow! ===\n" );
+ Abc_InfoFill( puTruth, p->nWords );
+ p->nQuantsOver++;
+ return 0;
+ }
+
+ // get the truth table
+clk = clock();
+ Abc_NtkDontCareSimulateSetElem( p );
+ nMints = Abc_NtkDontCareSimulate( p, puTruth );
+p->timeTruth += clock() - clk;
+ if ( p->fVeryVerbose )
+ {
+ printf( "AIG = %5d ", Odc_NodeNum(p) );
+ printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits );
+ printf( "\n" );
+ }
+p->timeTotal += clock() - clkTotal;
+ p->nWinsFinish++;
+ p->nTotalDcs += (int)(100.0 * (p->nBits - nMints) / p->nBits);
+ return nMints;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcOrder.c b/src/base/abci/abcOrder.c
new file mode 100644
index 00000000..04417f77
--- /dev/null
+++ b/src/base/abci/abcOrder.c
@@ -0,0 +1,131 @@
+/**CFile****************************************************************
+
+ FileName [abcOrder.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Exploring static BDD variable orders.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Changes the order of primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose )
+{
+ Vec_Ptr_t * vSupp;
+ vSupp = Abc_NtkSupport( pNtk );
+ Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse );
+ Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the given variable order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose )
+{
+ char Buffer[1000];
+ FILE * pFile;
+ Vec_Ptr_t * vSupp;
+ Abc_Obj_t * pObj;
+ pFile = fopen( pFileName, "r" );
+ vSupp = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) );
+ while ( fscanf( pFile, "%s", Buffer ) == 1 )
+ {
+ pObj = Abc_NtkFindCi( pNtk, Buffer );
+ if ( pObj == NULL || !Abc_ObjIsCi(pObj) )
+ {
+ printf( "Name \"%s\" is not a PI name. Cannot use this order.\n", Buffer );
+ Vec_PtrFree( vSupp );
+ fclose( pFile );
+ return;
+ }
+ Vec_PtrPush( vSupp, pObj );
+ }
+ fclose( pFile );
+ if ( Vec_PtrSize(vSupp) != Abc_NtkCiNum(pNtk) )
+ {
+ printf( "The number of names in the order (%d) is not the same as the number of PIs (%d).\n", Vec_PtrSize(vSupp), Abc_NtkCiNum(pNtk) );
+ Vec_PtrFree( vSupp );
+ return;
+ }
+ Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse );
+ Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Changes the order of primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ assert( Vec_PtrSize(vSupp) == Abc_NtkCiNum(pNtk) );
+ // order CIs using the array
+ if ( fReverse )
+ Vec_PtrForEachEntry( vSupp, pObj, i )
+ Vec_PtrWriteEntry( pNtk->vCis, Vec_PtrSize(vSupp)-1-i, pObj );
+ else
+ Vec_PtrForEachEntry( vSupp, pObj, i )
+ Vec_PtrWriteEntry( pNtk->vCis, i, pObj );
+ // order PIs accordingly
+ Vec_PtrClear( pNtk->vPis );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjIsPi(pObj) )
+ Vec_PtrPush( pNtk->vPis, pObj );
+// Abc_NtkForEachCi( pNtk, pObj, i )
+// printf( "%s ", Abc_ObjName(pObj) );
+// printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcPart.c b/src/base/abci/abcPart.c
new file mode 100644
index 00000000..85c4e918
--- /dev/null
+++ b/src/base/abci/abcPart.c
@@ -0,0 +1,1205 @@
+/**CFile****************************************************************
+
+ FileName [abcPart.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Output partitioning package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcPart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Supp_Man_t_ Supp_Man_t;
+struct Supp_Man_t_
+{
+ int nChunkSize; // the size of one chunk of memory (~1 Mb)
+ int nStepSize; // the step size in saving memory (~64 bytes)
+ char * pFreeBuf; // the pointer to free memory
+ int nFreeSize; // the size of remaining free memory
+ Vec_Ptr_t * vMemory; // the memory allocated
+ Vec_Ptr_t * vFree; // the vector of free pieces of memory
+};
+
+typedef struct Supp_One_t_ Supp_One_t;
+struct Supp_One_t_
+{
+ int nRefs; // the number of references
+ int nOuts; // the number of outputs
+ int nOutsAlloc; // the array size
+ int pOuts[0]; // the array of outputs
+};
+
+static inline int Supp_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); }
+static inline char * Supp_OneNext( char * pPart ) { return *((char **)pPart); }
+static inline void Supp_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Start the memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize )
+{
+ Supp_Man_t * p;
+ p = ALLOC( Supp_Man_t, 1 );
+ memset( p, 0, sizeof(Supp_Man_t) );
+ p->nChunkSize = nChunkSize;
+ p->nStepSize = nStepSize;
+ p->vMemory = Vec_PtrAlloc( 1000 );
+ p->vFree = Vec_PtrAlloc( 1000 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Supp_ManStop( Supp_Man_t * p )
+{
+ void * pMemory;
+ int i;
+ Vec_PtrForEachEntry( p->vMemory, pMemory, i )
+ free( pMemory );
+ Vec_PtrFree( p->vMemory );
+ Vec_PtrFree( p->vFree );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fetches the memory entry of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Supp_ManFetch( Supp_Man_t * p, int nSize )
+{
+ int Type, nSizeReal;
+ char * pMemory;
+ assert( nSize > 0 );
+ Type = Supp_SizeType( nSize, p->nStepSize );
+ Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
+ if ( pMemory = Vec_PtrEntry( p->vFree, Type ) )
+ {
+ Vec_PtrWriteEntry( p->vFree, Type, Supp_OneNext(pMemory) );
+ return pMemory;
+ }
+ nSizeReal = p->nStepSize * Type;
+ if ( p->nFreeSize < nSizeReal )
+ {
+ p->pFreeBuf = ALLOC( char, p->nChunkSize );
+ p->nFreeSize = p->nChunkSize;
+ Vec_PtrPush( p->vMemory, p->pFreeBuf );
+ }
+ assert( p->nFreeSize >= nSizeReal );
+ pMemory = p->pFreeBuf;
+ p->pFreeBuf += nSizeReal;
+ p->nFreeSize -= nSizeReal;
+ return pMemory;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the memory entry of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize )
+{
+ int Type;
+ Type = Supp_SizeType( nSize, p->nStepSize );
+ Vec_PtrFillExtra( p->vFree, Type + 1, NULL );
+ Supp_OneSetNext( pMemory, Vec_PtrEntry(p->vFree, Type) );
+ Vec_PtrWriteEntry( p->vFree, Type, pMemory );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fetches the memory entry of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs )
+{
+ Supp_One_t * pPart;
+ pPart = (Supp_One_t *)Supp_ManFetch( p, sizeof(Supp_One_t) + sizeof(int) * nWords );
+ pPart->nRefs = nRefs;
+ pPart->nOuts = 0;
+ pPart->nOutsAlloc = nWords;
+ return pPart;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the memory entry of the given size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry )
+{
+ assert( pEntry->nOuts <= pEntry->nOutsAlloc );
+ assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 );
+ Supp_ManRecycle( p, (char *)pEntry, sizeof(Supp_One_t) + sizeof(int) * pEntry->nOutsAlloc );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs )
+{
+ Supp_One_t * p = Supp_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs );
+ int * pBeg1 = p1->pOuts;
+ int * pBeg2 = p2->pOuts;
+ int * pBeg = p->pOuts;
+ int * pEnd1 = p1->pOuts + p1->nOuts;
+ int * pEnd2 = p2->pOuts + p2->nOuts;
+ while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
+ {
+ if ( *pBeg1 == *pBeg2 )
+ *pBeg++ = *pBeg1++, pBeg2++;
+ else if ( *pBeg1 < *pBeg2 )
+ *pBeg++ = *pBeg1++;
+ else
+ *pBeg++ = *pBeg2++;
+ }
+ while ( pBeg1 < pEnd1 )
+ *pBeg++ = *pBeg1++;
+ while ( pBeg2 < pEnd2 )
+ *pBeg++ = *pBeg2++;
+ p->nOuts = pBeg - p->pOuts;
+ assert( p->nOuts <= p->nOutsAlloc );
+ assert( p->nOuts >= p1->nOuts );
+ assert( p->nOuts >= p2->nOuts );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tranfers the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p )
+{
+ Vec_Int_t * vSupp;
+ int i;
+ vSupp = Vec_IntAlloc( p->nOuts );
+ for ( i = 0; i < p->nOuts; i++ )
+ Vec_IntPush( vSupp, p->pOuts[i] );
+ return vSupp;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes supports of the POs in the multi-output AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pNext;
+ int i, k;
+ assert( Abc_NtkIsStrash(pNtk) );
+ vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) );
+ Abc_NtkIncrementTravId( pNtk );
+ // add the constant-1 nodes
+ pObj = Abc_AigConst1(pNtk);
+ Abc_NodeSetTravIdCurrent( pObj );
+ Vec_PtrPush( vNodes, pObj );
+ // add the CIs/nodes/COs in the topological order
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ // check the fanins and add CIs
+ Abc_ObjForEachFanin( pObj, pNext, k )
+ if ( Abc_ObjIsCi(pNext) && !Abc_NodeIsTravIdCurrent(pNext) )
+ {
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vNodes, pNext );
+ }
+ // add the node
+ Vec_PtrPush( vNodes, pObj );
+ // check the fanouts and add COs
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ if ( Abc_ObjIsCo(pNext) && !Abc_NodeIsTravIdCurrent(pNext) )
+ {
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes supports of the POs.]
+
+ Description [Returns the ptr-vector of int-vectors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkComputeSupportsSmart( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vSupports;
+ Vec_Ptr_t * vNodes;
+ Vec_Int_t * vSupp;
+ Supp_Man_t * p;
+ Supp_One_t * pPart0, * pPart1;
+ Abc_Obj_t * pObj;
+ int i;
+ // set the number of PIs/POs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = (Abc_Obj_t *)i;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pNext = (Abc_Obj_t *)i;
+ // start the support computation manager
+ p = Supp_ManStart( 1 << 20, 1 << 6 );
+ // consider objects in the topological order
+ vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkCleanCopy(pNtk);
+ // order the nodes so that the PIs and POs follow naturally
+ vNodes = Abc_NtkDfsNatural( pNtk );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ if ( Abc_ObjIsNode(pObj) )
+ {
+ pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy;
+ pPart1 = (Supp_One_t *)Abc_ObjFanin1(pObj)->pCopy;
+ pObj->pCopy = (Abc_Obj_t *)Supp_ManMergeEntry( p, pPart0, pPart1, Abc_ObjFanoutNum(pObj) );
+ assert( pPart0->nRefs > 0 );
+ if ( --pPart0->nRefs == 0 )
+ Supp_ManRecycleEntry( p, pPart0 );
+ assert( pPart1->nRefs > 0 );
+ if ( --pPart1->nRefs == 0 )
+ Supp_ManRecycleEntry( p, pPart1 );
+ continue;
+ }
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy;
+ // only save the CO if it is non-trivial
+ if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+ {
+ vSupp = Supp_ManTransferEntry(pPart0);
+ Vec_IntPush( vSupp, (int)pObj->pNext );
+ Vec_PtrPush( vSupports, vSupp );
+ }
+ assert( pPart0->nRefs > 0 );
+ if ( --pPart0->nRefs == 0 )
+ Supp_ManRecycleEntry( p, pPart0 );
+ continue;
+ }
+ if ( Abc_ObjIsCi(pObj) )
+ {
+ if ( Abc_ObjFanoutNum(pObj) )
+ {
+ pPart0 = (Supp_One_t *)Supp_ManFetchEntry( p, 1, Abc_ObjFanoutNum(pObj) );
+ pPart0->pOuts[ pPart0->nOuts++ ] = (int)pObj->pNext;
+ pObj->pCopy = (Abc_Obj_t *)pPart0;
+ }
+ continue;
+ }
+ if ( pObj == Abc_AigConst1(pNtk) )
+ {
+ if ( Abc_ObjFanoutNum(pObj) )
+ pObj->pCopy = (Abc_Obj_t *)Supp_ManFetchEntry( p, 0, Abc_ObjFanoutNum(pObj) );
+ continue;
+ }
+ assert( 0 );
+ }
+ Vec_PtrFree( vNodes );
+//printf( "Memory usage = %d Mb.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) );
+ Supp_ManStop( p );
+ // sort supports by size
+ Vec_VecSort( (Vec_Vec_t *)vSupports, 1 );
+ // clear the number of PIs/POs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = NULL;
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pNext = NULL;
+/*
+ Vec_PtrForEachEntry( vSupports, vSupp, i )
+ printf( "%d ", Vec_IntSize(vSupp) );
+ printf( "\n" );
+*/
+ return vSupports;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes supports of the POs using naive method.]
+
+ Description [Returns the ptr-vector of int-vectors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkComputeSupportsNaive( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vSupp, * vSupports;
+ Vec_Int_t * vSuppI;
+ Abc_Obj_t * pObj, * pTemp;
+ int i, k;
+ // set the PI numbers
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = (void *)i;
+ // save the CI numbers
+ vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) )
+ continue;
+ vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+ vSuppI = (Vec_Int_t *)vSupp;
+ Vec_PtrForEachEntry( vSupp, pTemp, k )
+ Vec_IntWriteEntry( vSuppI, k, (int)pTemp->pNext );
+ Vec_IntSort( vSuppI, 0 );
+ // append the number of this output
+ Vec_IntPush( vSuppI, i );
+ // save the support in the vector
+ Vec_PtrPush( vSupports, vSuppI );
+ }
+ // clean the CI numbers
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = NULL;
+ // sort supports by size
+ Vec_VecSort( (Vec_Vec_t *)vSupports, 1 );
+/*
+ Vec_PtrForEachEntry( vSupports, vSuppI, i )
+ printf( "%d ", Vec_IntSize(vSuppI) );
+ printf( "\n" );
+*/
+ return vSupports;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start bitwise support representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Abc_NtkSuppCharStart( Vec_Int_t * vOne, int nPis )
+{
+ unsigned * pBuffer;
+ int i, Entry;
+ int nWords = Abc_BitWordNum(nPis);
+ pBuffer = ALLOC( unsigned, nWords );
+ memset( pBuffer, 0, sizeof(unsigned) * nWords );
+ Vec_IntForEachEntry( vOne, Entry, i )
+ {
+ assert( Entry < nPis );
+ Abc_InfoSetBit( pBuffer, Entry );
+ }
+ return pBuffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add to bitwise support representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis )
+{
+ int i, Entry;
+ Vec_IntForEachEntry( vOne, Entry, i )
+ {
+ assert( Entry < nPis );
+ Abc_InfoSetBit( pBuffer, Entry );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the common variables using bitwise support representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne )
+{
+ int i, Entry, nCommon = 0;
+ Vec_IntForEachEntry( vOne, Entry, i )
+ nCommon += Abc_InfoHasBit(pBuffer, Entry);
+ return nCommon;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the best partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nSuppSizeLimit, Vec_Int_t * vOne )
+{
+/*
+ Vec_Int_t * vPartSupp, * vPart;
+ double Attract, Repulse, Cost, CostBest;
+ int i, nCommon, iBest;
+ iBest = -1;
+ CostBest = 0.0;
+ Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i )
+ {
+ vPart = Vec_PtrEntry( vPartsAll, i );
+ if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) >= nPartSizeLimit )
+ continue;
+ nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne );
+ if ( nCommon == 0 )
+ continue;
+ if ( nCommon == Vec_IntSize(vOne) )
+ return i;
+ Attract = 1.0 * nCommon / Vec_IntSize(vOne);
+ if ( Vec_IntSize(vPartSupp) < 100 )
+ Repulse = 1.0;
+ else
+ Repulse = log10( Vec_IntSize(vPartSupp) / 10.0 );
+ Cost = pow( Attract, pow(Repulse, 5.0) );
+ if ( CostBest < Cost )
+ {
+ CostBest = Cost;
+ iBest = i;
+ }
+ }
+ if ( CostBest < 0.6 )
+ return -1;
+ return iBest;
+*/
+
+ Vec_Int_t * vPartSupp;//, * vPart;
+ int Attract, Repulse, Value, ValueBest;
+ int i, nCommon, iBest;
+// int nCommon2;
+ iBest = -1;
+ ValueBest = 0;
+ Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i )
+ {
+ // skip partitions with too many outputs
+// vPart = Vec_PtrEntry( vPartsAll, i );
+// if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit )
+// continue;
+ // find the number of common variables between this output and the partitions
+// nCommon2 = Vec_IntTwoCountCommon( vPartSupp, vOne );
+ nCommon = Abc_NtkSuppCharCommon( Vec_PtrEntry(vPartSuppsChar, i), vOne );
+// assert( nCommon2 == nCommon );
+ // if no common variables, continue searching
+ if ( nCommon == 0 )
+ continue;
+ // if all variables are common, the best partition if found
+ if ( nCommon == Vec_IntSize(vOne) )
+ return i;
+ // skip partitions whose size exceeds the limit
+ if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit )
+ continue;
+ // figure out might be the good partition for this one
+ Attract = 1000 * nCommon / Vec_IntSize(vOne);
+ if ( Vec_IntSize(vPartSupp) < 100 )
+ Repulse = 1;
+ else
+ Repulse = 1+Extra_Base2Log(Vec_IntSize(vPartSupp)-100);
+ Value = Attract/Repulse;
+ if ( ValueBest < Value )
+ {
+ ValueBest = Value;
+ iBest = i;
+ }
+ }
+ if ( ValueBest < 75 )
+ return -1;
+ return iBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform the smart partitioning.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll )
+{
+ Vec_Int_t * vOne;
+ int i, nOutputs, Counter;
+
+ Counter = 0;
+ Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
+ {
+ nOutputs = Vec_IntSize(Vec_PtrEntry(vPartsAll, i));
+ printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs );
+ Counter += nOutputs;
+ if ( i == Vec_PtrSize(vPartsAll) - 1 )
+ break;
+ }
+// assert( Counter == Abc_NtkCoNum(pNtk) );
+ printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform the smart partitioning.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit )
+{
+ Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
+ int i, iPart;
+
+ if ( nSuppSizeLimit == 0 )
+ nSuppSizeLimit = 200;
+
+ // pack smaller partitions into larger blocks
+ iPart = 0;
+ vPart = vPartSupp = NULL;
+ Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
+ {
+ if ( Vec_IntSize(vOne) < nSuppSizeLimit )
+ {
+ if ( vPartSupp == NULL )
+ {
+ assert( vPart == NULL );
+ vPartSupp = Vec_IntDup(vOne);
+ vPart = Vec_PtrEntry(vPartsAll, i);
+ }
+ else
+ {
+ vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
+ Vec_IntFree( vTemp );
+ vPart = Vec_IntTwoMerge( vTemp = vPart, Vec_PtrEntry(vPartsAll, i) );
+ Vec_IntFree( vTemp );
+ Vec_IntFree( Vec_PtrEntry(vPartsAll, i) );
+ }
+ if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit )
+ continue;
+ }
+ else
+ vPart = Vec_PtrEntry(vPartsAll, i);
+ // add the partition
+ Vec_PtrWriteEntry( vPartsAll, iPart, vPart );
+ vPart = NULL;
+ if ( vPartSupp )
+ {
+ Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) );
+ Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
+ vPartSupp = NULL;
+ }
+ iPart++;
+ }
+ // add the last one
+ if ( vPart )
+ {
+ Vec_PtrWriteEntry( vPartsAll, iPart, vPart );
+ vPart = NULL;
+
+ assert( vPartSupp != NULL );
+ Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) );
+ Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
+ vPartSupp = NULL;
+ iPart++;
+ }
+ Vec_PtrShrink( vPartsAll, iPart );
+ Vec_PtrShrink( vPartsAll, iPart );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform the smart partitioning.]
+
+ Description [Returns the ptr-vector of int-vectors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose )
+{
+ ProgressBar * pProgress;
+ Vec_Ptr_t * vPartSuppsChar;
+ Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll;
+ Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
+ int i, iPart, iOut, clk, clk2, timeFind = 0;
+
+ // compute the supports for all outputs
+clk = clock();
+// vSupps = Abc_NtkComputeSupportsNaive( pNtk );
+ vSupps = Abc_NtkComputeSupportsSmart( pNtk );
+if ( fVerbose )
+{
+PRT( "Supps", clock() - clk );
+}
+ // start char-based support representation
+ vPartSuppsChar = Vec_PtrAlloc( 1000 );
+
+ // create partitions
+clk = clock();
+ vPartsAll = Vec_PtrAlloc( 256 );
+ vPartSuppsAll = Vec_PtrAlloc( 256 );
+ pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vSupps) );
+ Vec_PtrForEachEntry( vSupps, vOne, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+// if ( i % 1000 == 0 )
+// printf( "CIs = %6d. COs = %6d. Processed = %6d (out of %6d). Parts = %6d.\r",
+// Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), i, Vec_PtrSize(vSupps), Vec_PtrSize(vPartsAll) );
+ // get the output number
+ iOut = Vec_IntPop(vOne);
+ // find closely matching part
+clk2 = clock();
+ iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nSuppSizeLimit, vOne );
+timeFind += clock() - clk2;
+ if ( iPart == -1 )
+ {
+ // create new partition
+ vPart = Vec_IntAlloc( 32 );
+ Vec_IntPush( vPart, iOut );
+ // create new partition support
+ vPartSupp = Vec_IntDup( vOne );
+ // add this partition and its support
+ Vec_PtrPush( vPartsAll, vPart );
+ Vec_PtrPush( vPartSuppsAll, vPartSupp );
+
+ Vec_PtrPush( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) );
+ }
+ else
+ {
+ // add output to this partition
+ vPart = Vec_PtrEntry( vPartsAll, iPart );
+ Vec_IntPush( vPart, iOut );
+ // merge supports
+ vPartSupp = Vec_PtrEntry( vPartSuppsAll, iPart );
+ vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne );
+ Vec_IntFree( vTemp );
+ // reinsert new support
+ Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp );
+
+ Abc_NtkSuppCharAdd( Vec_PtrEntry(vPartSuppsChar, iPart), vOne, Abc_NtkCiNum(pNtk) );
+ }
+ }
+ Extra_ProgressBarStop( pProgress );
+
+ // stop char-based support representation
+ Vec_PtrForEachEntry( vPartSuppsChar, vTemp, i )
+ free( vTemp );
+ Vec_PtrFree( vPartSuppsChar );
+
+//printf( "\n" );
+if ( fVerbose )
+{
+PRT( "Parts", clock() - clk );
+//PRT( "Find ", timeFind );
+}
+
+clk = clock();
+ // remember number of supports
+ Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
+ Vec_IntPush( vOne, i );
+ // sort the supports in the decreasing order
+ Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 );
+ // reproduce partitions
+ vPartsAll2 = Vec_PtrAlloc( 256 );
+ Vec_PtrForEachEntry( vPartSuppsAll, vOne, i )
+ Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) );
+ Vec_PtrFree( vPartsAll );
+ vPartsAll = vPartsAll2;
+
+ // compact small partitions
+// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll );
+ Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit );
+
+if ( fVerbose )
+{
+PRT( "Comps", clock() - clk );
+}
+ if ( fVerbose )
+ printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) );
+// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll );
+
+ // cleanup
+ Vec_VecFree( (Vec_Vec_t *)vSupps );
+ Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll );
+/*
+ // converts from intergers to nodes
+ Vec_PtrForEachEntry( vPartsAll, vPart, iPart )
+ {
+ vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) );
+ Vec_IntForEachEntry( vPart, iOut, i )
+ Vec_PtrPush( vPartPtr, Abc_NtkCo(pNtk, iOut) );
+ Vec_IntFree( vPart );
+ Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr );
+ }
+*/
+ return vPartsAll;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform the naive partitioning.]
+
+ Description [Returns the ptr-vector of int-vectors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize )
+{
+ Vec_Ptr_t * vParts;
+ Abc_Obj_t * pObj;
+ int nParts, i;
+ nParts = (Abc_NtkCoNum(pNtk) / nPartSize) + ((Abc_NtkCoNum(pNtk) % nPartSize) > 0);
+ vParts = (Vec_Ptr_t *)Vec_VecStart( nParts );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Vec_IntPush( Vec_PtrEntry(vParts, i / nPartSize), i );
+ return vParts;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts from intergers to pointers for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOutsPtr )
+{
+ int Out, i;
+ Vec_PtrClear( vOutsPtr );
+ Vec_IntForEachEntry( vOuts, Out, i )
+ Vec_PtrPush( vOutsPtr, Abc_NtkCo(pNtk, Out) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns representative of the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkPartStitchFindRepr_rec( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pRepr;
+ pRepr = Vec_PtrEntry( vEquiv, pObj->Id );
+ if ( pRepr == NULL || pRepr == pObj )
+ return pObj;
+ return Abc_NtkPartStitchFindRepr_rec( vEquiv, pRepr );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the representative of the fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Abc_Obj_t * Abc_NtkPartStitchCopy0( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFan = Abc_ObjFanin0( pObj );
+ Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan );
+ return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) );
+}
+static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFan = Abc_ObjFanin1( pObj );
+ Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan );
+ return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Hop_Obj_t * Hop_ObjChild0Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin0(pObj)->pNext, Abc_ObjFaninC0(pObj) ); }
+static inline Hop_Obj_t * Hop_ObjChild1Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin1(pObj)->pNext, Abc_ObjFaninC1(pObj) ); }
+
+
+/**Function*************************************************************
+
+ Synopsis [Stitches together several networks with choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk )
+{
+ Hop_Man_t * pMan;
+ Abc_Obj_t * pObj;
+ int i;
+ // start the HOP package
+ pMan = Hop_ManStart();
+ pMan->vObjs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) + 1 );
+ Vec_PtrPush( pMan->vObjs, Hop_ManConst1(pMan) );
+ // map constant node and PIs
+ Abc_AigConst1(pNtk)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pNext = (Abc_Obj_t *)Hop_ObjCreatePi(pMan);
+ // map the internal nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ pObj->pNext = (Abc_Obj_t *)Hop_And( pMan, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) );
+ assert( !Abc_ObjIsComplement(pObj->pNext) );
+ }
+ // set the choice nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ if ( pObj->pCopy )
+ ((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext;
+ }
+ // transfer the POs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Hop_ObjCreatePo( pMan, Hop_ObjChild0Next(pObj) );
+ // check the new manager
+ if ( !Hop_ManCheck(pMan) )
+ printf( "Abc_NtkPartStartHop: HOP manager check has failed.\n" );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stitches together several networks with choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
+{
+ extern Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan );
+
+ Hop_Man_t * pMan;
+ Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew, * pNtkTemp;
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, iNodeId;
+
+ // start a new network similar to the original one
+ assert( Abc_NtkIsStrash(pNtk) );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+
+ // annotate parts to point to the new network
+ Vec_PtrForEachEntry( vParts, pNtkTemp, i )
+ {
+ assert( Abc_NtkIsStrash(pNtkTemp) );
+ Abc_NtkCleanCopy( pNtkTemp );
+
+ // map the CI nodes
+ Abc_AigConst1(pNtkTemp)->pCopy = Abc_AigConst1(pNtkNew);
+ Abc_NtkForEachCi( pNtkTemp, pObj, k )
+ {
+ iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO );
+ if ( iNodeId == -1 )
+ {
+ printf( "Cannot find CI node %s in the original network.\n", Abc_ObjName(pObj) );
+ return NULL;
+ }
+ pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
+ }
+
+ // add the internal nodes while saving representatives
+ vNodes = Abc_AigDfs( pNtkTemp, 1, 0 );
+ Vec_PtrForEachEntry( vNodes, pObj, k )
+ {
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ assert( !Abc_ObjIsComplement(pObj->pCopy) );
+ if ( Abc_AigNodeIsChoice(pObj) )
+ for ( pFanin = pObj->pData; pFanin; pFanin = pFanin->pData )
+ pFanin->pCopy->pCopy = pObj->pCopy;
+ }
+ Vec_PtrFree( vNodes );
+
+ // map the CO nodes
+ Abc_NtkForEachCo( pNtkTemp, pObj, k )
+ {
+ iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
+ if ( iNodeId == -1 )
+ {
+ printf( "Cannot find CO node %s in the original network.\n", Abc_ObjName(pObj) );
+ return NULL;
+ }
+ pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+ }
+ }
+
+ // connect the remaining POs
+/*
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkCi( pNtkNew, i );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pCopy = Abc_NtkCo( pNtkNew, i );
+*/
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ if ( Abc_ObjFaninNum(pObj->pCopy) == 0 )
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+ }
+
+ // transform into the HOP manager
+ pMan = Abc_NtkPartStartHop( pNtkNew );
+ pNtkNew = Abc_NtkHopRemoveLoops( pNtkTemp = pNtkNew, pMan );
+ Abc_NtkDelete( pNtkTemp );
+
+ // check correctness of the new network
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkPartStitchChoices: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stitches together several networks with choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams )
+{
+ extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ Vec_Ptr_t * vParts, * vFraigs, * vOnePtr;
+ Vec_Int_t * vOne;
+ Abc_Ntk_t * pNtk, * pNtk2, * pNtkAig, * pNtkFraig;
+ int i, k;
+
+ // perform partitioning
+ pNtk = Vec_PtrEntry( vStore, 0 );
+ assert( Abc_NtkIsStrash(pNtk) );
+// vParts = Abc_NtkPartitionNaive( pNtk, 20 );
+ vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 );
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+ // fraig each partition
+ vOnePtr = Vec_PtrAlloc( 1000 );
+ vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+ Vec_PtrForEachEntry( vParts, vOne, i )
+ {
+ // start the partition
+ Abc_NtkConvertCos( pNtk, vOne, vOnePtr );
+ pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 );
+ // add nodes to the partition
+ Vec_PtrForEachEntryStart( vStore, pNtk2, k, 1 )
+ {
+ Abc_NtkConvertCos( pNtk2, vOne, vOnePtr );
+ Abc_NtkAppendToCone( pNtkAig, pNtk2, vOnePtr );
+ }
+ printf( "Fraiging part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r",
+ i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pNtkAig), Abc_NtkPoNum(pNtkAig),
+ Abc_NtkNodeNum(pNtkAig), Abc_AigLevel(pNtkAig) );
+ // fraig the partition
+ pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 1, 0 );
+ Vec_PtrPush( vFraigs, pNtkFraig );
+ Abc_NtkDelete( pNtkAig );
+ }
+ printf( " \r" );
+ Vec_VecFree( (Vec_Vec_t *)vParts );
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+ // derive the final network
+ pNtkFraig = Abc_NtkPartStitchChoices( pNtk, vFraigs );
+ Vec_PtrForEachEntry( vFraigs, pNtkAig, i )
+ Abc_NtkDelete( pNtkAig );
+ Vec_PtrFree( vFraigs );
+ Vec_PtrFree( vOnePtr );
+ return pNtkFraig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stitches together several networks with choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams )
+{
+ extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ Vec_Ptr_t * vParts, * vFraigs, * vOnePtr;
+ Vec_Int_t * vOne;
+ Abc_Ntk_t * pNtkAig, * pNtkFraig;
+ int i;
+ int clk = clock();
+
+ // perform partitioning
+ assert( Abc_NtkIsStrash(pNtk) );
+// vParts = Abc_NtkPartitionNaive( pNtk, 20 );
+ vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 );
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+ // fraig each partition
+ vOnePtr = Vec_PtrAlloc( 1000 );
+ vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+ Vec_PtrForEachEntry( vParts, vOne, i )
+ {
+ Abc_NtkConvertCos( pNtk, vOne, vOnePtr );
+ pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 );
+ pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0, 0 );
+ Vec_PtrPush( vFraigs, pNtkFraig );
+ Abc_NtkDelete( pNtkAig );
+
+ printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) );
+ }
+ Vec_VecFree( (Vec_Vec_t *)vParts );
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+ // derive the final network
+ Vec_PtrForEachEntry( vFraigs, pNtkAig, i )
+ Abc_NtkDelete( pNtkAig );
+ Vec_PtrFree( vFraigs );
+ Vec_PtrFree( vOnePtr );
+ PRT( "Partitioned fraiging time", clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcPlace.c b/src/base/abci/abcPlace.c
new file mode 100644
index 00000000..87c99e99
--- /dev/null
+++ b/src/base/abci/abcPlace.c
@@ -0,0 +1,255 @@
+/**CFile****************************************************************
+
+ FileName [abcPlace.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface with a placer.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcPlace.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+// placement includes
+#include "place_base.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+AbstractCell *abstractCells = NULL;
+ConcreteCell *cells = NULL;
+ConcreteNet *nets = NULL;
+int nAllocSize = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new cell.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_PlaceCreateCell( Abc_Obj_t * pObj, int fAnd )
+{
+ assert( cells[pObj->Id].m_id == 0 );
+
+ cells[pObj->Id].m_id = pObj->Id;
+ cells[pObj->Id].m_label = "";
+ cells[pObj->Id].m_parent = &(abstractCells[fAnd]);
+ cells[pObj->Id].m_fixed = 0;
+ addConcreteCell(&(cells[pObj->Id]));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_PlaceUpdateNet( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int k;
+ // free the old array of net terminals
+ if ( nets[pObj->Id].m_terms )
+ free( nets[pObj->Id].m_terms );
+ // fill in the net with the new information
+ nets[pObj->Id].m_id = pObj->Id;
+ nets[pObj->Id].m_weight = 1.0;
+ nets[pObj->Id].m_numTerms = Abc_ObjFanoutNum(pObj); //fanout
+ nets[pObj->Id].m_terms = ALLOC(ConcreteCell*, Abc_ObjFanoutNum(pObj));
+ Abc_ObjForEachFanout( pObj, pFanout, k )
+ nets[pObj->Id].m_terms[k] = &(cells[pFanout->Id]);
+ addConcreteNet(&(nets[pObj->Id]));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the placement cost of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins )
+{
+ Abc_Obj_t * pObj;
+// double x, y;
+ int i;
+ Vec_PtrForEachEntry( vFanins, pObj, i )
+ {
+// pObj->Id
+ }
+ return 0.0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates placement after one step of rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k;
+ Vec_Ptr_t * vCells, * vNets;
+
+ // start the arrays of new cells and nets
+ vCells = Vec_PtrAlloc( 16 );
+ vNets = Vec_PtrAlloc( 32 );
+
+ // go through the new nodes
+ Vec_PtrForEachEntry( vAddedCells, pObj, i )
+ {
+ assert( !Abc_ObjIsComplement(pObj) );
+ Abc_PlaceCreateCell( pObj, 1 );
+ Abc_PlaceUpdateNet( pObj );
+
+ // add the new cell and its fanin nets to temporary storage
+ Vec_PtrPush( vCells, &(cells[pObj->Id]) );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Vec_PtrPushUnique( vNets, &(nets[pFanin->Id]) );
+ }
+
+ // go through the modified nets
+ Vec_PtrForEachEntry( vUpdatedNets, pObj, i )
+ {
+ assert( !Abc_ObjIsComplement(pObj) );
+ if ( Abc_ObjType(pObj) == ABC_OBJ_NONE ) // dead node
+ continue;
+ Abc_PlaceUpdateNet( pObj );
+ }
+
+ // update the placement
+// fastPlace( Vec_PtrSize(vCells), (ConcreteCell **)Vec_PtrArray(vCells),
+// Vec_PtrSize(vNets), (ConcreteNet **)Vec_PtrArray(vNets) );
+
+ // clean up
+ Vec_PtrFree( vCells );
+ Vec_PtrFree( vNets );
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure is called before the writing start.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_PlaceBegin( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+
+ // allocate and clean internal storage
+ nAllocSize = 5 * Abc_NtkObjNumMax(pNtk);
+ cells = REALLOC(ConcreteCell, cells, nAllocSize);
+ nets = REALLOC(ConcreteNet, nets, nAllocSize);
+ memset( cells, 0, sizeof(ConcreteCell) * nAllocSize );
+ memset( nets, 0, sizeof(ConcreteNet) * nAllocSize );
+
+ // create AbstractCells
+ // 1: pad
+ // 2: and
+ if (!abstractCells)
+ abstractCells = ALLOC(AbstractCell,2);
+
+ abstractCells[0].m_height = 1.0;
+ abstractCells[0].m_width = 1.0;
+ abstractCells[0].m_label = "pio";
+ abstractCells[0].m_pad = 1;
+
+ abstractCells[1].m_height = 1.0;
+ abstractCells[1].m_width = 1.0;
+ abstractCells[1].m_label = "and";
+ abstractCells[1].m_pad = 0;
+
+ // input pads
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Abc_PlaceCreateCell( pObj, 0 );
+
+ // ouput pads
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_PlaceCreateCell( pObj, 0 );
+
+ // AND nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_PlaceCreateCell( pObj, 1 );
+
+ // all nets
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj) )
+ continue;
+ Abc_PlaceUpdateNet( pObj );
+ }
+
+ globalPreplace((float)0.8);
+ globalPlace();
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure is called after the writing completes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_PlaceEnd( Abc_Ntk_t * pNtk )
+{
+ int i;
+
+
+ // clean up
+ for ( i = 0; i < nAllocSize; i++ )
+ FREE( nets[i].m_terms );
+ FREE( abstractCells );
+ FREE( cells );
+ FREE( nets );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c
new file mode 100644
index 00000000..bfb380f3
--- /dev/null
+++ b/src/base/abci/abcPrint.c
@@ -0,0 +1,953 @@
+/**CFile****************************************************************
+
+ FileName [abcPrint.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Printing statistics.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcPrint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+#include "main.h"
+#include "mio.h"
+//#include "seq.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+//extern int s_TotalNodes = 0;
+//extern int s_TotalChanges = 0;
+
+int s_MappingTime = 0;
+int s_MappingMem = 0;
+int s_ResubTime = 0;
+int s_ResynTime = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Print the vital stats of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
+{
+ int Num;
+
+// if ( Abc_NtkIsStrash(pNtk) )
+// Abc_AigCountNext( pNtk->pManFunc );
+
+ fprintf( pFile, "%-13s:", pNtk->pName );
+ if ( Abc_NtkAssertNum(pNtk) )
+ fprintf( pFile, " i/o/a = %4d/%4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkAssertNum(pNtk) );
+ else
+ fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) );
+ fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) );
+ if ( Abc_NtkIsNetlist(pNtk) )
+ {
+ fprintf( pFile, " net = %5d", Abc_NtkNetNum(pNtk) );
+ fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
+ fprintf( pFile, " wbox = %3d", Abc_NtkWhiteboxNum(pNtk) );
+ fprintf( pFile, " bbox = %3d", Abc_NtkBlackboxNum(pNtk) );
+ }
+ else if ( Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
+ if ( Num = Abc_NtkGetChoiceNum(pNtk) )
+ fprintf( pFile, " (choice = %d)", Num );
+ if ( Num = Abc_NtkGetExorNum(pNtk) )
+ fprintf( pFile, " (exor = %d)", Num );
+// if ( Num2 = Abc_NtkGetMuxNum(pNtk) )
+// fprintf( pFile, " (mux = %d)", Num2-Num );
+// if ( Num2 )
+// fprintf( pFile, " (other = %d)", Abc_NtkNodeNum(pNtk)-3*Num2 );
+ }
+ else
+ {
+ fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
+ fprintf( pFile, " net = %5d", Abc_NtkGetTotalFanins(pNtk) );
+ }
+
+ if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) )
+ {
+ }
+ else if ( Abc_NtkHasSop(pNtk) )
+ {
+
+ fprintf( pFile, " cube = %5d", Abc_NtkGetCubeNum(pNtk) );
+// fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) );
+ if ( fFactored )
+ fprintf( pFile, " lit(fac) = %5d", Abc_NtkGetLitFactNum(pNtk) );
+ }
+ else if ( Abc_NtkHasAig(pNtk) )
+ fprintf( pFile, " aig = %5d", Abc_NtkGetAigNodeNum(pNtk) );
+ else if ( Abc_NtkHasBdd(pNtk) )
+ fprintf( pFile, " bdd = %5d", Abc_NtkGetBddNodeNum(pNtk) );
+ else if ( Abc_NtkHasMapping(pNtk) )
+ {
+ fprintf( pFile, " area = %5.2f", Abc_NtkGetMappedArea(pNtk) );
+ fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTrace(pNtk) );
+ }
+ else if ( !Abc_NtkHasBlackbox(pNtk) )
+ {
+ assert( 0 );
+ }
+
+ if ( Abc_NtkIsStrash(pNtk) )
+ fprintf( pFile, " lev = %3d", Abc_AigLevel(pNtk) );
+ else
+ fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) );
+
+ fprintf( pFile, "\n" );
+
+// Abc_NtkCrossCut( pNtk );
+
+ // print the statistic into a file
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "ibm/seq_stats.txt", "a+" );
+// fprintf( pTable, "%s ", pNtk->pName );
+// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+ fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+
+/*
+ // print the statistic into a file
+ {
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pSpec );
+ fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) );
+ fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+
+/*
+ // print the statistic into a file
+ {
+ FILE * pTable;
+ pTable = fopen( "x/stats_new.txt", "a+" );
+ fprintf( pTable, "%s ", pNtk->pName );
+// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) );
+// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
+// fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) );
+ fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) );
+// fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+
+ s_ResynTime = 0;
+ }
+*/
+
+/*
+ // print the statistic into a file
+ {
+ static int Counter = 0;
+ extern int timeRetime;
+ FILE * pTable;
+ Counter++;
+ pTable = fopen( "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_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 );
+ }
+*/
+
+/*
+ s_TotalNodes += Abc_NtkNodeNum(pNtk);
+ printf( "Total nodes = %6d %6.2f Mb Changes = %6d.\n",
+ s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges );
+*/
+
+// if ( Abc_NtkHasSop(pNtk) )
+// printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints PIs/POs and LIs/LOs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+
+ fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ fprintf( pFile, " %s", Abc_ObjName(pObj) );
+// fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ fprintf( pFile, " %s", Abc_ObjName(pObj) );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj),
+ Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics about latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pLatch, * pFanin;
+ int i, Counter0, Counter1, Counter2;
+ int InitNums[4], Init;
+
+ assert( !Abc_NtkIsNetlist(pNtk) );
+ if ( Abc_NtkLatchNum(pNtk) == 0 )
+ {
+ fprintf( pFile, "The network is combinational.\n" );
+ return;
+ }
+
+ for ( i = 0; i < 4; i++ )
+ InitNums[i] = 0;
+ Counter0 = Counter1 = Counter2 = 0;
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ Init = Abc_LatchInit( pLatch );
+ assert( Init < 4 );
+ InitNums[Init]++;
+
+ pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+ if ( Abc_NtkIsLogic(pNtk) )
+ {
+ if ( !Abc_NodeIsConst(pFanin) )
+ continue;
+ }
+ else if ( Abc_NtkIsStrash(pNtk) )
+ {
+ if ( !Abc_AigNodeIsConst(pFanin) )
+ continue;
+ }
+ else
+ assert( 0 );
+
+ // the latch input is a constant node
+ Counter0++;
+ if ( Abc_LatchIsInitDc(pLatch) )
+ {
+ Counter1++;
+ continue;
+ }
+ // count the number of cases when the constant is equal to the initial value
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) )
+ Counter2++;
+ }
+ else
+ {
+ if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) )
+ Counter2++;
+ }
+ }
+ fprintf( pFile, "%-15s: ", pNtk->pName );
+ fprintf( pFile, "Latch = %6d. No = %4d. Zero = %4d. One = %4d. DC = %4d.\n",
+ Abc_NtkLatchNum(pNtk), InitNums[0], InitNums[1], InitNums[2], InitNums[3] );
+ fprintf( pFile, "Const fanin = %3d. DC init = %3d. Matching init = %3d. ", Counter0, Counter1, Counter2 );
+ fprintf( pFile, "Self-feed latches = %2d.\n", -1 ); //Abc_NtkCountSelfFeedLatches(pNtk) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the distribution of fanins/fanouts in the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i, k, nFanins, nFanouts;
+ Vec_Int_t * vFanins, * vFanouts;
+ int nOldSize, nNewSize;
+
+ vFanins = Vec_IntAlloc( 0 );
+ vFanouts = Vec_IntAlloc( 0 );
+ Vec_IntFill( vFanins, 100, 0 );
+ Vec_IntFill( vFanouts, 100, 0 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ nFanins = Abc_ObjFaninNum(pNode);
+ if ( Abc_NtkIsNetlist(pNtk) )
+ nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) );
+ else
+ nFanouts = Abc_ObjFanoutNum(pNode);
+// nFanouts = Abc_NodeMffcSize(pNode);
+ if ( nFanins > vFanins->nSize || nFanouts > vFanouts->nSize )
+ {
+ nOldSize = vFanins->nSize;
+ nNewSize = ABC_MAX(nFanins, nFanouts) + 10;
+ Vec_IntGrow( vFanins, nNewSize );
+ Vec_IntGrow( vFanouts, nNewSize );
+ for ( k = nOldSize; k < nNewSize; k++ )
+ {
+ Vec_IntPush( vFanins, 0 );
+ Vec_IntPush( vFanouts, 0 );
+ }
+ }
+ vFanins->pArray[nFanins]++;
+ vFanouts->pArray[nFanouts]++;
+ }
+ fprintf( pFile, "The distribution of fanins and fanouts in the network:\n" );
+ fprintf( pFile, " Number Nodes with fanin Nodes with fanout\n" );
+ for ( k = 0; k < vFanins->nSize; k++ )
+ {
+ if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 )
+ continue;
+ fprintf( pFile, "%5d : ", k );
+ if ( vFanins->pArray[k] == 0 )
+ fprintf( pFile, " " );
+ else
+ fprintf( pFile, "%12d ", vFanins->pArray[k] );
+ fprintf( pFile, " " );
+ if ( vFanouts->pArray[k] == 0 )
+ fprintf( pFile, " " );
+ else
+ fprintf( pFile, "%12d ", vFanouts->pArray[k] );
+ fprintf( pFile, "\n" );
+ }
+ Vec_IntFree( vFanins );
+ Vec_IntFree( vFanouts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the fanins/fanouts of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pNode2;
+ int i;
+ if ( Abc_ObjIsPo(pNode) )
+ pNode = Abc_ObjFanin0(pNode);
+
+ fprintf( pFile, "Node %s", Abc_ObjName(pNode) );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, "Fanins (%d): ", Abc_ObjFaninNum(pNode) );
+ Abc_ObjForEachFanin( pNode, pNode2, i )
+ fprintf( pFile, " %s", Abc_ObjName(pNode2) );
+ fprintf( pFile, "\n" );
+
+ fprintf( pFile, "Fanouts (%d): ", Abc_ObjFaninNum(pNode) );
+ Abc_ObjForEachFanout( pNode, pNode2, i )
+ fprintf( pFile, " %s", Abc_ObjName(pNode2) );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the MFFCs of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ extern void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Abc_NodeMffsConeSuppPrint( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the factored form of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ assert( Abc_NtkIsSopLogic(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Abc_NodePrintFactor( pFile, pNode, fUseRealNames );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the factored form of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames )
+{
+ Dec_Graph_t * pGraph;
+ Vec_Ptr_t * vNamesIn;
+ if ( Abc_ObjIsCo(pNode) )
+ pNode = Abc_ObjFanin0(pNode);
+ if ( Abc_ObjIsPi(pNode) )
+ {
+ fprintf( pFile, "Skipping the PI node.\n" );
+ return;
+ }
+ if ( Abc_ObjIsLatch(pNode) )
+ {
+ fprintf( pFile, "Skipping the latch.\n" );
+ return;
+ }
+ assert( Abc_ObjIsNode(pNode) );
+ pGraph = Dec_Factor( pNode->pData );
+ if ( fUseRealNames )
+ {
+ vNamesIn = Abc_NodeGetFaninNames(pNode);
+ Dec_GraphPrint( stdout, pGraph, (char **)vNamesIn->pArray, Abc_ObjName(pNode) );
+ Abc_NodeFreeNames( vNamesIn );
+ }
+ else
+ Dec_GraphPrint( stdout, pGraph, (char **)NULL, Abc_ObjName(pNode) );
+ Dec_GraphFree( pGraph );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the level stats of the PO node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes )
+{
+ Abc_Obj_t * pNode;
+ int i, k, Length;
+
+ if ( fListNodes )
+ {
+ int nLevels;
+ nLevels = Abc_NtkLevel(pNtk);
+ printf( "Nodes by level:\n" );
+ for ( i = 0; i <= nLevels; i++ )
+ {
+ printf( "%2d : ", i );
+ Abc_NtkForEachNode( pNtk, pNode, k )
+ if ( (int)pNode->Level == i )
+ printf( " %s", Abc_ObjName(pNode) );
+ printf( "\n" );
+ }
+ return;
+ }
+
+ // print the delay profile
+ if ( fProfile && Abc_NtkHasMapping(pNtk) )
+ {
+ int nIntervals = 12;
+ float DelayMax, DelayCur, DelayDelta;
+ int * pLevelCounts;
+ int DelayInt, nOutsSum, nOutsTotal;
+
+ // get the max delay and delta
+ DelayMax = Abc_NtkDelayTrace( pNtk );
+ DelayDelta = DelayMax/nIntervals;
+ // collect outputs by delay
+ pLevelCounts = ALLOC( int, nIntervals );
+ memset( pLevelCounts, 0, sizeof(int) * nIntervals );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ DelayCur = Abc_NodeReadArrival( Abc_ObjFanin0(pNode) )->Worst;
+ DelayInt = (int)(DelayCur / DelayDelta);
+ if ( DelayInt >= nIntervals )
+ DelayInt = nIntervals - 1;
+ pLevelCounts[DelayInt]++;
+ }
+
+ nOutsSum = 0;
+ nOutsTotal = Abc_NtkCoNum(pNtk);
+ for ( i = 0; i < nIntervals; i++ )
+ {
+ nOutsSum += pLevelCounts[i];
+ printf( "[%8.2f - %8.2f] : COs = %4d. %5.1f %%\n",
+ DelayDelta * i, DelayDelta * (i+1), pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal );
+ }
+ free( pLevelCounts );
+ return;
+ }
+ else if ( fProfile )
+ {
+ int LevelMax, * pLevelCounts;
+ int nOutsSum, nOutsTotal;
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ Abc_NtkLevel(pNtk);
+
+ LevelMax = 0;
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ if ( LevelMax < (int)Abc_ObjFanin0(pNode)->Level )
+ LevelMax = Abc_ObjFanin0(pNode)->Level;
+ pLevelCounts = ALLOC( int, LevelMax + 1 );
+ memset( pLevelCounts, 0, sizeof(int) * (LevelMax + 1) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ pLevelCounts[Abc_ObjFanin0(pNode)->Level]++;
+
+ nOutsSum = 0;
+ nOutsTotal = Abc_NtkCoNum(pNtk);
+ for ( i = 0; i <= LevelMax; i++ )
+ if ( pLevelCounts[i] )
+ {
+ nOutsSum += pLevelCounts[i];
+ printf( "Level = %4d. COs = %4d. %5.1f %%\n", i, pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal );
+ }
+ free( pLevelCounts );
+ return;
+ }
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // find the longest name
+ Length = 0;
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ if ( Length < (int)strlen(Abc_ObjName(pNode)) )
+ Length = strlen(Abc_ObjName(pNode));
+ if ( Length < 5 )
+ Length = 5;
+ // print stats for each output
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ fprintf( pFile, "CO %4d : %*s ", i, Length, Abc_ObjName(pNode) );
+ Abc_NodePrintLevel( pFile, pNode );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the factored form of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pDriver;
+ Vec_Ptr_t * vNodes;
+
+ pDriver = Abc_ObjIsCo(pNode)? Abc_ObjFanin0(pNode) : pNode;
+ if ( Abc_ObjIsPi(pDriver) )
+ {
+ fprintf( pFile, "Primary input.\n" );
+ return;
+ }
+ if ( Abc_ObjIsLatch(pDriver) )
+ {
+ fprintf( pFile, "Latch.\n" );
+ return;
+ }
+ if ( Abc_NodeIsConst(pDriver) )
+ {
+ fprintf( pFile, "Constant %d.\n", !Abc_ObjFaninC0(pNode) );
+ return;
+ }
+ // print the level
+ fprintf( pFile, "Level = %3d. ", pDriver->Level );
+ // print the size of MFFC
+ fprintf( pFile, "Mffc = %5d. ", Abc_NodeMffcSize(pDriver) );
+ // print the size of the shole cone
+ vNodes = Abc_NtkDfsNodes( pNode->pNtk, &pDriver, 1 );
+ fprintf( pFile, "Cone = %5d. ", Vec_PtrSize(vNodes) );
+ Vec_PtrFree( vNodes );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the factored form of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames )
+{
+ Vec_Ptr_t * vNamesIn;
+ if ( fUseRealNames )
+ {
+ vNamesIn = Abc_NodeGetFaninNames(pNode);
+ Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData),
+ Abc_ObjFaninNum(pNode), NULL, 0, (char **)vNamesIn->pArray );
+ Abc_NodeFreeNames( vNamesIn );
+ }
+ else
+ Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData),
+ Abc_ObjFaninNum(pNode), NULL, 0, NULL );
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics about gates used in the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary )
+{
+ Abc_Obj_t * pObj;
+ int fHasBdds, i;
+ int CountConst, CountBuf, CountInv, CountAnd, CountOr, CountOther, CounterTotal;
+ char * pSop;
+
+ if ( fUseLibrary && Abc_NtkHasMapping(pNtk) )
+ {
+ stmm_table * tTable;
+ stmm_generator * gen;
+ char * pName;
+ int * pCounter, Counter;
+ double Area, AreaTotal;
+
+ // count the gates by name
+ CounterTotal = 0;
+ tTable = stmm_init_table(strcmp, stmm_strhash);
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ if ( !stmm_find_or_add( tTable, Mio_GateReadName(pObj->pData), (char ***)&pCounter ) )
+ *pCounter = 0;
+ (*pCounter)++;
+ CounterTotal++;
+ }
+ // print the gates
+ AreaTotal = Abc_NtkGetMappedArea(pNtk);
+ stmm_foreach_item( tTable, gen, (char **)&pName, (char **)&Counter )
+ {
+ Area = Counter * Mio_GateReadArea(Mio_LibraryReadGateByName(pNtk->pManFunc,pName));
+ printf( "%-12s = %8d %10.2f %6.2f %%\n", pName, Counter, Area, 100.0 * Area / AreaTotal );
+ }
+ printf( "%-12s = %8d %10.2f %6.2f %%\n", "TOTAL", CounterTotal, AreaTotal, 100.0 );
+ stmm_free_table( tTable );
+ return;
+ }
+
+ if ( Abc_NtkIsAigLogic(pNtk) )
+ return;
+
+ // transform logic functions from BDD to SOP
+ if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) )
+ {
+ if ( !Abc_NtkBddToSop(pNtk, 0) )
+ {
+ printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" );
+ return;
+ }
+ }
+
+ // get hold of the SOP of the node
+ CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ if ( Abc_NtkHasMapping(pNtk) )
+ pSop = Mio_GateReadSop(pObj->pData);
+ else
+ pSop = pObj->pData;
+ // collect the stats
+ if ( Abc_SopIsConst0(pSop) || Abc_SopIsConst1(pSop) )
+ CountConst++;
+ else if ( Abc_SopIsBuf(pSop) )
+ CountBuf++;
+ else if ( Abc_SopIsInv(pSop) )
+ CountInv++;
+ else if ( !Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) )
+ CountAnd++;
+ else if ( Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || !Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) )
+ CountOr++;
+ else
+ CountOther++;
+ CounterTotal++;
+ }
+ printf( "Const = %8d %6.2f %%\n", CountConst , 100.0 * CountConst / CounterTotal );
+ printf( "Buffer = %8d %6.2f %%\n", CountBuf , 100.0 * CountBuf / CounterTotal );
+ printf( "Inverter = %8d %6.2f %%\n", CountInv , 100.0 * CountInv / CounterTotal );
+ printf( "And = %8d %6.2f %%\n", CountAnd , 100.0 * CountAnd / CounterTotal );
+ printf( "Or = %8d %6.2f %%\n", CountOr , 100.0 * CountOr / CounterTotal );
+ printf( "Other = %8d %6.2f %%\n", CountOther , 100.0 * CountOther / CounterTotal );
+ printf( "TOTAL = %8d %6.2f %%\n", CounterTotal, 100.0 * CounterTotal / CounterTotal );
+
+ // convert the network back into BDDs if this is how it was
+ if ( fHasBdds )
+ Abc_NtkSopToBdd(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics about gates used in the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes1, * vNodes2;
+ Abc_Obj_t * pObj1, * pObj2, * pNode1, * pNode2;
+ int i, k, m, n, Counter;
+
+ // print the template
+ printf( "Statistics about sharing of logic nodes among the CO pairs.\n" );
+ printf( "(CO1,CO2)=NumShared : " );
+ // go though the CO pairs
+ Abc_NtkForEachCo( pNtk, pObj1, i )
+ {
+ vNodes1 = Abc_NtkDfsNodes( pNtk, &pObj1, 1 );
+ // mark the nodes
+ Vec_PtrForEachEntry( vNodes1, pNode1, m )
+ pNode1->fMarkA = 1;
+ // go through the second COs
+ Abc_NtkForEachCo( pNtk, pObj2, k )
+ {
+ if ( i >= k )
+ continue;
+ vNodes2 = Abc_NtkDfsNodes( pNtk, &pObj2, 1 );
+ // count the number of marked
+ Counter = 0;
+ Vec_PtrForEachEntry( vNodes2, pNode2, n )
+ Counter += pNode2->fMarkA;
+ // print
+ printf( "(%d,%d)=%d ", i, k, Counter );
+ Vec_PtrFree( vNodes2 );
+ }
+ // unmark the nodes
+ Vec_PtrForEachEntry( vNodes1, pNode1, m )
+ pNode1->fMarkA = 0;
+ Vec_PtrFree( vNodes1 );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints info for each output cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vSupp, * vNodes;
+ Abc_Obj_t * pObj;
+ int i;
+ printf( "Structural support info:\n" );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
+ vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
+ printf( "%20s : Cone = %5d. Supp = %5d.\n",
+ Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize );
+ Vec_PtrFree( vNodes );
+ Vec_PtrFree( vSupp );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints information about the object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ fprintf( pFile, "Object %5d : ", pObj->Id );
+ switch ( pObj->Type )
+ {
+ case ABC_OBJ_NONE:
+ fprintf( pFile, "NONE " );
+ break;
+ case ABC_OBJ_CONST1:
+ fprintf( pFile, "Const1 " );
+ break;
+ case ABC_OBJ_PIO:
+ fprintf( pFile, "PIO " );
+ break;
+ case ABC_OBJ_PI:
+ fprintf( pFile, "PI " );
+ break;
+ case ABC_OBJ_PO:
+ fprintf( pFile, "PO " );
+ break;
+ case ABC_OBJ_BI:
+ fprintf( pFile, "BI " );
+ break;
+ case ABC_OBJ_BO:
+ fprintf( pFile, "BO " );
+ break;
+ case ABC_OBJ_ASSERT:
+ fprintf( pFile, "Assert " );
+ break;
+ case ABC_OBJ_NET:
+ fprintf( pFile, "Net " );
+ break;
+ case ABC_OBJ_NODE:
+ fprintf( pFile, "Node " );
+ break;
+ case ABC_OBJ_LATCH:
+ fprintf( pFile, "Latch " );
+ break;
+ case ABC_OBJ_WHITEBOX:
+ fprintf( pFile, "Whitebox" );
+ break;
+ case ABC_OBJ_BLACKBOX:
+ fprintf( pFile, "Blackbox" );
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ // print the fanins
+ fprintf( pFile, " Fanins ( " );
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ fprintf( pFile, "%d ", pFanin->Id );
+ fprintf( pFile, ") " );
+/*
+ fprintf( pFile, " Fanouts ( " );
+ Abc_ObjForEachFanout( pObj, pFanin, i )
+ fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' );
+ fprintf( pFile, ") " );
+*/
+ // print the logic function
+ if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) )
+ fprintf( pFile, " %s", pObj->pData );
+ else
+ fprintf( pFile, "\n" );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c
new file mode 100644
index 00000000..618b6a0f
--- /dev/null
+++ b/src/base/abci/abcProve.c
@@ -0,0 +1,341 @@
+/**CFile****************************************************************
+
+ FileName [abcProve.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Proves the miter using AIG rewriting, FRAIGing, and SAT solving.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcProve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fraig.h"
+#include "math.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
+extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+
+static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects );
+static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns
+ a simplified version of the original network (or a constant 0 network).
+ In case the network is not a constant zero and a SAT assignment is found,
+ pNtk->pModel contains a satisfying assignment.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars )
+{
+ Prove_Params_t * pParams = pPars;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ int RetValue, nIter, nSatFails, Counter, clk, timeStart = clock();
+ sint64 nSatConfs, nSatInspects, nInspectLimit;
+
+ // get the starting network
+ pNtk = *ppNtk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+
+ if ( pParams->fVerbose )
+ {
+ printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n",
+ pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" );
+ printf( "Miter = %d (%3.1f). Rwr = %d (%3.1f). Fraig = %d (%3.1f). Last = %d.\n",
+ pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti,
+ pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti,
+ pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti, pParams->nMiteringLimitLast );
+ }
+
+ // if SAT only, solve without iteration
+ if ( !pParams->fUseRewriting && !pParams->fUseFraiging )
+ {
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+ *ppNtk = pNtk;
+ return RetValue;
+ }
+
+ // check the current resource limits
+ for ( nIter = 0; nIter < pParams->nItersMax; nIter++ )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1,
+ (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)),
+ (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) );
+ fflush( stdout );
+ }
+
+ // try brute-force SAT
+ clk = clock();
+ nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0;
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (sint64)nInspectLimit, 0, &nSatConfs, &nSatInspects );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+ if ( RetValue >= 0 )
+ break;
+
+ // add to the number of backtracks and inspects
+ pParams->nTotalBacktracksMade += nSatConfs;
+ pParams->nTotalInspectsMade += nSatInspects;
+ // check if global resource limit is reached
+ if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) ||
+ (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) )
+ {
+ printf( "Reached global limit on conflicts/inspects. Quitting.\n" );
+ *ppNtk = pNtk;
+ return -1;
+ }
+
+ // try rewriting
+ if ( pParams->fUseRewriting )
+ {
+ clk = clock();
+ Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter));
+// Counter = 1;
+ while ( 1 )
+ {
+/*
+ extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose );
+ pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 ); Abc_NtkDelete( pNtkTemp );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+*/
+/*
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+*/
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ if ( --Counter == 0 )
+ break;
+ }
+ Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose );
+ }
+
+ if ( pParams->fUseFraiging )
+ {
+ // try FRAIGing
+ clk = clock();
+ nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0;
+ pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects ); Abc_NtkDelete( pNtkTemp );
+ Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose );
+// printf( "NumFails = %d\n", nSatFails );
+ if ( RetValue >= 0 )
+ break;
+
+ // add to the number of backtracks and inspects
+ pParams->nTotalBacktracksMade += nSatConfs;
+ pParams->nTotalInspectsMade += nSatInspects;
+ // check if global resource limit is reached
+ if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) ||
+ (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) )
+ {
+ printf( "Reached global limit on conflicts/inspects. Quitting.\n" );
+ *ppNtk = pNtk;
+ return -1;
+ }
+ }
+
+ }
+
+ // try to prove it using brute force SAT
+ if ( RetValue < 0 && pParams->fUseBdds )
+ {
+ if ( pParams->fVerbose )
+ {
+ printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit );
+ fflush( stdout );
+ }
+ clk = clock();
+ pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 );
+ if ( pNtk )
+ {
+ Abc_NtkDelete( pNtkTemp );
+ RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) );
+ }
+ else
+ pNtk = pNtkTemp;
+ Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose );
+ }
+
+ 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;
+ RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)nInspectLimit, 0, NULL, NULL );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose );
+ }
+
+ // assign the model if it was proved by rewriting (const 1 miter)
+ if ( RetValue == 0 && pNtk->pModel == NULL )
+ {
+ pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) );
+ }
+ *ppNtk = pNtk;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects )
+{
+ Abc_Ntk_t * pNtkNew;
+ Fraig_Params_t Params, * pParams = &Params;
+ Fraig_Man_t * pMan;
+ int nWords1, nWords2, nWordsMin, RetValue;
+ int * pModel;
+
+ // to determine the number of simulation patterns
+ // use the following strategy
+ // at least 64 words (32 words random and 32 words dynamic)
+ // no more than 256M for one circuit (128M + 128M)
+ nWords1 = 32;
+ nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk));
+ nWordsMin = ABC_MIN( nWords1, nWords2 );
+
+ // set the FRAIGing parameters
+ Fraig_ParamsSetDefault( pParams );
+ pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info
+ pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info
+ pParams->nBTLimit = nBTLimit; // the max number of backtracks
+ pParams->nSeconds = -1; // the runtime limit
+ pParams->fTryProve = 0; // do not try to prove the final miter
+ pParams->fDoSparse = 1; // try proving sparse functions
+ pParams->fVerbose = 0;
+ pParams->nInspLimit = nInspLimit;
+
+ // transform the target into a fraig
+ pMan = Abc_NtkToFraig( pNtk, pParams, 0, 0 );
+ Fraig_ManProveMiter( pMan );
+ RetValue = Fraig_ManCheckMiter( pMan );
+
+ // create the network
+ pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
+
+ // save model
+ if ( RetValue == 0 )
+ {
+ pModel = Fraig_ManReadModel( pMan );
+ FREE( pNtkNew->pModel );
+ pNtkNew->pModel = ALLOC( int, Abc_NtkCiNum(pNtkNew) );
+ memcpy( pNtkNew->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtkNew) );
+ }
+
+ // save the return values
+ *pRetValue = RetValue;
+ *pNumFails = Fraig_ManReadSatFails( pMan );
+ *pNumConfs = Fraig_ManReadConflicts( pMan );
+ *pNumInspects = Fraig_ManReadInspects( pMan );
+
+ // delete the fraig manager
+ Fraig_ManFree( pMan );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose )
+{
+ if ( !fVerbose )
+ return;
+ printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk),
+ Abc_NtkIsStrash(pNtk)? Abc_AigLevel(pNtk) : Abc_NtkLevel(pNtk) );
+ PRT( pString, clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Implements resynthesis for CEC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterRwsat( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkTemp;
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp );
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ return pNtk;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcQbf.c b/src/base/abci/abcQbf.c
new file mode 100644
index 00000000..b839f812
--- /dev/null
+++ b/src/base/abci/abcQbf.c
@@ -0,0 +1,260 @@
+/**CFile****************************************************************
+
+ FileName [abcQbf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Implementation of a simple QBF solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcQbf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+/*
+ Implementation of a simple QBF solver along the lines of
+ A. Solar-Lezama, L. Tancau, R. Bodik, V. Saraswat, and S. Seshia,
+ "Combinatorial sketching for finite programs", 12th International
+ Conference on Architectural Support for Programming Languages and
+ Operating Systems (ASPLOS 2006), San Jose, CA, October 2006.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues );
+static void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars );
+static void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Solve the QBF problem EpAx[M(p,x)].]
+
+ Description [Variables p go first, followed by variable x.
+ The number of parameters is nPars. The miter is in pNtk.
+ The miter expresses EQUALITY of the implementation and spec.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose )
+{
+ Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp;
+ Vec_Int_t * vPiValues;
+ int clkTotal = clock(), clkS, clkV;
+ int nIters, nIterMax = 500, nInputs, RetValue, fFound = 0;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkIsComb(pNtk) );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+ assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) );
+ assert( Abc_NtkPiNum(pNtk)-nPars < 32 );
+ nInputs = Abc_NtkPiNum(pNtk) - nPars;
+
+ // initialize the synthesized network with 0000-combination
+ vPiValues = Vec_IntStart( Abc_NtkPiNum(pNtk) );
+ Abc_NtkVectorClearPars( vPiValues, nPars );
+ pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues );
+ if ( fVerbose )
+ {
+ printf( "Iter %2d : ", 0 );
+ printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) );
+ Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars );
+ printf( "\n" );
+ }
+
+ // iteratively solve
+ for ( nIters = 0; nIters < nIterMax; nIters++ )
+ {
+ // solve the synthesis instance
+clkS = clock();
+ RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL );
+clkS = clock() - clkS;
+ if ( RetValue == 0 )
+ Abc_NtkModelToVector( pNtkSyn, vPiValues );
+ if ( RetValue == 1 )
+ {
+ break;
+ }
+ if ( RetValue == -1 )
+ {
+ printf( "Synthesis timed out.\n" );
+ break;
+ }
+ // there is a counter-example
+
+ // construct the verification instance
+ Abc_NtkVectorClearVars( pNtk, vPiValues, nPars );
+ pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues );
+ // complement the output
+ Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 );
+
+ // solve the verification instance
+clkV = clock();
+ RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL );
+clkV = clock() - clkV;
+ if ( RetValue == 0 )
+ Abc_NtkModelToVector( pNtkVer, vPiValues );
+ Abc_NtkDelete( pNtkVer );
+ if ( RetValue == 1 )
+ {
+ fFound = 1;
+ break;
+ }
+ if ( RetValue == -1 )
+ {
+ printf( "Verification timed out.\n" );
+ break;
+ }
+ // there is a counter-example
+
+ // create a new synthesis network
+ Abc_NtkVectorClearPars( vPiValues, nPars );
+ pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues );
+ // add to the synthesis instance
+ pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 );
+ Abc_NtkDelete( pNtkSyn2 );
+ Abc_NtkDelete( pNtkTemp );
+
+ if ( fVerbose )
+ {
+ printf( "Iter %2d : ", nIters+1 );
+ printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) );
+ Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars );
+ printf( " " );
+// PRTn( "Syn", clkS );
+ PRT( "Ver", clkV );
+ }
+ }
+ Abc_NtkDelete( pNtkSyn );
+ // report the results
+ if ( fFound )
+ {
+ printf( "Parameters: " );
+ Abc_NtkVectorPrintPars( vPiValues, nPars );
+ printf( "\n" );
+ printf( "Solved after %d interations. ", nIters );
+ }
+ else if ( nIters == nIterMax )
+ printf( "Unsolved after %d interations. ", nIters );
+ else
+ printf( "Implementation does not exist. " );
+ PRT( "Total runtime", clock() - clkTotal );
+ Vec_IntFree( vPiValues );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Translates model into the vector of values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues )
+{
+ int * pModel, i;
+ pModel = pNtk->pModel;
+ for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
+ Vec_IntWriteEntry( vPiValues, i, pModel[i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars )
+{
+ int i;
+ for ( i = 0; i < nPars; i++ )
+ Vec_IntWriteEntry( vPiValues, i, -1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars )
+{
+ int i;
+ for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ )
+ Vec_IntWriteEntry( vPiValues, i, -1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars )
+{
+ int i;
+ for ( i = 0; i < nPars; i++ )
+ printf( "%d", Vec_IntEntry(vPiValues,i) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clears variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars )
+{
+ int i;
+ for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ )
+ printf( "%d", Vec_IntEntry(vPiValues,i) );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcQuant.c b/src/base/abci/abcQuant.c
new file mode 100644
index 00000000..0f2bd72f
--- /dev/null
+++ b/src/base/abci/abcQuant.c
@@ -0,0 +1,419 @@
+/**CFile****************************************************************
+
+ FileName [abcQuant.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [AIG-based variable quantification.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcQuant.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs fast synthesis.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSynthesize( Abc_Ntk_t ** ppNtk, int fMoreEffort )
+{
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+
+ pNtk = *ppNtk;
+
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+
+ if ( fMoreEffort )
+ {
+ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 );
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ }
+
+ *ppNtk = pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Existentially quantifies one variable.]
+
+ Description []
+
+ SideEffects [This procedure creates dangling nodes in the AIG.]
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pNext, * pFanin;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( iVar < Abc_NtkCiNum(pNtk) );
+
+ // collect the internal nodes
+ pObj = Abc_NtkCi( pNtk, iVar );
+ vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 );
+
+ // assign the cofactors of the CI node to be constants
+ pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pNtk) );
+ pObj->pData = Abc_AigConst1(pNtk);
+
+ // quantify the nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+ pFanin->pCopy = pFanin->pData = pFanin;
+ pFanin = Abc_ObjFanin1(pObj);
+ if ( !Abc_NodeIsTravIdCurrent(pFanin) )
+ pFanin->pCopy = pFanin->pData = pFanin;
+ pObj->pCopy = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ pObj->pData = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) );
+ }
+ }
+ Vec_PtrFree( vNodes );
+
+ // update the affected COs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ pFanin = Abc_ObjFanin0(pObj);
+ // get the result of quantification
+ if ( fUniv )
+ pNext = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) );
+ else
+ pNext = Abc_AigOr( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) );
+ pNext = Abc_ObjNotCond( pNext, Abc_ObjFaninC0(pObj) );
+ if ( Abc_ObjRegular(pNext) == pFanin )
+ continue;
+ // update the fanins of the CO
+ Abc_ObjPatchFanin( pObj, pFanin, pNext );
+// if ( Abc_ObjFanoutNum(pFanin) == 0 )
+// Abc_AigDeleteNode( pNtk->pManFunc, pFanin );
+ }
+
+ // make sure the node has no fanouts
+// pObj = Abc_NtkCi( pNtk, iVar );
+// assert( Abc_ObjFanoutNum(pObj) == 0 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs the transition relation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose )
+{
+ char Buffer[1000];
+ Vec_Ptr_t * vPairs;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pMiter;
+ int i, nLatches;
+ int fSynthesis = 1;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkLatchNum(pNtk) );
+ nLatches = Abc_NtkLatchNum(pNtk);
+ // start the network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ // duplicate the name and the spec
+ sprintf( Buffer, "%s_TR", pNtk->pName );
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+// pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+ Abc_NtkCleanCopy( pNtk );
+ // create current state variables
+ Abc_NtkForEachLatchOutput( pNtk, pObj, i )
+ {
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
+ }
+ // create next state variables
+ Abc_NtkForEachLatchInput( pNtk, pObj, i )
+ Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL );
+ // create PI variables
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkDupObj( pNtkNew, pObj, 1 );
+ // create the PO
+ Abc_NtkCreatePo( pNtkNew );
+ // restrash the nodes (assuming a topological order of the old network)
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // create the function of the primary output
+ assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+ vPairs = Vec_PtrAlloc( 2*nLatches );
+ Abc_NtkForEachLatchInput( pNtk, pObj, i )
+ {
+ Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pObj) );
+ Vec_PtrPush( vPairs, Abc_NtkPi(pNtkNew, i+nLatches) );
+ }
+ pMiter = Abc_AigMiter( pNtkNew->pManFunc, vPairs );
+ Vec_PtrFree( vPairs );
+ // add the primary output
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), Abc_ObjNot(pMiter) );
+ Abc_ObjAssignName( Abc_NtkPo(pNtkNew,0), "rel", NULL );
+
+ // quantify inputs
+ if ( fInputs )
+ {
+ assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) + 2*nLatches );
+ for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- )
+// for ( i = 2*nLatches; i < Abc_NtkPiNum(pNtkNew); i++ )
+ {
+ Abc_NtkQuantify( pNtkNew, 0, i, fVerbose );
+// if ( fSynthesis && (i % 3 == 2) )
+ if ( fSynthesis )
+ {
+ Abc_NtkCleanData( pNtkNew );
+ Abc_AigCleanup( pNtkNew->pManFunc );
+ Abc_NtkSynthesize( &pNtkNew, 1 );
+ }
+// printf( "Var = %3d. Nodes = %6d. ", Abc_NtkPiNum(pNtkNew) - 1 - i, Abc_NtkNodeNum(pNtkNew) );
+// printf( "Var = %3d. Nodes = %6d. ", i - 2*nLatches, Abc_NtkNodeNum(pNtkNew) );
+ }
+// printf( "\n" );
+ Abc_NtkCleanData( pNtkNew );
+ Abc_AigCleanup( pNtkNew->pManFunc );
+ for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- )
+ {
+ pObj = Abc_NtkPi( pNtkNew, i );
+ assert( Abc_ObjFanoutNum(pObj) == 0 );
+ Abc_NtkDeleteObj( pObj );
+ }
+ }
+
+ // check consistency of the network
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkTransRel: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs one image computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInitialState( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pMiter;
+ int i, nVars = Abc_NtkPiNum(pNtk)/2;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // compute the all-zero state in terms of the CS variables
+ pMiter = Abc_AigConst1(pNtkNew);
+ for ( i = 0; i < nVars; i++ )
+ pMiter = Abc_AigAnd( pNtkNew->pManFunc, pMiter, Abc_ObjNot( Abc_NtkPi(pNtkNew, i) ) );
+ // add the PO
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Swaps current state and next state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSwapVariables( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pMiter, * pObj, * pObj0, * pObj1;
+ int i, nVars = Abc_NtkPiNum(pNtk)/2;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the new network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // update the PIs
+ for ( i = 0; i < nVars; i++ )
+ {
+ pObj0 = Abc_NtkPi( pNtk, i );
+ pObj1 = Abc_NtkPi( pNtk, i+nVars );
+ pMiter = pObj0->pCopy;
+ pObj0->pCopy = pObj1->pCopy;
+ pObj1->pCopy = pMiter;
+ }
+ // restrash
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // add the PO
+ pMiter = Abc_ObjChild0Copy( Abc_NtkPo(pNtk,0) );
+ Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs reachability analisys.]
+
+ Description [Assumes that the input is the transition relation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtkRel, int nIters, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ Abc_Ntk_t * pNtkFront, * pNtkReached, * pNtkNext, * pNtkTemp;
+ int clk, i, v, nVars, nNodesOld, nNodesNew, nNodesPrev;
+ int fFixedPoint = 0;
+ int fSynthesis = 1;
+ int fMoreEffort = 1;
+
+ assert( Abc_NtkIsStrash(pNtkRel) );
+ assert( Abc_NtkLatchNum(pNtkRel) == 0 );
+ assert( Abc_NtkPiNum(pNtkRel) % 2 == 0 );
+
+ // compute the network composed of the initial states
+ pNtkFront = Abc_NtkInitialState( pNtkRel );
+ pNtkReached = Abc_NtkDup( pNtkFront );
+//Abc_NtkShow( pNtkReached, 0, 0, 0 );
+
+// if ( fVerbose )
+// printf( "Transition relation = %6d.\n", Abc_NtkNodeNum(pNtkRel) );
+
+ // perform iterations of reachability analysis
+ nNodesPrev = Abc_NtkNodeNum(pNtkFront);
+ nVars = Abc_NtkPiNum(pNtkRel)/2;
+ for ( i = 0; i < nIters; i++ )
+ {
+ clk = clock();
+ // get the set of next states
+ pNtkNext = Abc_NtkMiterAnd( pNtkRel, pNtkFront, 0, 0 );
+ Abc_NtkDelete( pNtkFront );
+ // quantify the current state variables
+ for ( v = 0; v < nVars; v++ )
+ {
+ Abc_NtkQuantify( pNtkNext, 0, v, fVerbose );
+ if ( fSynthesis && (v % 3 == 2) )
+ {
+ Abc_NtkCleanData( pNtkNext );
+ Abc_AigCleanup( pNtkNext->pManFunc );
+ Abc_NtkSynthesize( &pNtkNext, fMoreEffort );
+ }
+ }
+ Abc_NtkCleanData( pNtkNext );
+ Abc_AigCleanup( pNtkNext->pManFunc );
+ if ( fSynthesis )
+ Abc_NtkSynthesize( &pNtkNext, 1 );
+ // map the next states into the current states
+ pNtkNext = Abc_NtkSwapVariables( pNtkTemp = pNtkNext );
+ Abc_NtkDelete( pNtkTemp );
+ // check the termination condition
+ if ( Abc_ObjFanin0(Abc_NtkPo(pNtkNext,0)) == Abc_AigConst1(pNtkNext) )
+ {
+ fFixedPoint = 1;
+ printf( "Fixed point is reached!\n" );
+ Abc_NtkDelete( pNtkNext );
+ break;
+ }
+ // compute new front
+ pNtkFront = Abc_NtkMiterAnd( pNtkNext, pNtkReached, 0, 1 );
+ Abc_NtkDelete( pNtkNext );
+ // add the reached states
+ pNtkReached = Abc_NtkMiterAnd( pNtkTemp = pNtkReached, pNtkFront, 1, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ // compress the size of Front
+ nNodesOld = Abc_NtkNodeNum(pNtkFront);
+ if ( fSynthesis )
+ {
+ Abc_NtkSynthesize( &pNtkFront, fMoreEffort );
+ Abc_NtkSynthesize( &pNtkReached, fMoreEffort );
+ }
+ nNodesNew = Abc_NtkNodeNum(pNtkFront);
+ // print statistics
+ if ( fVerbose )
+ {
+ printf( "I = %3d : Reach = %6d Fr = %6d FrM = %6d %7.2f %% ",
+ i + 1, Abc_NtkNodeNum(pNtkReached), nNodesOld, nNodesNew, 100.0*(nNodesNew-nNodesPrev)/nNodesPrev );
+ PRT( "T", clock() - clk );
+ }
+ nNodesPrev = Abc_NtkNodeNum(pNtkFront);
+ }
+ if ( !fFixedPoint )
+ fprintf( stdout, "Reachability analysis stopped after %d iterations.\n", nIters );
+
+ // complement the output to represent the set of unreachable states
+ Abc_ObjXorFaninC( Abc_NtkPo(pNtkReached,0), 0 );
+
+ // remove next state variables
+ for ( i = 2*nVars - 1; i >= nVars; i-- )
+ {
+ pObj = Abc_NtkPi( pNtkReached, i );
+ assert( Abc_ObjFanoutNum(pObj) == 0 );
+ Abc_NtkDeleteObj( pObj );
+ }
+
+ // check consistency of the network
+ if ( !Abc_NtkCheck( pNtkReached ) )
+ {
+ printf( "Abc_NtkReachability: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkReached );
+ return NULL;
+ }
+ return pNtkReached;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRec.c b/src/base/abci/abcRec.c
new file mode 100644
index 00000000..a6ec6981
--- /dev/null
+++ b/src/base/abci/abcRec.c
@@ -0,0 +1,1173 @@
+/**CFile****************************************************************
+
+ FileName [abcRec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Record of semi-canonical AIG subgraphs.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "if.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_ManRec_t_ Abc_ManRec_t;
+struct Abc_ManRec_t_
+{
+ Abc_Ntk_t * pNtk; // the record
+ Vec_Ptr_t * vTtElems; // the elementary truth tables
+ Vec_Ptr_t * vTtNodes; // the node truth tables
+ Abc_Obj_t ** pBins; // hash table mapping truth tables into nodes
+ int nBins; // the number of allocated bins
+ int nVars; // the number of variables
+ int nVarsInit; // the number of variables requested initially
+ int nWords; // the number of TT words
+ int nCuts; // the max number of cuts to use
+ // temporaries
+ int * pBytes; // temporary storage for minterms
+ int * pMints; // temporary storage for minterm counters
+ unsigned * pTemp1; // temporary truth table
+ unsigned * pTemp2; // temporary truth table
+ Vec_Ptr_t * vNodes; // the temporary nodes
+ Vec_Ptr_t * vTtTemps; // the truth tables for the internal nodes of the cut
+ Vec_Ptr_t * vLabels; // temporary storage for AIG node labels
+ Vec_Str_t * vCosts; // temporary storage for costs
+ Vec_Int_t * vMemory; // temporary memory for truth tables
+ // statistics
+ int nTried; // the number of cuts tried
+ int nFilterSize; // the number of same structures
+ int nFilterRedund; // the number of same structures
+ int nFilterVolume; // the number of same structures
+ int nFilterTruth; // the number of same structures
+ int nFilterError; // the number of same structures
+ int nFilterSame; // the number of same structures
+ int nAdded; // the number of subgraphs added
+ int nAddedFuncs; // the number of functions added
+ // rewriting
+ int nFunsFound; // the found functions
+ int nFunsNotFound; // the missing functions
+ // runtime
+ int timeCollect; // the runtime to canonicize
+ int timeTruth; // the runtime to canonicize
+ int timeCanon; // the runtime to canonicize
+ int timeOther; // the runtime to canonicize
+ int timeTotal; // the runtime to canonicize
+};
+
+// the truth table is canonicized in such a way that for (00000) its value is 0
+
+static Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars );
+static int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars );
+static int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj );
+
+static Abc_ManRec_t * s_pMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the record for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecIsRunning()
+{
+ return s_pMan != NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the record for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecVarNum()
+{
+ return (s_pMan != NULL)? s_pMan->nVars : -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the record for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRecMemory()
+{
+ return s_pMan->vMemory;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the record for the given network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts )
+{
+ Abc_ManRec_t * p;
+ Abc_Obj_t * pObj, ** ppSpot;
+ char Buffer[10];
+ unsigned * pTruth;
+ int i, RetValue;
+ int clkTotal = clock(), clk;
+
+ assert( s_pMan == NULL );
+ if ( pNtk == NULL )
+ {
+ assert( nVars > 2 && nVars <= 16 );
+ pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pNtk->pName = Extra_UtilStrsav( "record" );
+ }
+ else
+ {
+ if ( Abc_NtkGetChoiceNum(pNtk) > 0 )
+ {
+ printf( "The starting record should be a network without choice nodes.\n" );
+ return;
+ }
+ if ( Abc_NtkPiNum(pNtk) > 16 )
+ {
+ printf( "The starting record should be a network with no more than %d primary inputs.\n", 16 );
+ return;
+ }
+ if ( Abc_NtkPiNum(pNtk) > nVars )
+ printf( "The starting record has %d inputs (warning only).\n", Abc_NtkPiNum(pNtk) );
+ pNtk = Abc_NtkDup( pNtk );
+ }
+ // create the primary inputs
+ for ( i = Abc_NtkPiNum(pNtk); i < nVars; i++ )
+ {
+ pObj = Abc_NtkCreatePi( pNtk );
+ Buffer[0] = 'a' + i;
+ Buffer[1] = 0;
+ Abc_ObjAssignName( pObj, Buffer, NULL );
+ }
+ Abc_NtkCleanCopy( pNtk );
+ Abc_NtkCleanEquiv( pNtk );
+
+ // start the manager
+ p = ALLOC( Abc_ManRec_t, 1 );
+ memset( p, 0, sizeof(Abc_ManRec_t) );
+ p->pNtk = pNtk;
+ p->nVars = Abc_NtkPiNum(pNtk);
+ p->nWords = Kit_TruthWordNum( p->nVars );
+ p->nCuts = nCuts;
+ p->nVarsInit = nVars;
+
+ // create elementary truth tables
+ p->vTtElems = Vec_PtrAlloc( 0 ); assert( p->vTtElems->pArray == NULL );
+ p->vTtElems->nSize = p->nVars;
+ p->vTtElems->nCap = p->nVars;
+ p->vTtElems->pArray = (void *)Extra_TruthElementary( p->nVars );
+
+ // allocate room for node truth tables
+ if ( Abc_NtkObjNum(pNtk) > (1<<14) )
+ p->vTtNodes = Vec_PtrAllocSimInfo( 2 * Abc_NtkObjNum(pNtk), p->nWords );
+ else
+ p->vTtNodes = Vec_PtrAllocSimInfo( 1<<14, p->nWords );
+
+ // create hash table
+ p->nBins = 50011;
+ p->pBins = ALLOC( Abc_Obj_t *, p->nBins );
+ memset( p->pBins, 0, sizeof(Abc_Obj_t *) * p->nBins );
+
+ // set elementary tables
+ Kit_TruthFill( Vec_PtrEntry(p->vTtNodes, 0), p->nVars );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, pObj->Id), Vec_PtrEntry(p->vTtElems, i), p->nVars );
+
+ // compute the tables
+clk = clock();
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ RetValue = Abc_NtkRecComputeTruth( pObj, p->vTtNodes, p->nVars );
+ assert( RetValue );
+ }
+p->timeTruth += clock() - clk;
+
+ // insert the PO nodes into the table
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ p->nTried++;
+ p->nAdded++;
+
+ pObj = Abc_ObjFanin0(pObj);
+ pTruth = Vec_PtrEntry( p->vTtNodes, pObj->Id );
+
+ if ( pTruth[0] == 1128481603 )
+ {
+ int x = 0;
+ }
+
+ // add the resulting truth table to the hash table
+ ppSpot = Abc_NtkRecTableLookup( p, pTruth, p->nVars );
+ assert( pObj->pEquiv == NULL );
+ assert( pObj->pCopy == NULL );
+ if ( *ppSpot == NULL )
+ {
+ p->nAddedFuncs++;
+ *ppSpot = pObj;
+ }
+ else
+ {
+ pObj->pEquiv = (*ppSpot)->pEquiv;
+ (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj;
+ if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) )
+ printf( "Loop!\n" );
+ }
+ }
+
+ // temporaries
+ p->pBytes = ALLOC( int, 4*p->nWords );
+ p->pMints = ALLOC( int, 2*p->nVars );
+ p->pTemp1 = ALLOC( unsigned, p->nWords );
+ p->pTemp2 = ALLOC( unsigned, p->nWords );
+ p->vNodes = Vec_PtrAlloc( 100 );
+ p->vTtTemps = Vec_PtrAllocSimInfo( 64, p->nWords );
+ p->vMemory = Vec_IntAlloc( Abc_TruthWordNum(p->nVars) * 1000 );
+
+ // set the manager
+ s_pMan = p;
+p->timeTotal += clock() - clkTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the given record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecStop()
+{
+ assert( s_pMan != NULL );
+ if ( s_pMan->pNtk )
+ Abc_NtkDelete( s_pMan->pNtk );
+ Vec_PtrFree( s_pMan->vTtNodes );
+ Vec_PtrFree( s_pMan->vTtElems );
+ free( s_pMan->pBins );
+
+ // temporaries
+ free( s_pMan->pBytes );
+ free( s_pMan->pMints );
+ free( s_pMan->pTemp1 );
+ free( s_pMan->pTemp2 );
+ Vec_PtrFree( s_pMan->vNodes );
+ Vec_PtrFree( s_pMan->vTtTemps );
+ if ( s_pMan->vLabels )
+ Vec_PtrFree( s_pMan->vLabels );
+ if ( s_pMan->vCosts )
+ Vec_StrFree( s_pMan->vCosts );
+ Vec_IntFree( s_pMan->vMemory );
+
+ free( s_pMan );
+ s_pMan = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the given record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRecUse()
+{
+ Abc_ManRec_t * p = s_pMan;
+ Abc_Ntk_t * pNtk = p->pNtk;
+ assert( p != NULL );
+ Abc_NtkRecPs();
+ p->pNtk = NULL;
+ Abc_NtkRecStop();
+ return pNtk;
+}
+
+static inline void Abc_ObjSetMax( Abc_Obj_t * pObj, int Value ) { assert( pObj->Level < 0xff ); pObj->Level = (Value << 8) | (pObj->Level & 0xff); }
+static inline void Abc_ObjClearMax( Abc_Obj_t * pObj ) { pObj->Level = (pObj->Level & 0xff); }
+static inline int Abc_ObjGetMax( Abc_Obj_t * pObj ) { return (pObj->Level >> 8) & 0xff; }
+
+/**Function*************************************************************
+
+ Synopsis [Print statistics about the current record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecPs()
+{
+ int Counter, Counters[17] = {0};
+ int CounterS, CountersS[17] = {0};
+ Abc_ManRec_t * p = s_pMan;
+ Abc_Ntk_t * pNtk = p->pNtk;
+ Abc_Obj_t * pObj, * pEntry, * pTemp;
+ int i;
+
+ // set the max PI number
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetMax( pObj, i+1 );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_ObjSetMax( pObj, ABC_MAX( Abc_ObjGetMax(Abc_ObjFanin0(pObj)), Abc_ObjGetMax(Abc_ObjFanin1(pObj)) ) );
+ // go through the table
+ Counter = CounterS = 0;
+ for ( i = 0; i < p->nBins; i++ )
+ for ( pEntry = p->pBins[i]; pEntry; pEntry = pEntry->pCopy )
+ {
+ Counters[ Abc_ObjGetMax(pEntry) ]++;
+ Counter++;
+ for ( pTemp = pEntry; pTemp; pTemp = (Abc_Obj_t *)pTemp->pEquiv )
+ {
+ assert( Abc_ObjGetMax(pTemp) == Abc_ObjGetMax(pEntry) );
+ CountersS[ Abc_ObjGetMax(pTemp) ]++;
+ CounterS++;
+ }
+ }
+// printf( "Functions = %d. Expected = %d.\n", Counter, p->nAddedFuncs );
+// printf( "Subgraphs = %d. Expected = %d.\n", CounterS, p->nAdded );
+ assert( Counter == p->nAddedFuncs );
+ assert( CounterS == p->nAdded );
+
+ // clean
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ Abc_ObjClearMax( pObj );
+ }
+
+ printf( "The record with %d AND nodes in %d subgraphs for %d functions with %d inputs:\n",
+ Abc_NtkNodeNum(pNtk), Abc_NtkPoNum(pNtk), p->nAddedFuncs, Abc_NtkPiNum(pNtk) );
+ for ( i = 0; i <= 16; i++ )
+ {
+ if ( Counters[i] )
+ printf( "Inputs = %2d. Funcs = %8d. Subgrs = %8d. Ratio = %6.2f.\n", i, Counters[i], CountersS[i], 1.0*CountersS[i]/Counters[i] );
+ }
+
+ printf( "Subgraphs tried = %8d. (%6.2f %%)\n", p->nTried, !p->nTried? 0 : 100.0*p->nTried/p->nTried );
+ printf( "Subgraphs filtered by support size = %8d. (%6.2f %%)\n", p->nFilterSize, !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried );
+ printf( "Subgraphs filtered by structural redundancy = %8d. (%6.2f %%)\n", p->nFilterRedund, !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried );
+ printf( "Subgraphs filtered by volume = %8d. (%6.2f %%)\n", p->nFilterVolume, !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried );
+ printf( "Subgraphs filtered by TT redundancy = %8d. (%6.2f %%)\n", p->nFilterTruth, !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried );
+ printf( "Subgraphs filtered by error = %8d. (%6.2f %%)\n", p->nFilterError, !p->nTried? 0 : 100.0*p->nFilterError/p->nTried );
+ printf( "Subgraphs filtered by isomorphism = %8d. (%6.2f %%)\n", p->nFilterSame, !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried );
+ printf( "Subgraphs added = %8d. (%6.2f %%)\n", p->nAdded, !p->nTried? 0 : 100.0*p->nAdded/p->nTried );
+ printf( "Functions added = %8d. (%6.2f %%)\n", p->nAddedFuncs, !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried );
+
+ p->timeOther = p->timeTotal - p->timeCollect - p->timeTruth - p->timeCanon;
+ PRTP( "Collecting nodes ", p->timeCollect, p->timeTotal );
+ PRTP( "Computing truth ", p->timeTruth, p->timeTotal );
+ PRTP( "Canonicizing ", p->timeCanon, p->timeTotal );
+ PRTP( "Other ", p->timeOther, p->timeTotal );
+ PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ if ( p->nFunsFound )
+ printf( "During rewriting found = %d and not found = %d functions.\n", p->nFunsFound, p->nFunsNotFound );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filters the current record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecFilter( int iVar, int iPlus )
+{
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the hash key.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Abc_NtkRecTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes )
+{
+ int i, nWords = Kit_TruthWordNum( nVars );
+ unsigned uHash = 0;
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= pTruth[i] * pPrimes[i & 0x7];
+ return uHash % nBins;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the given record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars )
+{
+ static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
+ Abc_Obj_t ** ppSpot, * pEntry;
+ ppSpot = p->pBins + Abc_NtkRecTableHash( pTruth, nVars, p->nBins, s_Primes );
+ for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pCopy, pEntry = pEntry->pCopy )
+ if ( Kit_TruthIsEqualWithPhase(Vec_PtrEntry(p->vTtNodes, pEntry->Id), pTruth, nVars) )
+ return ppSpot;
+ return ppSpot;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars )
+{
+ unsigned * pTruth, * pTruth0, * pTruth1;
+ int RetValue;
+ assert( Abc_ObjIsNode(pObj) );
+ pTruth = Vec_PtrEntry( vTtNodes, pObj->Id );
+ pTruth0 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId0(pObj) );
+ pTruth1 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId1(pObj) );
+ Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ assert( (pTruth[0] & 1) == pObj->fPhase );
+ RetValue = ((pTruth[0] & 1) == pObj->fPhase);
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs renoding as technology mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecAdd( Abc_Ntk_t * pNtk )
+{
+ extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+ extern int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut );
+
+ If_Par_t Pars, * pPars = &Pars;
+ Abc_Ntk_t * pNtkNew;
+ int clk = clock();
+
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Performing renoding with choices.\n" );
+
+ // set defaults
+ memset( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+ pPars->nLutSize = s_pMan->nVarsInit;
+ pPars->nCutsMax = s_pMan->nCuts;
+ pPars->nFlowIters = 0;
+ pPars->nAreaIters = 0;
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 0;
+ pPars->fArea = 1;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 0;
+ pPars->fLatchPaths = 0;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = 0;
+ // internal parameters
+ pPars->fTruth = 0;
+ pPars->fUsePerm = 0;
+ pPars->nLatches = 0;
+ pPars->pLutLib = NULL; // Abc_FrameReadLibLut();
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->fUseBdds = 0;
+ pPars->fUseSops = 0;
+ pPars->fUseCnfs = 0;
+ pPars->fUseMv = 0;
+ pPars->pFuncCost = NULL;
+ pPars->pFuncUser = Abc_NtkRecAddCut;
+
+ // perform recording
+ pNtkNew = Abc_NtkIf( pNtk, pPars );
+ Abc_NtkDelete( pNtkNew );
+s_pMan->timeTotal += clock() - clk;
+
+// if ( !Abc_NtkCheck( s_pMan->pNtk ) )
+// printf( "Abc_NtkRecAdd: The network check has failed.\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut function to the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRecCollectNodes_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes )
+{
+ if ( pNode->fMark )
+ return;
+ pNode->fMark = 1;
+ assert( If_ObjIsAnd(pNode) );
+ Abc_NtkRecCollectNodes_rec( If_ObjFanin0(pNode), vNodes );
+ Abc_NtkRecCollectNodes_rec( If_ObjFanin1(pNode), vNodes );
+ Vec_PtrPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut function to the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecCollectNodes( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes )
+{
+ If_Obj_t * pLeaf;
+ int i, RetValue = 1;
+
+ // collect the internal nodes of the cut
+ Vec_PtrClear( vNodes );
+ If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+ {
+ Vec_PtrPush( vNodes, pLeaf );
+ assert( pLeaf->fMark == 0 );
+ pLeaf->fMark = 1;
+ }
+
+ // collect other nodes
+ Abc_NtkRecCollectNodes_rec( pRoot, vNodes );
+
+ // check if there are leaves, such that both of their fanins are marked
+ // this indicates a redundant cut
+ If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
+ {
+ if ( !If_ObjIsAnd(pLeaf) )
+ continue;
+ if ( If_ObjFanin0(pLeaf)->fMark && If_ObjFanin1(pLeaf)->fMark )
+ {
+ RetValue = 0;
+ break;
+ }
+ }
+
+ // clean the mark
+ Vec_PtrForEachEntry( vNodes, pLeaf, i )
+ pLeaf->fMark = 0;
+/*
+ if ( pRoot->Id == 2639 )
+ {
+ // print the cut
+ Vec_PtrForEachEntry( vNodes, pLeaf, i )
+ {
+ if ( If_ObjIsAnd(pLeaf) )
+ printf( "%4d = %c%4d & %c%4d\n", pLeaf->Id,
+ (If_ObjFaninC0(pLeaf)? '-':'+'), If_ObjFanin0(pLeaf)->Id,
+ (If_ObjFaninC1(pLeaf)? '-':'+'), If_ObjFanin1(pLeaf)->Id );
+ else
+ printf( "%4d = pi\n", pLeaf->Id );
+ }
+ printf( "\n" );
+ }
+*/
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes truth tables of nodes in the cut.]
+
+ Description [Returns 0 if the TT does not depend on some cut variables.
+ Or if the TT can be expressed simpler using other nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecCutTruth( Vec_Ptr_t * vNodes, int nLeaves, Vec_Ptr_t * vTtTemps, Vec_Ptr_t * vTtElems )
+{
+ unsigned * pSims, * pSims0, * pSims1;
+ unsigned * pTemp = s_pMan->pTemp2;
+ unsigned uWord;
+ If_Obj_t * pObj, * pObj2, * pRoot;
+ int i, k, nLimit, nInputs = s_pMan->nVars;
+
+ assert( Vec_PtrSize(vNodes) > nLeaves );
+
+ // set the elementary truth tables and compute the truth tables of the nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ pObj->pCopy = Vec_PtrEntry(vTtTemps, i);
+ pSims = (unsigned *)pObj->pCopy;
+ if ( i < nLeaves )
+ {
+ Kit_TruthCopy( pSims, Vec_PtrEntry(vTtElems, i), nInputs );
+ continue;
+ }
+ assert( If_ObjIsAnd(pObj) );
+ // get hold of the simulation information
+ pSims0 = (unsigned *)If_ObjFanin0(pObj)->pCopy;
+ pSims1 = (unsigned *)If_ObjFanin1(pObj)->pCopy;
+ // simulate the node
+ Kit_TruthAndPhase( pSims, pSims0, pSims1, nInputs, If_ObjFaninC0(pObj), If_ObjFaninC1(pObj) );
+ }
+
+ // check the support size
+ pRoot = Vec_PtrEntryLast( vNodes );
+ pSims = (unsigned *)pRoot->pCopy;
+ if ( Kit_TruthSupport(pSims, nInputs) != Kit_BitMask(nLeaves) )
+ return 0;
+
+ // make sure none of the nodes has the same simulation info as the output
+ // check pairwise comparisons
+ nLimit = Vec_PtrSize(vNodes) - 1;
+ Vec_PtrForEachEntryStop( vNodes, pObj, i, nLimit )
+ {
+ pSims0 = (unsigned *)pObj->pCopy;
+ if ( Kit_TruthIsEqualWithPhase(pSims, pSims0, nInputs) )
+ return 0;
+ Vec_PtrForEachEntryStop( vNodes, pObj2, k, i )
+ {
+ if ( (If_ObjFanin0(pRoot) == pObj && If_ObjFanin1(pRoot) == pObj2) ||
+ (If_ObjFanin1(pRoot) == pObj && If_ObjFanin0(pRoot) == pObj2) )
+ continue;
+ pSims1 = (unsigned *)pObj2->pCopy;
+
+ uWord = pSims0[0] & pSims1[0];
+ if ( pSims[0] == uWord || pSims[0] == ~uWord )
+ {
+ Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 0 );
+ if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) )
+ return 0;
+ }
+
+ uWord = pSims0[0] & ~pSims1[0];
+ if ( pSims[0] == uWord || pSims[0] == ~uWord )
+ {
+ Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 1 );
+ if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) )
+ return 0;
+ }
+
+ uWord = ~pSims0[0] & pSims1[0];
+ if ( pSims[0] == uWord || pSims[0] == ~uWord )
+ {
+ Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 0 );
+ if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) )
+ return 0;
+ }
+
+ uWord = ~pSims0[0] & ~pSims1[0];
+ if ( pSims[0] == uWord || pSims[0] == ~uWord )
+ {
+ Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 1 );
+ if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) )
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut function to the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj )
+{
+ assert( pRoot->Level > 0 );
+ if ( pObj->Level < pRoot->Level )
+ return 1;
+ if ( pObj == pRoot )
+ return 0;
+ if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin0(pObj)) )
+ return 0;
+ if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin1(pObj)) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the cut function to the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut )
+{
+ static int s_MaxSize[16] = { 0 };
+ char Buffer[40], Name[20], Truth[20];
+ char pCanonPerm[16];
+ Abc_Obj_t * pObj, * pFanin0, * pFanin1, ** ppSpot, * pObjPo;
+ Abc_Ntk_t * pAig = s_pMan->pNtk;
+ If_Obj_t * pIfObj;
+ Vec_Ptr_t * vNodes = s_pMan->vNodes;
+ unsigned * pInOut = s_pMan->pTemp1;
+ unsigned * pTemp = s_pMan->pTemp2;
+ unsigned * pTruth;
+ int i, RetValue, nNodes, nNodesBeg, nInputs = s_pMan->nVars, nLeaves = If_CutLeaveNum(pCut);
+ unsigned uCanonPhase;
+ int clk;
+
+ if ( pRoot->Id == 2639 )
+ {
+ int y = 0;
+ }
+
+ assert( nInputs <= 16 );
+ assert( nInputs == (int)pCut->nLimit );
+ s_pMan->nTried++;
+
+ // skip small cuts
+ if ( nLeaves < 3 )
+ {
+ s_pMan->nFilterSize++;
+ return 1;
+ }
+
+ // collect internal nodes and skip redundant cuts
+clk = clock();
+ RetValue = Abc_NtkRecCollectNodes( pIfMan, pRoot, pCut, vNodes );
+s_pMan->timeCollect += clock() - clk;
+ if ( !RetValue )
+ {
+ s_pMan->nFilterRedund++;
+ return 1;
+ }
+
+ // skip cuts with very large volume
+ if ( Vec_PtrSize(vNodes) > nLeaves + 3*(nLeaves-1) + s_MaxSize[nLeaves] )
+ {
+ s_pMan->nFilterVolume++;
+ return 1;
+ }
+
+ // compute truth table and skip the redundant structures
+clk = clock();
+ RetValue = Abc_NtkRecCutTruth( vNodes, nLeaves, s_pMan->vTtTemps, s_pMan->vTtElems );
+s_pMan->timeTruth += clock() - clk;
+ if ( !RetValue )
+ {
+ s_pMan->nFilterTruth++;
+ return 1;
+ }
+
+ // copy the truth table
+ Kit_TruthCopy( pInOut, (unsigned *)pRoot->pCopy, nInputs );
+
+ // set permutation
+ for ( i = 0; i < nInputs; i++ )
+ pCanonPerm[i] = i;
+
+ // semi-canonicize the truth table
+clk = clock();
+ uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nInputs, pCanonPerm, (short *)s_pMan->pMints );
+s_pMan->timeCanon += clock() - clk;
+ // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth
+
+ // go through the variables in the new truth table
+ for ( i = 0; i < nLeaves; i++ )
+ {
+ // get hold of the corresponding leaf
+ pIfObj = If_ManObj( pIfMan, pCut->pLeaves[pCanonPerm[i]] );
+ // get hold of the corresponding new node
+ pObj = Abc_NtkPi( pAig, i );
+ pObj = Abc_ObjNotCond( pObj, (uCanonPhase & (1 << i)) );
+ // map them
+ pIfObj->pCopy = pObj;
+/*
+ if ( pRoot->Id == 2639 )
+ {
+ unsigned uSupp;
+ printf( "Node %6d : ", pIfObj->Id );
+ printf( "Support " );
+ uSupp = Kit_TruthSupport(Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), nInputs);
+ Extra_PrintBinary( stdout, &uSupp, nInputs );
+ printf( " " );
+ Extra_PrintBinary( stdout, Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), 1<<6 );
+ printf( "\n" );
+ }
+*/
+ }
+
+ // build the node and compute its truth table
+ nNodesBeg = Abc_NtkObjNumMax( pAig );
+ Vec_PtrForEachEntryStart( vNodes, pIfObj, i, nLeaves )
+ {
+ pFanin0 = Abc_ObjNotCond( If_ObjFanin0(pIfObj)->pCopy, If_ObjFaninC0(pIfObj) );
+ pFanin1 = Abc_ObjNotCond( If_ObjFanin1(pIfObj)->pCopy, If_ObjFaninC1(pIfObj) );
+
+ nNodes = Abc_NtkObjNumMax( pAig );
+ pObj = Abc_AigAnd( pAig->pManFunc, pFanin0, pFanin1 );
+ assert( !Abc_ObjIsComplement(pObj) );
+ pIfObj->pCopy = pObj;
+
+ if ( pObj->Id == nNodes )
+ {
+ // increase storage for truth tables
+ if ( Vec_PtrSize(s_pMan->vTtNodes) <= pObj->Id )
+ Vec_PtrDoubleSimInfo(s_pMan->vTtNodes);
+ // compute the truth table
+ RetValue = Abc_NtkRecComputeTruth( pObj, s_pMan->vTtNodes, nInputs );
+ if ( RetValue == 0 )
+ {
+ s_pMan->nFilterError++;
+ printf( "T" );
+ return 1;
+ }
+ }
+ }
+
+ pTruth = Vec_PtrEntry( s_pMan->vTtNodes, pObj->Id );
+ if ( Kit_TruthSupport(pTruth, nInputs) != Kit_BitMask(nLeaves) )
+ {
+ s_pMan->nFilterError++;
+ printf( "S" );
+ return 1;
+ }
+
+ // compare the truth tables
+ if ( !Kit_TruthIsEqualWithPhase( pTruth, pInOut, nInputs ) )
+ {
+ s_pMan->nFilterError++;
+ printf( "F" );
+ return 1;
+ }
+// Extra_PrintBinary( stdout, pInOut, 8 ); printf( "\n" );
+
+ // if not new nodes were added and the node has a CO fanout
+ if ( nNodesBeg == Abc_NtkObjNumMax(pAig) && Abc_NodeFindCoFanout(pObj) != NULL )
+ {
+ s_pMan->nFilterSame++;
+ return 1;
+ }
+ s_pMan->nAdded++;
+
+ // create PO for this node
+ pObjPo = Abc_NtkCreatePo(pAig);
+ Abc_ObjAddFanin( pObjPo, pObj );
+
+ // assign the name to this PO
+ sprintf( Name, "%d_%06d", nLeaves, Abc_NtkPoNum(pAig) );
+ if ( (nInputs <= 6) && 0 )
+ {
+ Extra_PrintHexadecimalString( Truth, pInOut, nInputs );
+ sprintf( Buffer, "%s_%s", Name, Truth );
+ }
+ else
+ {
+ sprintf( Buffer, "%s", Name );
+ }
+ Abc_ObjAssignName( pObjPo, Buffer, NULL );
+
+ // add the resulting truth table to the hash table
+ ppSpot = Abc_NtkRecTableLookup( s_pMan, pTruth, nInputs );
+ assert( pObj->pEquiv == NULL );
+ assert( pObj->pCopy == NULL );
+ if ( *ppSpot == NULL )
+ {
+ s_pMan->nAddedFuncs++;
+ *ppSpot = pObj;
+ }
+ else
+ {
+ pObj->pEquiv = (*ppSpot)->pEquiv;
+ (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj;
+ if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) )
+ printf( "Loop!\n" );
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Labels the record AIG with the corresponding new AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkRecStrashNodeLabel_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fBuild, Vec_Ptr_t * vLabels )
+{
+ Abc_Obj_t * pFanin0New, * pFanin1New, * pLabel;
+ assert( !Abc_ObjIsComplement(pObj) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pObj ) )
+ return Vec_PtrEntry( vLabels, pObj->Id );
+ assert( Abc_ObjIsNode(pObj) );
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pObj );
+ // label the fanins
+ pFanin0New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin0(pObj), fBuild, vLabels );
+ pFanin1New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin1(pObj), fBuild, vLabels );
+ // label the node if possible
+ pLabel = NULL;
+ if ( pFanin0New && pFanin1New )
+ {
+ pFanin0New = Abc_ObjNotCond( pFanin0New, Abc_ObjFaninC0(pObj) );
+ pFanin1New = Abc_ObjNotCond( pFanin1New, Abc_ObjFaninC1(pObj) );
+ if ( fBuild )
+ pLabel = Abc_AigAnd( pNtkNew->pManFunc, pFanin0New, pFanin1New );
+ else
+ pLabel = Abc_AigAndLookup( pNtkNew->pManFunc, pFanin0New, pFanin1New );
+ }
+ Vec_PtrWriteEntry( vLabels, pObj->Id, pLabel );
+ return pLabel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the area of the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecStrashNodeCount_rec( Abc_Obj_t * pObj, Vec_Str_t * vCosts, Vec_Ptr_t * vLabels )
+{
+ int Cost0, Cost1;
+ if ( Vec_PtrEntry( vLabels, pObj->Id ) )
+ return 0;
+ assert( Abc_ObjIsNode(pObj) );
+ // if this node is already visited, skip
+ if ( Abc_NodeIsTravIdCurrent( pObj ) )
+ return Vec_StrEntry( vCosts, pObj->Id );
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pObj );
+ // count for the fanins
+ Cost0 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin0(pObj), vCosts, vLabels );
+ Cost1 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin1(pObj), vCosts, vLabels );
+ Vec_StrWriteEntry( vCosts, pObj->Id, (char)(Cost0 + Cost1 + 1) );
+ return Cost0 + Cost1 + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes the given node using its local function.]
+
+ Description [Assumes that the fanins are already strashed.
+ Returns 0 if the function is not found in the table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars )
+{
+ char pCanonPerm[16];
+ Abc_Ntk_t * pAig = s_pMan->pNtk;
+ unsigned * pInOut = s_pMan->pTemp1;
+ unsigned * pTemp = s_pMan->pTemp2;
+ unsigned * pTruthRec;
+ Abc_Obj_t * pCand, * pCandMin, * pLeaf, * pFanin, ** ppSpot;
+ unsigned uCanonPhase;
+ int i, nLeaves, CostMin, Cost, nOnes, fCompl;
+
+ // check if the record works
+ nLeaves = Abc_ObjFaninNum(pObj);
+ assert( nLeaves >= 3 && nLeaves <= s_pMan->nVars );
+ pFanin = Abc_ObjFanin0(pObj);
+ assert( Abc_ObjRegular(pFanin->pCopy)->pNtk == pNtkNew );
+ assert( s_pMan != NULL );
+ assert( nVars == s_pMan->nVars );
+
+ // copy the truth table
+ Kit_TruthCopy( pInOut, pTruth, nVars );
+
+ // set permutation
+ for ( i = 0; i < nVars; i++ )
+ pCanonPerm[i] = i;
+
+ // canonicize the truth table
+ uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nVars, pCanonPerm, (short *)s_pMan->pMints );
+
+ // get hold of the curresponding class
+ ppSpot = Abc_NtkRecTableLookup( s_pMan, pInOut, nVars );
+ if ( *ppSpot == NULL )
+ {
+ s_pMan->nFunsNotFound++;
+// printf( "The class of a function with %d inputs is not found.\n", nLeaves );
+ return 0;
+ }
+ s_pMan->nFunsFound++;
+
+ // make sure the truth table is the same
+ pTruthRec = Vec_PtrEntry( s_pMan->vTtNodes, (*ppSpot)->Id );
+ if ( !Kit_TruthIsEqualWithPhase( pTruthRec, pInOut, nVars ) )
+ {
+ assert( 0 );
+ return 0;
+ }
+
+
+ // allocate storage for costs
+ if ( s_pMan->vLabels && Vec_PtrSize(s_pMan->vLabels) < Abc_NtkObjNumMax(pAig) )
+ {
+ Vec_PtrFree( s_pMan->vLabels );
+ s_pMan->vLabels = NULL;
+ }
+ if ( s_pMan->vLabels == NULL )
+ s_pMan->vLabels = Vec_PtrStart( Abc_NtkObjNumMax(pAig) );
+
+ // go through the variables in the new truth table
+ Abc_NtkIncrementTravId( pAig );
+ for ( i = 0; i < nLeaves; i++ )
+ {
+ // get hold of the corresponding fanin
+ pFanin = Abc_ObjFanin( pObj, pCanonPerm[i] )->pCopy;
+ pFanin = Abc_ObjNotCond( pFanin, (uCanonPhase & (1 << i)) );
+ // label the PI of the AIG subgraphs with this fanin
+ pLeaf = Abc_NtkPi( pAig, i );
+ Vec_PtrWriteEntry( s_pMan->vLabels, pLeaf->Id, pFanin );
+ Abc_NodeSetTravIdCurrent( pLeaf );
+ }
+
+ // go through the candidates - and recursively label them
+ for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv )
+ Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCand, 0, s_pMan->vLabels );
+
+
+ // allocate storage for costs
+ if ( s_pMan->vCosts && Vec_StrSize(s_pMan->vCosts) < Abc_NtkObjNumMax(pAig) )
+ {
+ Vec_StrFree( s_pMan->vCosts );
+ s_pMan->vCosts = NULL;
+ }
+ if ( s_pMan->vCosts == NULL )
+ s_pMan->vCosts = Vec_StrStart( Abc_NtkObjNumMax(pAig) );
+
+ // find the best subgraph
+ CostMin = ABC_INFINITY;
+ pCandMin = NULL;
+ for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv )
+ {
+ // label the leaves
+ Abc_NtkIncrementTravId( pAig );
+ // count the number of non-labeled nodes
+ Cost = Abc_NtkRecStrashNodeCount_rec( pCand, s_pMan->vCosts, s_pMan->vLabels );
+ if ( CostMin > Cost )
+ {
+// printf( "%d ", Cost );
+ CostMin = Cost;
+ pCandMin = pCand;
+ }
+ }
+// printf( "\n" );
+ assert( pCandMin != NULL );
+ if ( pCandMin == NULL )
+ return 0;
+
+
+ // label the leaves
+ Abc_NtkIncrementTravId( pAig );
+ for ( i = 0; i < nLeaves; i++ )
+ Abc_NodeSetTravIdCurrent( Abc_NtkPi(pAig, i) );
+
+ // implement the subgraph
+ pObj->pCopy = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCandMin, 1, s_pMan->vLabels );
+ assert( Abc_ObjRegular(pObj->pCopy)->pNtk == pNtkNew );
+
+ // determine phase difference
+ nOnes = Kit_TruthCountOnes(pTruth, nVars);
+ fCompl = (nOnes > (1<< nVars)/2);
+// assert( fCompl == ((uCanonPhase & (1 << nVars)) > 0) );
+
+ nOnes = Kit_TruthCountOnes(pTruthRec, nVars);
+ fCompl ^= (nOnes > (1<< nVars)/2);
+ // complement
+ pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, fCompl );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcReconv.c b/src/base/abci/abcReconv.c
new file mode 100644
index 00000000..e77f055a
--- /dev/null
+++ b/src/base/abci/abcReconv.c
@@ -0,0 +1,762 @@
+/**CFile****************************************************************
+
+ FileName [abcReconv.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Computation of reconvergence-driven cuts.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcReconv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Abc_ManCut_t_
+{
+ // user specified parameters
+ int nNodeSizeMax; // the limit on the size of the supernode
+ int nConeSizeMax; // the limit on the size of the containing cone
+ int nNodeFanStop; // the limit on the size of the supernode
+ int nConeFanStop; // the limit on the size of the containing cone
+ // internal parameters
+ Vec_Ptr_t * vNodeLeaves; // fanins of the collapsed node (the cut)
+ Vec_Ptr_t * vConeLeaves; // fanins of the containing cone
+ Vec_Ptr_t * vVisited; // the visited nodes
+ Vec_Vec_t * vLevels; // the data structure to compute TFO nodes
+ Vec_Ptr_t * vNodesTfo; // the nodes in the TFO of the cut
+};
+
+static int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit );
+static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit );
+static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Unmarks the TFI cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_NodesMark( Vec_Ptr_t * vVisited )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Vec_PtrForEachEntry( vVisited, pNode, i )
+ pNode->fMarkA = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Unmarks the TFI cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Vec_PtrForEachEntry( vVisited, pNode, i )
+ pNode->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Unmarks the TFI cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Vec_PtrForEachEntry( vVisited, pNode, i )
+ pNode->fMarkB = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluate the cost of removing the node from the set of leaves.]
+
+ Description [Returns the number of new leaves that will be brought in.
+ Returns large number if the node cannot be removed from the set of leaves.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit )
+{
+ int Cost;
+ // make sure the node is in the construction zone
+ assert( pNode->fMarkB == 1 );
+ // cannot expand over the PI node
+ if ( Abc_ObjIsCi(pNode) )
+ return 999;
+ // get the cost of the cone
+ Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB);
+ // always accept if the number of leaves does not increase
+ if ( Cost < 2 )
+ return Cost;
+ // skip nodes with many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > nFaninLimit )
+ return 999;
+ // return the number of nodes that will be on the leaves if this node is removed
+ return Cost;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluate the cost of removing the node from the set of leaves.]
+
+ Description [Returns the number of new leaves that will be brought in.
+ Returns large number if the node cannot be removed from the set of leaves.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit,
+ Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 )
+{
+ Abc_Obj_t * pFanin0, * pFanin1, * pTemp;
+ Abc_Obj_t * pGrand, * pGrandToAdd;
+ // make sure the node is in the construction zone
+ assert( pNode->fMarkB == 1 );
+ // cannot expand over the PI node
+ if ( Abc_ObjIsCi(pNode) )
+ return 999;
+ // skip nodes with many fanouts
+// if ( Abc_ObjFanoutNum(pNode) > nFaninLimit )
+// return 999;
+ // get the children
+ pFanin0 = Abc_ObjFanin0(pNode);
+ pFanin1 = Abc_ObjFanin1(pNode);
+ assert( !pFanin0->fMarkB && !pFanin1->fMarkB );
+ // count the number of unique grandchildren that will be included
+ // return infinite cost if this number if more than 1
+ if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) )
+ return 999;
+ // consider the special case when a non-CI fanin can be dropped
+ if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB )
+ {
+ *ppLeafToAdd = pFanin1;
+ *pNodeToMark1 = pFanin0;
+ *pNodeToMark2 = NULL;
+ return 1;
+ }
+ if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB )
+ {
+ *ppLeafToAdd = pFanin0;
+ *pNodeToMark1 = pFanin1;
+ *pNodeToMark2 = NULL;
+ return 1;
+ }
+
+ // make the first node CI if any
+ if ( Abc_ObjIsCi(pFanin1) )
+ pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp;
+ // consider the first node
+ pGrandToAdd = NULL;
+ if ( Abc_ObjIsCi(pFanin0) )
+ {
+ *pNodeToMark1 = NULL;
+ pGrandToAdd = pFanin0;
+ }
+ else
+ {
+ *pNodeToMark1 = pFanin0;
+ pGrand = Abc_ObjFanin0(pFanin0);
+ if ( !pGrand->fMarkB )
+ {
+ if ( pGrandToAdd && pGrandToAdd != pGrand )
+ return 999;
+ pGrandToAdd = pGrand;
+ }
+ pGrand = Abc_ObjFanin1(pFanin0);
+ if ( !pGrand->fMarkB )
+ {
+ if ( pGrandToAdd && pGrandToAdd != pGrand )
+ return 999;
+ pGrandToAdd = pGrand;
+ }
+ }
+ // consider the second node
+ *pNodeToMark2 = pFanin1;
+ pGrand = Abc_ObjFanin0(pFanin1);
+ if ( !pGrand->fMarkB )
+ {
+ if ( pGrandToAdd && pGrandToAdd != pGrand )
+ return 999;
+ pGrandToAdd = pGrand;
+ }
+ pGrand = Abc_ObjFanin1(pFanin1);
+ if ( !pGrand->fMarkB )
+ {
+ if ( pGrandToAdd && pGrandToAdd != pGrand )
+ return 999;
+ pGrandToAdd = pGrand;
+ }
+ assert( pGrandToAdd != NULL );
+ *ppLeafToAdd = pGrandToAdd;
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds a fanin-limited, reconvergence-driven cut for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain )
+{
+ Abc_Obj_t * pNode;
+ int i;
+
+ assert( !Abc_ObjIsComplement(pRoot) );
+ assert( Abc_ObjIsNode(pRoot) );
+
+ // start the visited nodes and mark them
+ Vec_PtrClear( p->vVisited );
+ Vec_PtrPush( p->vVisited, pRoot );
+ Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) );
+ Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) );
+ pRoot->fMarkB = 1;
+ Abc_ObjFanin0(pRoot)->fMarkB = 1;
+ Abc_ObjFanin1(pRoot)->fMarkB = 1;
+
+ // start the cut
+ Vec_PtrClear( p->vNodeLeaves );
+ Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) );
+ Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) );
+
+ // compute the cut
+ while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) );
+ assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax );
+
+ // return if containing cut is not requested
+ if ( !fContain )
+ {
+ // unmark both fMarkA and fMarkB in tbe TFI
+ Abc_NodesUnmarkB( p->vVisited );
+ return p->vNodeLeaves;
+ }
+
+//printf( "\n\n\n" );
+ // compute the containing cut
+ assert( p->nNodeSizeMax < p->nConeSizeMax );
+ // copy the current boundary
+ Vec_PtrClear( p->vConeLeaves );
+ Vec_PtrForEachEntry( p->vNodeLeaves, pNode, i )
+ Vec_PtrPush( p->vConeLeaves, pNode );
+ // compute the containing cut
+ while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) );
+ assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax );
+ // unmark TFI using fMarkA and fMarkB
+ Abc_NodesUnmarkB( p->vVisited );
+ return p->vNodeLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.]
+
+ Description [This procedure looks at the current leaves and tries to change
+ one leaf at a time in such a way that the cut grows as little as possible.
+ In evaluating the fanins, this procedure looks only at their immediate
+ predecessors (this is why it is called a one-level construction procedure).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit )
+{
+ Abc_Obj_t * pNode, * pFaninBest, * pNext;
+ int CostBest, CostCur, i;
+ // find the best fanin
+ CostBest = 100;
+ pFaninBest = NULL;
+//printf( "Evaluating fanins of the cut:\n" );
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ {
+ CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit );
+//printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur );
+// if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level
+ if ( CostBest > CostCur ||
+ (CostBest == CostCur && pNode->Level > pFaninBest->Level) )
+ {
+ CostBest = CostCur;
+ pFaninBest = pNode;
+ }
+ if ( CostBest == 0 )
+ break;
+ }
+ if ( pFaninBest == NULL )
+ return 0;
+// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit );
+
+ assert( CostBest < 3 );
+ if ( vLeaves->nSize - 1 + CostBest > nSizeLimit )
+ return 0;
+// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit );
+
+ assert( Abc_ObjIsNode(pFaninBest) );
+ // remove the node from the array
+ Vec_PtrRemove( vLeaves, pFaninBest );
+//printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) );
+
+ // add the left child to the fanins
+ pNext = Abc_ObjFanin0(pFaninBest);
+ if ( !pNext->fMarkB )
+ {
+//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) );
+ pNext->fMarkB = 1;
+ Vec_PtrPush( vLeaves, pNext );
+ Vec_PtrPush( vVisited, pNext );
+ }
+ // add the right child to the fanins
+ pNext = Abc_ObjFanin1(pFaninBest);
+ if ( !pNext->fMarkB )
+ {
+//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) );
+ pNext->fMarkB = 1;
+ Vec_PtrPush( vLeaves, pNext );
+ Vec_PtrPush( vVisited, pNext );
+ }
+ assert( vLeaves->nSize <= nSizeLimit );
+ // keep doing this
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.]
+
+ Description [This procedure looks at the current leaves and tries to change
+ one leaf at a time in such a way that the cut grows as little as possible.
+ In evaluating the fanins, this procedure looks across two levels of fanins
+ (this is why it is called a two-level construction procedure).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit )
+{
+ Abc_Obj_t * pNode, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2;
+ int CostCur, i;
+ // find the best fanin
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ {
+ CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 );
+ if ( CostCur < 2 )
+ break;
+ }
+ if ( CostCur > 2 )
+ return 0;
+ // remove the node from the array
+ Vec_PtrRemove( vLeaves, pNode );
+ // add the node to the leaves
+ if ( pLeafToAdd )
+ {
+ assert( !pLeafToAdd->fMarkB );
+ pLeafToAdd->fMarkB = 1;
+ Vec_PtrPush( vLeaves, pLeafToAdd );
+ Vec_PtrPush( vVisited, pLeafToAdd );
+ }
+ // mark the other nodes
+ if ( pNodeToMark1 )
+ {
+ assert( !pNodeToMark1->fMarkB );
+ pNodeToMark1->fMarkB = 1;
+ Vec_PtrPush( vVisited, pNodeToMark1 );
+ }
+ if ( pNodeToMark2 )
+ {
+ assert( !pNodeToMark2->fMarkB );
+ pNodeToMark2->fMarkB = 1;
+ Vec_PtrPush( vVisited, pNodeToMark2 );
+ }
+ // keep doing this
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Get the nodes contained in the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins )
+{
+ Abc_Obj_t * pTemp;
+ int i;
+ // mark the fanins of the cone
+ Abc_NodesMark( vLeaves );
+ // collect the nodes in the DFS order
+ Vec_PtrClear( vVisited );
+ // add the fanins
+ if ( fIncludeFanins )
+ Vec_PtrForEachEntry( vLeaves, pTemp, i )
+ Vec_PtrPush( vVisited, pTemp );
+ // add other nodes
+ for ( i = 0; i < nRoots; i++ )
+ Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited );
+ // unmark both sets
+ Abc_NodesUnmark( vLeaves );
+ Abc_NodesUnmark( vVisited );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
+{
+ if ( pNode->fMarkA == 1 )
+ return;
+ // visit transitive fanin
+ if ( Abc_ObjIsNode(pNode) )
+ {
+ Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited );
+ Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited );
+ }
+ assert( pNode->fMarkA == 0 );
+ pNode->fMarkA = 1;
+ Vec_PtrPush( vVisited, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns BDD representing the logic function of the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited )
+{
+ Abc_Obj_t * pNode;
+ DdNode * bFunc0, * bFunc1, * bFunc;
+ int i;
+ // get the nodes in the cut without fanins in the DFS order
+ Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 );
+ // set the elementary BDDs
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ pNode->pCopy = (Abc_Obj_t *)pbVars[i];
+ // compute the BDDs for the collected nodes
+ Vec_PtrForEachEntry( vVisited, pNode, i )
+ {
+ assert( !Abc_ObjIsPi(pNode) );
+ bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) );
+ bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) );
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ pNode->pCopy = (Abc_Obj_t *)bFunc;
+ }
+ Cudd_Ref( bFunc );
+ // dereference the intermediate ones
+ Vec_PtrForEachEntry( vVisited, pNode, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns BDD representing the transition relation of the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited )
+{
+ DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult;
+ Abc_Obj_t * pNode;
+ int i;
+ // get the nodes in the cut without fanins in the DFS order
+ Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 );
+ // set the elementary BDDs
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ pNode->pCopy = (Abc_Obj_t *)pbVarsX[i];
+ // compute the BDDs for the collected nodes
+ Vec_PtrForEachEntry( vVisited, pNode, i )
+ {
+ bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) );
+ bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) );
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ pNode->pCopy = (Abc_Obj_t *)bFunc;
+ }
+ // compute the transition relation of the cone
+ bTrans = b1; Cudd_Ref( bTrans );
+ Vec_PtrForEachEntry( vRoots, pNode, i )
+ {
+ bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] ); Cudd_Ref( bFunc );
+ bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc ); Cudd_Ref( bTrans );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bFunc );
+ }
+ // dereference the intermediate ones
+ Vec_PtrForEachEntry( vVisited, pNode, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
+ // compute don't-cares
+ bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize ); Cudd_Ref( bCube );
+ bResult = Cudd_bddExistAbstract( dd, bTrans, bCube ); Cudd_Ref( bResult );
+ bResult = Cudd_Not( bResult );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_RecursiveDeref( dd, bTrans );
+ Cudd_Deref( bResult );
+ return bResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop )
+{
+ Abc_ManCut_t * p;
+ p = ALLOC( Abc_ManCut_t, 1 );
+ memset( p, 0, sizeof(Abc_ManCut_t) );
+ p->vNodeLeaves = Vec_PtrAlloc( 100 );
+ p->vConeLeaves = Vec_PtrAlloc( 100 );
+ p->vVisited = Vec_PtrAlloc( 100 );
+ p->vLevels = Vec_VecAlloc( 100 );
+ p->vNodesTfo = Vec_PtrAlloc( 100 );
+ p->nNodeSizeMax = nNodeSizeMax;
+ p->nConeSizeMax = nConeSizeMax;
+ p->nNodeFanStop = nNodeFanStop;
+ p->nConeFanStop = nConeFanStop;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManCutStop( Abc_ManCut_t * p )
+{
+ Vec_PtrFree( p->vNodeLeaves );
+ Vec_PtrFree( p->vConeLeaves );
+ Vec_PtrFree( p->vVisited );
+ Vec_VecFree( p->vLevels );
+ Vec_PtrFree( p->vNodesTfo );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the leaves of the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p )
+{
+ return p->vConeLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the leaves of the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p )
+{
+ return p->vNodeLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the leaves of the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p )
+{
+ return p->vVisited;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the TFO of the cut in the topological order.]
+
+ Description [TFO of the cut is defined as a set of nodes, for which the cut
+ is a cut, that is, every path from the collected nodes to the CIs goes through
+ a node in the cut. The nodes are collected if their level does not exceed
+ the given number (LevelMax). The nodes are returned in the topological order.
+ If the root node is given, its MFFC is marked, so that the collected nodes
+ do not contain any nodes in the MFFC.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax )
+{
+ Abc_Ntk_t * pNtk = pRoot->pNtk;
+ Vec_Ptr_t * vVec;
+ Abc_Obj_t * pNode, * pFanout;
+ int i, k, v, LevelMin;
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // assuming that the structure is clean
+ Vec_VecForEachLevel( p->vLevels, vVec, i )
+ assert( vVec->nSize == 0 );
+
+ // put fanins into the structure while labeling them
+ Abc_NtkIncrementTravId( pNtk );
+ LevelMin = -1;
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ {
+ if ( pNode->Level > (unsigned)LevelMax )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNode );
+ Vec_VecPush( p->vLevels, pNode->Level, pNode );
+ if ( LevelMin < (int)pNode->Level )
+ LevelMin = pNode->Level;
+ }
+ assert( LevelMin >= 0 );
+
+ // mark MFFC
+ if ( pRoot )
+ Abc_NodeMffcLabelAig( pRoot );
+
+ // go through the levels up
+ Vec_PtrClear( p->vNodesTfo );
+ Vec_VecForEachEntryStart( p->vLevels, pNode, i, k, LevelMin )
+ {
+ if ( i > LevelMax )
+ break;
+ // if the node is not marked, it is not a fanin
+ if ( !Abc_NodeIsTravIdCurrent(pNode) )
+ {
+ // check if it belongs to the TFO
+ if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) ||
+ !Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) )
+ continue;
+ // save the node in the TFO and label it
+ Vec_PtrPush( p->vNodesTfo, pNode );
+ Abc_NodeSetTravIdCurrent( pNode );
+ }
+ // go through the fanouts and add them to the structure if they meet the conditions
+ Abc_ObjForEachFanout( pNode, pFanout, v )
+ {
+ // skip if fanout is a CO or its level exceeds
+ if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax )
+ continue;
+ // skip if it is already added or if it is in MFFC
+ if ( Abc_NodeIsTravIdCurrent(pFanout) )
+ continue;
+ // add it to the structure but do not mark it (until tested later)
+ Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout );
+ }
+ }
+
+ // clear the levelized structure
+ Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin )
+ {
+ if ( i > LevelMax )
+ break;
+ Vec_PtrClear( vVec );
+ }
+ return p->vNodesTfo;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRefactor.c b/src/base/abci/abcRefactor.c
new file mode 100644
index 00000000..d2b77ed2
--- /dev/null
+++ b/src/base/abci/abcRefactor.c
@@ -0,0 +1,379 @@
+/**CFile****************************************************************
+
+ FileName [abcRefactor.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Resynthesis based on collapsing and refactoring.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRefactor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_ManRef_t_ Abc_ManRef_t;
+struct Abc_ManRef_t_
+{
+ // user specified parameters
+ int nNodeSizeMax; // the limit on the size of the supernode
+ int nConeSizeMax; // the limit on the size of the containing cone
+ int fVerbose; // the verbosity flag
+ // internal data structures
+ DdManager * dd; // the BDD manager
+ Vec_Str_t * vCube; // temporary
+ Vec_Int_t * vForm; // temporary
+ Vec_Ptr_t * vVisited; // temporary
+ Vec_Ptr_t * vLeaves; // temporary
+ // node statistics
+ int nLastGain;
+ int nNodesConsidered;
+ int nNodesRefactored;
+ int nNodesGained;
+ int nNodesBeg;
+ int nNodesEnd;
+ // runtime statistics
+ int timeCut;
+ int timeBdd;
+ int timeDcs;
+ int timeSop;
+ int timeFact;
+ int timeEval;
+ int timeRes;
+ int timeNtk;
+ int timeTotal;
+};
+
+static void Abc_NtkManRefPrintStats( Abc_ManRef_t * p );
+static Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose );
+static void Abc_NtkManRefStop( Abc_ManRef_t * p );
+static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental resynthesis of the AIG.]
+
+ Description [Starting from each node, computes a reconvergence-driven cut,
+ derives BDD of the cut function, constructs ISOP, factors the ISOP,
+ and replaces the current implementation of the MFFC of the node by the
+ new factored form, if the number of AIG nodes is reduced and the total
+ number of levels of the AIG network is not increated. Returns the
+ number of AIG nodes saved.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_ManRef_t * pManRef;
+ Abc_ManCut_t * pManCut;
+ Dec_Graph_t * pFForm;
+ Vec_Ptr_t * vFanins;
+ Abc_Obj_t * pNode;
+ int clk, clkStart = clock();
+ int i, nNodes;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // cleanup the AIG
+ Abc_AigCleanup(pNtk->pManFunc);
+ // start the managers
+ pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 );
+ pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose );
+ pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCut );
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk, 0 );
+
+ // resynthesize each node once
+ pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk);
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // skip the constant node
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
+ continue;
+ // skip the nodes with many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+ // compute a reconvergence-driven cut
+clk = clock();
+ vFanins = Abc_NodeFindCut( pManCut, pNode, fUseDcs );
+pManRef->timeCut += clock() - clk;
+ // evaluate this cut
+clk = clock();
+ pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose );
+pManRef->timeRes += clock() - clk;
+ if ( pFForm == NULL )
+ continue;
+ // acceptable replacement found, update the graph
+clk = clock();
+ Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRef->nLastGain );
+pManRef->timeNtk += clock() - clk;
+ Dec_GraphFree( pFForm );
+// {
+// extern int s_TotalChanges;
+// s_TotalChanges++;
+// }
+ }
+ Extra_ProgressBarStop( pProgress );
+pManRef->timeTotal = clock() - clkStart;
+ pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk);
+
+ // print statistics of the manager
+ if ( fVerbose )
+ Abc_NtkManRefPrintStats( pManRef );
+ // delete the managers
+ Abc_NtkManCutStop( pManCut );
+ Abc_NtkManRefStop( pManRef );
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkLevel( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRefactor: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resynthesizes the node using refactoring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose )
+{
+ int fVeryVerbose = 0;
+ Abc_Obj_t * pFanin;
+ Dec_Graph_t * pFForm;
+ DdNode * bNodeFunc;
+ int nNodesSaved, nNodesAdded, i, clk;
+ char * pSop;
+ int Required;
+
+ Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY;
+
+ p->nNodesConsidered++;
+
+ // get the function of the cut
+clk = clock();
+ bNodeFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pNode, vFanins, p->vVisited ); Cudd_Ref( bNodeFunc );
+p->timeBdd += clock() - clk;
+
+ // if don't-care are used, transform the function into ISOP
+ if ( fUseDcs )
+ {
+ DdNode * bNodeDc, * bNodeOn, * bNodeOnDc;
+ int nMints, nMintsDc;
+clk = clock();
+ // get the don't-cares
+ bNodeDc = Abc_NodeConeDcs( p->dd, p->dd->vars + vFanins->nSize, p->dd->vars, p->vLeaves, vFanins, p->vVisited ); Cudd_Ref( bNodeDc );
+ nMints = (1 << vFanins->nSize);
+ nMintsDc = (int)Cudd_CountMinterm( p->dd, bNodeDc, vFanins->nSize );
+// printf( "Percentage of minterms = %5.2f.\n", 100.0 * nMintsDc / nMints );
+ // get the ISF
+ bNodeOn = Cudd_bddAnd( p->dd, bNodeFunc, Cudd_Not(bNodeDc) ); Cudd_Ref( bNodeOn );
+ bNodeOnDc = Cudd_bddOr ( p->dd, bNodeFunc, bNodeDc ); Cudd_Ref( bNodeOnDc );
+ Cudd_RecursiveDeref( p->dd, bNodeFunc );
+ Cudd_RecursiveDeref( p->dd, bNodeDc );
+ // get the ISOP
+ bNodeFunc = Cudd_bddIsop( p->dd, bNodeOn, bNodeOnDc ); Cudd_Ref( bNodeFunc );
+ Cudd_RecursiveDeref( p->dd, bNodeOn );
+ Cudd_RecursiveDeref( p->dd, bNodeOnDc );
+p->timeDcs += clock() - clk;
+ }
+
+ // always accept the case of constant node
+ if ( Cudd_IsConstant(bNodeFunc) )
+ {
+ p->nLastGain = Abc_NodeMffcSize( pNode );
+ p->nNodesGained += p->nLastGain;
+ p->nNodesRefactored++;
+ Cudd_RecursiveDeref( p->dd, bNodeFunc );
+ if ( Cudd_IsComplement(bNodeFunc) )
+ return Dec_GraphCreateConst0();
+ return Dec_GraphCreateConst1();
+ }
+
+ // get the SOP of the cut
+clk = clock();
+ pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, 0, p->vCube, -1 );
+p->timeSop += clock() - clk;
+
+ // get the factored form
+clk = clock();
+ pFForm = Dec_Factor( pSop );
+ free( pSop );
+p->timeFact += clock() - clk;
+
+ // mark the fanin boundary
+ // (can mark only essential fanins, belonging to bNodeFunc!)
+ Vec_PtrForEachEntry( vFanins, pFanin, i )
+ pFanin->vFanouts.nSize++;
+ // label MFFC with current traversal ID
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ nNodesSaved = Abc_NodeMffcLabelAig( pNode );
+ // unmark the fanin boundary and set the fanins as leaves in the form
+ Vec_PtrForEachEntry( vFanins, pFanin, i )
+ {
+ pFanin->vFanouts.nSize--;
+ Dec_GraphNode(pFForm, i)->pFunc = pFanin;
+ }
+
+ // detect how many new nodes will be added (while taking into account reused nodes)
+clk = clock();
+ nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required );
+p->timeEval += clock() - clk;
+ // quit if there is no improvement
+ if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !fUseZeros )
+ {
+ Cudd_RecursiveDeref( p->dd, bNodeFunc );
+ Dec_GraphFree( pFForm );
+ return NULL;
+ }
+
+ // compute the total gain in the number of nodes
+ p->nLastGain = nNodesSaved - nNodesAdded;
+ p->nNodesGained += p->nLastGain;
+ p->nNodesRefactored++;
+
+ // report the progress
+ if ( fVeryVerbose )
+ {
+ printf( "Node %6s : ", Abc_ObjName(pNode) );
+ printf( "Cone = %2d. ", vFanins->nSize );
+ printf( "BDD = %2d. ", Cudd_DagSize(bNodeFunc) );
+ printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pFForm) );
+ printf( "MFFC = %2d. ", nNodesSaved );
+ printf( "Add = %2d. ", nNodesAdded );
+ printf( "GAIN = %2d. ", p->nLastGain );
+ printf( "\n" );
+ }
+ Cudd_RecursiveDeref( p->dd, bNodeFunc );
+ return pFForm;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose )
+{
+ Abc_ManRef_t * p;
+ p = ALLOC( Abc_ManRef_t, 1 );
+ memset( p, 0, sizeof(Abc_ManRef_t) );
+ p->vCube = Vec_StrAlloc( 100 );
+ p->vVisited = Vec_PtrAlloc( 100 );
+ p->nNodeSizeMax = nNodeSizeMax;
+ p->nConeSizeMax = nConeSizeMax;
+ p->fVerbose = fVerbose;
+ // start the BDD manager
+ if ( fUseDcs )
+ p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ else
+ p->dd = Cudd_Init( p->nNodeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_zddVarsFromBddVars( p->dd, 2 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManRefStop( Abc_ManRef_t * p )
+{
+ Extra_StopManager( p->dd );
+ Vec_PtrFree( p->vVisited );
+ Vec_StrFree( p->vCube );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManRefPrintStats( Abc_ManRef_t * p )
+{
+ printf( "Refactoring statistics:\n" );
+ printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
+ printf( "Nodes refactored = %8d.\n", p->nNodesRefactored );
+ printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
+ PRT( "Cuts ", p->timeCut );
+ PRT( "Resynthesis", p->timeRes );
+ PRT( " BDD ", p->timeBdd );
+ PRT( " DCs ", p->timeDcs );
+ PRT( " SOP ", p->timeSop );
+ PRT( " FF ", p->timeFact );
+ PRT( " Eval ", p->timeEval );
+ PRT( "AIG update ", p->timeNtk );
+ PRT( "TOTAL ", p->timeTotal );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRenode.c b/src/base/abci/abcRenode.c
new file mode 100644
index 00000000..8e8e8719
--- /dev/null
+++ b/src/base/abci/abcRenode.c
@@ -0,0 +1,311 @@
+/**CFile****************************************************************
+
+ FileName [abcRenode.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRenode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "reo.h"
+#include "if.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalSop( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalMv( If_Cut_t * pCut );
+
+static reo_man * s_pReo = NULL;
+static DdManager * s_pDd = NULL;
+static Vec_Int_t * s_vMemory = NULL;
+static Vec_Int_t * s_vMemory2 = NULL;
+
+static int nDsdCounter = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs renoding as technology mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose )
+{
+ extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+ If_Par_t Pars, * pPars = &Pars;
+ Abc_Ntk_t * pNtkNew;
+
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ printf( "Performing renoding with choices.\n" );
+
+ nDsdCounter = 0;
+
+ // set defaults
+ memset( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+ pPars->nLutSize = nFaninMax;
+ pPars->nCutsMax = nCubeMax;
+ pPars->nFlowIters = nFlowIters;
+ pPars->nAreaIters = nAreaIters;
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 1;
+ pPars->fArea = fArea;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 0; //
+ pPars->fLatchPaths = 0;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = fVerbose;
+ // internal parameters
+ pPars->fTruth = 1;
+ pPars->fUsePerm = 1;
+ pPars->nLatches = 0;
+ pPars->pLutLib = NULL; // Abc_FrameReadLibLut();
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->fUseBdds = fUseBdds;
+ pPars->fUseSops = fUseSops;
+ pPars->fUseCnfs = fUseCnfs;
+ pPars->fUseMv = fUseMv;
+ if ( fUseBdds )
+ pPars->pFuncCost = Abc_NtkRenodeEvalBdd;
+ else if ( fUseSops )
+ pPars->pFuncCost = Abc_NtkRenodeEvalSop;
+ else if ( fUseCnfs )
+ {
+ pPars->fArea = 1;
+ pPars->pFuncCost = Abc_NtkRenodeEvalCnf;
+ }
+ else if ( fUseMv )
+ pPars->pFuncCost = Abc_NtkRenodeEvalMv;
+ else
+ pPars->pFuncCost = Abc_NtkRenodeEvalAig;
+
+ // start the manager
+ if ( fUseBdds )
+ {
+ assert( s_pReo == NULL );
+ s_pDd = Cudd_Init( nFaninMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ s_pReo = Extra_ReorderInit( nFaninMax, 100 );
+ pPars->pReoMan = s_pReo;
+ }
+ else
+ {
+ assert( s_vMemory == NULL );
+ s_vMemory = Vec_IntAlloc( 1 << 16 );
+ s_vMemory2 = Vec_IntAlloc( 1 << 16 );
+ }
+
+ // perform mapping/renoding
+ pNtkNew = Abc_NtkIf( pNtk, pPars );
+
+ // start the manager
+ if ( fUseBdds )
+ {
+ Extra_StopManager( s_pDd );
+ Extra_ReorderQuit( s_pReo );
+ s_pReo = NULL;
+ s_pDd = NULL;
+ }
+ else
+ {
+ Vec_IntFree( s_vMemory );
+ Vec_IntFree( s_vMemory2 );
+ s_vMemory = NULL;
+ s_vMemory2 = NULL;
+ }
+
+// printf( "Decomposed %d functions.\n", nDsdCounter );
+
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cost based on the factored form.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalAig( If_Cut_t * pCut )
+{
+ Kit_Graph_t * pGraph;
+ int i, nNodes;
+/*
+extern void Kit_DsdTest( unsigned * pTruth, int nVars );
+if ( If_CutLeaveNum(pCut) == 8 )
+{
+ nDsdCounter++;
+ Kit_DsdTest( If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+}
+*/
+ pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory );
+ if ( pGraph == NULL )
+ {
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = 100;
+ return IF_COST_MAX;
+ }
+ nNodes = Kit_GraphNodeNum( pGraph );
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) );
+ Kit_GraphFree( pGraph );
+ return nNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cost based on the BDD size after reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut )
+{
+ int pOrder[IF_MAX_LUTSIZE];
+ DdNode * bFunc, * bFuncNew;
+ int i, k, nNodes;
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = pOrder[i] = -100;
+ bFunc = Kit_TruthToBdd( s_pDd, If_CutTruth(pCut), If_CutLeaveNum(pCut), 0 ); Cudd_Ref( bFunc );
+ bFuncNew = Extra_Reorder( s_pReo, s_pDd, bFunc, pOrder ); Cudd_Ref( bFuncNew );
+ for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ )
+ if ( pOrder[i] >= 0 )
+ pCut->pPerm[pOrder[i]] = ++k; // double-check this!
+ nNodes = -1 + Cudd_DagSize( bFuncNew );
+ Cudd_RecursiveDeref( s_pDd, bFuncNew );
+ Cudd_RecursiveDeref( s_pDd, bFunc );
+ return nNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cost based on ISOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalSop( If_Cut_t * pCut )
+{
+ int i, RetValue;
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = 1;
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 1 );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ return Vec_IntSize( s_vMemory );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cost based on two ISOPs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
+{
+ int i, RetValue, nClauses;
+ // set internal mapper parameters
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = 1;
+ // compute ISOP for the positive phase
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ nClauses = Vec_IntSize( s_vMemory );
+ // compute ISOP for the negative phase
+ Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+ Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ nClauses += Vec_IntSize( s_vMemory );
+ return nClauses;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cost of MV-SOP of the cut function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalMv( If_Cut_t * pCut )
+{
+ int i, RetValue;
+ // set internal mapper parameters
+ for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+ pCut->pPerm[i] = 1;
+ // compute ISOP for the positive phase
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ // compute ISOP for the negative phase
+ Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+ RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 );
+ Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+ if ( RetValue == -1 )
+ return IF_COST_MAX;
+ assert( RetValue == 0 || RetValue == 1 );
+ // return the cost of the cut
+ RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 );
+ if ( RetValue >= IF_COST_MAX )
+ return IF_COST_MAX;
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcReorder.c b/src/base/abci/abcReorder.c
new file mode 100644
index 00000000..d6dee49b
--- /dev/null
+++ b/src/base/abci/abcReorder.c
@@ -0,0 +1,100 @@
+/**CFile****************************************************************
+
+ FileName [abcReorder.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Reordering local BDDs of the nodes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcReorder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "reo.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reorders BDD of the local function of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ DdNode * bFunc;
+ int * pOrder, i;
+ // create the temporary array for the variable order
+ pOrder = ALLOC( int, Abc_ObjFaninNum(pNode) );
+ for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+ pOrder[i] = -1;
+ // reorder the BDD
+ bFunc = Extra_Reorder( p, pNode->pNtk->pManFunc, pNode->pData, pOrder ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( pNode->pNtk->pManFunc, pNode->pData );
+ pNode->pData = bFunc;
+ // update the fanin order
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ];
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ pNode->vFanins.pArray[i] = pOrder[i];
+ free( pOrder );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reorders BDDs of the local functions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ reo_man * p;
+ Abc_Obj_t * pNode;
+ int i;
+ p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( Abc_ObjFaninNum(pNode) < 3 )
+ continue;
+ if ( fVerbose )
+ fprintf( stdout, "%10s: ", Abc_ObjName(pNode) );
+ if ( fVerbose )
+ fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize(pNode->pData) );
+ Abc_NodeBddReorder( p, pNode );
+ if ( fVerbose )
+ fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize(pNode->pData) );
+ }
+ Extra_ReorderQuit( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRestruct.c b/src/base/abci/abcRestruct.c
new file mode 100644
index 00000000..326d1543
--- /dev/null
+++ b/src/base/abci/abcRestruct.c
@@ -0,0 +1,1496 @@
+/**CFile****************************************************************
+
+ FileName [abcRestruct.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRestruct.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+#include "dsd.h"
+#include "cut.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define RST_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+typedef struct Abc_ManRst_t_ Abc_ManRst_t;
+struct Abc_ManRst_t_
+{
+ // the network
+ Abc_Ntk_t * pNtk; // the network for restructuring
+ // user specified parameters
+ int nCutMax; // the limit on the size of the supernode
+ int fUpdateLevel; // turns on watching the number of levels
+ int fUseZeros; // turns on zero-cost replacements
+ int fVerbose; // the verbosity flag
+ // internal data structures
+ DdManager * dd; // the BDD manager
+ Dsd_Manager_t * pManDsd; // the DSD manager
+ Vec_Ptr_t * vVisited; // temporary
+ Vec_Ptr_t * vLeaves; // temporary
+ Vec_Ptr_t * vDecs; // temporary
+ Vec_Ptr_t * vTemp; // temporary
+ Vec_Int_t * vSims; // temporary
+ Vec_Int_t * vRands; // temporary
+ Vec_Int_t * vOnes; // temporary
+ Vec_Int_t * vBinate; // temporary
+ Vec_Int_t * vTwos; // temporary
+ // node statistics
+ int nLastGain;
+ int nCutsConsidered;
+ int nCutsExplored;
+ int nNodesConsidered;
+ int nNodesRestructured;
+ int nNodesGained;
+ // runtime statistics
+ int timeCut;
+ int timeBdd;
+ int timeDsd;
+ int timeEval;
+ int timeRes;
+ int timeNtk;
+ int timeTotal;
+};
+
+static Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList );
+
+static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList );
+static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut );
+static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded );
+
+static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag );
+static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose );
+static void Abc_NtkManRstStop( Abc_ManRst_t * p );
+static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implements AIG restructuring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_ManRst_t * pManRst;
+ Cut_Man_t * pManCut;
+ Cut_Cut_t * pCutList;
+ Dec_Graph_t * pGraph;
+ Abc_Obj_t * pNode;
+ int clk, clkStart = clock();
+ int fMulti = 1;
+ int fResub = 0;
+ int i, nNodes;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // cleanup the AIG
+ Abc_AigCleanup(pNtk->pManFunc);
+ Abc_NtkCleanCopy(pNtk);
+
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk, 0 );
+
+ // start the restructuring manager
+ pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose );
+ pManRst->pNtk = pNtk;
+ // start the cut manager
+clk = clock();
+ pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti );
+pManRst->timeCut += clock() - clk;
+// pNtk->pManCut = pManCut;
+
+ // resynthesize each node once
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // skip the constant node
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
+ continue;
+ // skip the node if it is inside the tree
+// if ( Abc_ObjFanoutNum(pNode) < 2 )
+// continue;
+ // skip the nodes with too many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+ // get the cuts for the given node
+clk = clock();
+ pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti, 0 );
+pManRst->timeCut += clock() - clk;
+
+ // perform restructuring
+clk = clock();
+ if ( fResub )
+ pGraph = Abc_NodeResubstitute( pManRst, pNode, pCutList );
+ else
+ pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList );
+pManRst->timeRes += clock() - clk;
+ if ( pGraph == NULL )
+ continue;
+
+ // acceptable replacement found, update the graph
+clk = clock();
+ Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain );
+pManRst->timeNtk += clock() - clk;
+ Dec_GraphFree( pGraph );
+ }
+ Extra_ProgressBarStop( pProgress );
+pManRst->timeTotal = clock() - clkStart;
+
+ // print statistics of the manager
+// if ( fVerbose )
+ Abc_NtkManRstPrintStats( pManRst );
+ // delete the managers
+ Cut_ManStop( pManCut );
+ Abc_NtkManRstStop( pManRst );
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkLevel( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRefactor: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot, int nNodesSaved )
+{
+ Abc_Obj_t * pNode, * pFanout;//, * pFanin;
+ int i, k;
+ // start with the leaves
+ Vec_PtrClear( p->vDecs );
+ Vec_PtrForEachEntry( p->vLeaves, pNode, i )
+ {
+ Vec_PtrPush( p->vDecs, pNode );
+ assert( pNode->fMarkC == 0 );
+ pNode->fMarkC = 1;
+ }
+ // explore the fanouts
+ Vec_PtrForEachEntry( p->vDecs, pNode, i )
+ {
+ // if the fanout has both fanins in the set, add it
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( pFanout->fMarkC || Abc_ObjIsPo(pFanout) )
+ continue;
+ if ( Abc_ObjFanin0(pFanout)->fMarkC && Abc_ObjFanin1(pFanout)->fMarkC )
+ {
+ Vec_PtrPush( p->vDecs, pFanout );
+ pFanout->fMarkC = 1;
+ }
+ }
+ }
+ // unmark the nodes
+ Vec_PtrForEachEntry( p->vDecs, pNode, i )
+ pNode->fMarkC = 0;
+/*
+ // print the nodes
+ Vec_PtrForEachEntryStart( p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) )
+ {
+ printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " );
+ // find the first fanin
+ Vec_PtrForEachEntry( p->vDecs, pFanin, k )
+ if ( Abc_ObjFanin0(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(p->vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+ // find the second fanin
+ Vec_PtrForEachEntry( p->vDecs, pFanin, k )
+ if ( Abc_ObjFanin1(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(p->vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+ printf( "\n" );
+ }
+*/
+ printf( "%d\n", Vec_PtrSize(p->vDecs)-nNodesSaved-Vec_PtrSize(p->vLeaves) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList )
+{
+ Dec_Graph_t * pGraph;
+ Cut_Cut_t * pCut;
+// int nCuts;
+ p->nNodesConsidered++;
+/*
+ // count the number of cuts with four inputs or more
+ nCuts = 0;
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ nCuts += (int)(pCut->nLeaves > 3);
+ printf( "-----------------------------------\n" );
+ printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts );
+*/
+ // go through the interesting cuts
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ {
+ if ( pCut->nLeaves < 4 )
+ continue;
+ if ( pGraph = Abc_NodeRestructureCut( p, pNode, pCut ) )
+ return pGraph;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+ Dec_Graph_t * pGraph;
+ Dsd_Node_t * pNodeDsd;
+ Abc_Obj_t * pLeaf;
+ DdNode * bFunc;
+ int nNodesSaved, nNodesAdded;
+ int Required, nMaxSize, clk, i;
+ int fVeryVerbose = 0;
+
+ p->nCutsConsidered++;
+
+ // get the required time for the node
+ Required = p->fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY;
+
+ // collect the leaves of the cut
+ Vec_PtrClear( p->vLeaves );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ pLeaf = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]);
+ if ( pLeaf == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes
+ return NULL;
+ Vec_PtrPush( p->vLeaves, pLeaf );
+ }
+
+ if ( pRoot->Id == 29 )
+ {
+ int x = 0;
+ }
+
+clk = clock();
+ // collect the internal nodes of the cut
+// Abc_NodeConeCollect( &pRoot, 1, p->vLeaves, p->vVisited, 0 );
+ // derive the BDD of the cut
+ bFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pRoot, p->vLeaves, p->vVisited ); Cudd_Ref( bFunc );
+p->timeBdd += clock() - clk;
+
+ // consider the special case, when the function is a constant
+ if ( Cudd_IsConstant(bFunc) )
+ {
+ p->nLastGain = Abc_NodeMffcSize( pRoot );
+ p->nNodesGained += p->nLastGain;
+ p->nNodesRestructured++;
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ if ( Cudd_IsComplement(bFunc) )
+ return Dec_GraphCreateConst0();
+ return Dec_GraphCreateConst1();
+ }
+
+clk = clock();
+ // try disjoint support decomposition
+ pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc );
+p->timeDsd += clock() - clk;
+
+ // skip nodes with non-decomposable blocks
+ Dsd_TreeNodeGetInfoOne( pNodeDsd, NULL, &nMaxSize );
+ if ( nMaxSize > 3 )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return NULL;
+ }
+
+
+/*
+ // skip nodes that cannot be improved
+ if ( Vec_PtrSize(p->vVisited) <= Dsd_TreeGetAigCost(pNodeDsd) )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return NULL;
+ }
+*/
+
+ p->nCutsExplored++;
+
+ // mark the fanin boundary
+ // (can mark only essential fanins, belonging to bNodeFunc!)
+ Vec_PtrForEachEntry( p->vLeaves, pLeaf, i )
+ pLeaf->vFanouts.nSize++;
+ // label MFFC with current traversal ID
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ nNodesSaved = Abc_NodeMffcLabelAig( pRoot );
+ // unmark the fanin boundary and set the fanins as leaves in the form
+ Vec_PtrForEachEntry( p->vLeaves, pLeaf, i )
+ pLeaf->vFanouts.nSize--;
+/*
+ if ( nNodesSaved < 3 )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return NULL;
+ }
+*/
+
+/*
+ printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d.\n",
+ pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd),
+ nNodesSaved );
+ Dsd_NodePrint( stdout, pNodeDsd );
+
+ Abc_RestructNodeDivisors( p, pRoot );
+
+ if ( pRoot->Id == 433 )
+ {
+ int x = 0;
+ }
+*/
+// Abc_RestructNodeDivisors( p, pRoot, nNodesSaved );
+
+
+ // detect how many new nodes will be added (while taking into account reused nodes)
+clk = clock();
+ if ( nMaxSize > 3 )
+ pGraph = NULL;
+ else
+ pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded );
+// pGraph = NULL;
+p->timeEval += clock() - clk;
+
+ // quit if there is no improvement
+ if ( pGraph == NULL || nNodesAdded == -1 || nNodesAdded == nNodesSaved && !p->fUseZeros )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ if ( pGraph ) Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+/*
+ // print stats
+ printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d. New MFFC = %2d. Gain = %d.\n",
+ pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd),
+ nNodesSaved, nNodesAdded, (nNodesAdded == -1)? 0 : nNodesSaved-nNodesAdded );
+// Dsd_NodePrint( stdout, pNodeDsd );
+// Dec_GraphPrint( stdout, pGraph, NULL, NULL );
+*/
+
+ // compute the total gain in the number of nodes
+ p->nLastGain = nNodesSaved - nNodesAdded;
+ p->nNodesGained += p->nLastGain;
+ p->nNodesRestructured++;
+
+ // report the progress
+ if ( fVeryVerbose )
+ {
+ printf( "Node %6s : ", Abc_ObjName(pRoot) );
+ printf( "Cone = %2d. ", p->vLeaves->nSize );
+ printf( "BDD = %2d. ", Cudd_DagSize(bFunc) );
+ printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pGraph) );
+ printf( "MFFC = %2d. ", nNodesSaved );
+ printf( "Add = %2d. ", nNodesAdded );
+ printf( "GAIN = %2d. ", p->nLastGain );
+ printf( "\n" );
+ }
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return pGraph;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Moves closer to the end the node that is best for sharing.]
+
+ Description [If the flag is set, tries to find an EXOR, otherwise, tries
+ to find an OR.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEdgeDsdPermute( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Vec_Int_t * vEdges, int fExor )
+{
+ Dec_Edge_t eNode1, eNode2, eNode3;
+ Abc_Obj_t * pNode1, * pNode2, * pNode3, * pTemp;
+ int LeftBound = 0, RightBound, i;
+ // get the right bound
+ RightBound = Vec_IntSize(vEdges) - 2;
+ assert( LeftBound <= RightBound );
+ if ( LeftBound == RightBound )
+ return;
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound + 1) );
+ eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound ) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // quit if the last node does not exist
+ if ( pNode1 == NULL )
+ return;
+ // find the first node that can be shared
+ for ( i = RightBound; i >= LeftBound; i-- )
+ {
+ // get the third node
+ eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, i) );
+ pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc;
+ pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl );
+ if ( pNode3 == NULL )
+ continue;
+ // check if the node exists
+ if ( fExor )
+ {
+ if ( pNode1 && pNode3 )
+ {
+ pTemp = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode3, NULL );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ continue;
+
+ if ( pNode3 == pNode2 )
+ return;
+ Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) );
+ Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) );
+ return;
+ }
+ }
+ else
+ {
+ if ( pNode1 && pNode3 )
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ continue;
+
+ if ( eNode3.Node == eNode2.Node )
+ return;
+ Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) );
+ Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) );
+ return;
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the new edge in the given order.]
+
+ Description [Similar to Vec_IntPushOrder, except in decreasing order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEdgeDsdPushOrdered( Dec_Graph_t * pGraph, Vec_Int_t * vEdges, int Edge )
+{
+ int i, NodeOld, NodeNew;
+ vEdges->nSize++;
+ for ( i = vEdges->nSize-2; i >= 0; i-- )
+ {
+ NodeOld = Dec_IntToEdge(vEdges->pArray[i]).Node;
+ NodeNew = Dec_IntToEdge(Edge).Node;
+ // use <= because we are trying to push the new (non-existent) nodes as far as possible
+ if ( Dec_GraphNode(pGraph, NodeOld)->Level <= Dec_GraphNode(pGraph, NodeNew)->Level )
+ vEdges->pArray[i+1] = vEdges->pArray[i];
+ else
+ break;
+ }
+ vEdges->pArray[i+1] = Edge;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluation one DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, int Required, int nNodesSaved, int * pnNodesAdded )
+{
+ Dec_Edge_t eNode1, eNode2, eNode3, eResult, eQuit = { 0, 2006 };
+ Abc_Obj_t * pNode1, * pNode2, * pNode3, * pNode4, * pTemp;
+ Dsd_Node_t * pChildDsd;
+ Dsd_Type_t DecType;
+ Vec_Int_t * vEdges;
+ int Level1, Level2, Level3, Level4;
+ int i, Index, fCompl, Type;
+
+ // remove the complemented attribute
+ fCompl = Dsd_IsComplement( pNodeDsd );
+ pNodeDsd = Dsd_Regular( pNodeDsd );
+
+ // consider the trivial case
+ DecType = Dsd_NodeReadType( pNodeDsd );
+ if ( DecType == DSD_NODE_BUF )
+ {
+ Index = Dsd_NodeReadFunc(pNodeDsd)->index;
+ assert( Index < Dec_GraphLeaveNum(pGraph) );
+ eResult = Dec_EdgeCreate( Index, fCompl );
+ return eResult;
+ }
+ assert( DecType == DSD_NODE_OR || DecType == DSD_NODE_EXOR || DecType == DSD_NODE_PRIME );
+
+ // solve the problem for the children
+ vEdges = Vec_IntAlloc( Dsd_NodeReadDecsNum(pNodeDsd) );
+ Dsd_NodeForEachChild( pNodeDsd, i, pChildDsd )
+ {
+ eResult = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pChildDsd, Required, nNodesSaved, pnNodesAdded );
+ if ( eResult.Node == eQuit.Node ) // infeasible
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ // order the inputs only if this is OR or EXOR
+ if ( DecType == DSD_NODE_PRIME )
+ Vec_IntPush( vEdges, Dec_EdgeToInt(eResult) );
+ else
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eResult) );
+ }
+ // the edges are sorted by the level of their nodes in decreasing order
+
+
+ // consider special cases
+ if ( DecType == DSD_NODE_OR )
+ {
+ // try to balance the nodes by delay
+ assert( Vec_IntSize(vEdges) > 1 );
+ while ( Vec_IntSize(vEdges) > 1 )
+ {
+ // permute the last two entries
+ if ( Vec_IntSize(vEdges) > 2 )
+ Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 0 );
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // check if the new node exists
+ pNode3 = NULL;
+ if ( pNode1 && pNode2 )
+ {
+ pNode3 = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ pNode3 = !pNode3? NULL : Abc_ObjNot(pNode3);
+ }
+ // create the new node
+ eNode3 = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 );
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + ABC_MAX(Level1, Level2);
+ // get the new node if possible
+ if ( pNode3 )
+ {
+ Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl);
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level );
+ }
+ if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) )
+ {
+ (*pnNodesAdded)++;
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ // add the resulting node to the form
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) );
+ }
+ // get the last node
+ eResult = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ Vec_IntFree( vEdges );
+ // complement the graph if the node was complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ if ( DecType == DSD_NODE_EXOR )
+ {
+ // try to balance the nodes by delay
+ assert( Vec_IntSize(vEdges) > 1 );
+ while ( Vec_IntSize(vEdges) > 1 )
+ {
+ // permute the last two entries
+ if ( Vec_IntSize(vEdges) > 2 )
+ Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 1 );
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // check if the new node exists
+ Type = 0;
+ pNode3 = NULL;
+ if ( pNode1 && pNode2 )
+ pNode3 = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, &Type );
+ // create the new node
+ eNode3 = Dec_GraphAddNodeXor( pGraph, eNode1, eNode2, Type ); // should have the same structure as in AIG
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + ABC_MAX(Level1, Level2);
+ // get the new node if possible
+ if ( pNode3 )
+ {
+ Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl);
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level );
+ }
+ if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) )
+ {
+ (*pnNodesAdded)++;
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded) += 2;
+ else if ( Type == 0 )
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ // add the resulting node to the form
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) );
+ }
+ // get the last node
+ eResult = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ Vec_IntFree( vEdges );
+ // complement the graph if the node is complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ if ( DecType == DSD_NODE_PRIME )
+ {
+ DdNode * bLocal, * bVar, * bCofT, * bCofE;
+ bLocal = Dsd_TreeGetPrimeFunction( pManRst->dd, pNodeDsd ); Cudd_Ref( bLocal );
+//Extra_bddPrint( pManRst->dd, bLocal );
+
+ bVar = pManRst->dd->vars[0];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ bVar = pManRst->dd->vars[1];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ bVar = pManRst->dd->vars[2];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ Cudd_RecursiveDeref( pManRst->dd, bLocal );
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ }
+ Cudd_RecursiveDeref( pManRst->dd, bLocal );
+ // we found the control variable (bVar) and the var-cofactors (bCofT, bCofE)
+
+ // find the graph nodes
+ eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, bVar->index) );
+ eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofT)->index) );
+ eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofE)->index) );
+ // add the complements to the graph nodes
+ eNode2.fCompl ^= Cudd_IsComplement(bCofT);
+ eNode3.fCompl ^= Cudd_IsComplement(bCofE);
+
+ // because the cofactors are vars, we can just as well deref them here
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+
+ // find the ABC nodes
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl );
+
+ // check if the new node exists
+ Type = 0;
+ pNode4 = NULL;
+ if ( pNode1 && pNode2 && pNode3 )
+ pNode4 = Abc_AigMuxLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, pNode3, &Type );
+
+ // create the new node
+ eResult = Dec_GraphAddNodeMux( pGraph, eNode1, eNode2, eNode3, Type ); // should have the same structure as AIG
+
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + ABC_MAX( ABC_MAX(Level1, Level2), Level3 );
+ // get the new node if possible
+ if ( pNode4 )
+ {
+ Dec_GraphNode( pGraph, eResult.Node )->pFunc = Abc_ObjNotCond(pNode4, eResult.fCompl);
+ Level4 = Dec_GraphNode( pGraph, eResult.Node )->Level;
+ assert( Required == ABC_INFINITY || Level4 == (int)Abc_ObjRegular(pNode4)->Level );
+ }
+ if ( !pNode4 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode4)) )
+ {
+ (*pnNodesAdded)++;
+ if ( Type == 0 )
+ {
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( !pNode1 || !pNode3 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ }
+ else
+ {
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( !pNode1 || !pNode3 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ }
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+
+ Vec_IntFree( vEdges );
+ // complement the graph if the node was complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ Vec_IntFree( vEdges );
+ return eQuit;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluation one DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t gEdge;
+ Abc_Obj_t * pLeaf;
+ Dec_Node_t * pNode;
+ int i;
+
+ // create the graph and set the leaves
+ pGraph = Dec_GraphCreate( Vec_PtrSize(pManRst->vLeaves) );
+ Dec_GraphForEachLeaf( pGraph, pNode, i )
+ {
+ pLeaf = Vec_PtrEntry( pManRst->vLeaves, i );
+ pNode->pFunc = pLeaf;
+ pNode->Level = pLeaf->Level;
+ }
+
+ // create the decomposition structure from the DSD
+ *pnNodesAdded = 0;
+ gEdge = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pNodeDsd, Required, nNodesSaved, pnNodesAdded );
+ if ( gEdge.Node > 1000 ) // infeasible
+ {
+ *pnNodesAdded = -1;
+ Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+ // quit if the root node is the same
+ pLeaf = Dec_GraphNode( pGraph, gEdge.Node )->pFunc;
+ if ( Abc_ObjRegular(pLeaf) == pRoot )
+ {
+ *pnNodesAdded = -1;
+ Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+ Dec_GraphSetRoot( pGraph, gEdge );
+ return pGraph;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag )
+{
+ static Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pManCut;
+ Abc_Obj_t * pObj;
+ int i;
+ // start the cut manager
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = nCutMax; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 250; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 0; // compute sequential cuts
+ pParams->fDrop = 0; // drop cuts on the fly
+ pParams->fDag = fDag; // compute DAG cuts
+ pParams->fTree = 0; // compute tree cuts
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pManCut = Cut_ManStart( pParams );
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( pManCut, pObj->Id );
+ return pManCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose )
+{
+ Abc_ManRst_t * p;
+ p = ALLOC( Abc_ManRst_t, 1 );
+ memset( p, 0, sizeof(Abc_ManRst_t) );
+ // set the parameters
+ p->nCutMax = nCutMax;
+ p->fUpdateLevel = fUpdateLevel;
+ p->fUseZeros = fUseZeros;
+ p->fVerbose = fVerbose;
+ // start the BDD manager
+ p->dd = Cudd_Init( p->nCutMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_zddVarsFromBddVars( p->dd, 2 );
+ // start the DSD manager
+ p->pManDsd = Dsd_ManagerStart( p->dd, p->dd->size, 0 );
+ // other temp datastructures
+ p->vVisited = Vec_PtrAlloc( 100 );
+ p->vLeaves = Vec_PtrAlloc( 100 );
+ p->vDecs = Vec_PtrAlloc( 100 );
+ p->vTemp = Vec_PtrAlloc( 100 );
+ p->vSims = Vec_IntAlloc( 100 );
+ p->vOnes = Vec_IntAlloc( 100 );
+ p->vBinate = Vec_IntAlloc( 100 );
+ p->vTwos = Vec_IntAlloc( 100 );
+ p->vRands = Vec_IntAlloc( 20 );
+
+ {
+ int i;
+ for ( i = 0; i < 20; i++ )
+ Vec_IntPush( p->vRands, (int)RST_RANDOM_UNSIGNED );
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManRstStop( Abc_ManRst_t * p )
+{
+ Dsd_ManagerStop( p->pManDsd );
+ Extra_StopManager( p->dd );
+ Vec_PtrFree( p->vDecs );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vVisited );
+ Vec_PtrFree( p->vTemp );
+ Vec_IntFree( p->vSims );
+ Vec_IntFree( p->vOnes );
+ Vec_IntFree( p->vBinate );
+ Vec_IntFree( p->vTwos );
+ Vec_IntFree( p->vRands );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManRstPrintStats( Abc_ManRst_t * p )
+{
+ printf( "Refactoring statistics:\n" );
+ printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
+ printf( "Cuts considered = %8d.\n", p->nCutsConsidered );
+ printf( "Cuts explored = %8d.\n", p->nCutsExplored );
+ printf( "Nodes restructured = %8d.\n", p->nNodesRestructured );
+ printf( "Calculated gain = %8d.\n", p->nNodesGained );
+ PRT( "Cuts ", p->timeCut );
+ PRT( "Resynthesis", p->timeRes );
+ PRT( " BDD ", p->timeBdd );
+ PRT( " DSD ", p->timeDsd );
+ PRT( " Eval ", p->timeEval );
+ PRT( "AIG update ", p->timeNtk );
+ PRT( "TOTAL ", p->timeTotal );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_Abc_NodeResubCollectDivs( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+ Abc_Obj_t * pNode, * pFanout;
+ int i, k;
+ // collect the leaves of the cut
+ Vec_PtrClear( p->vDecs );
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ pNode = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]);
+ if ( pNode == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes
+ return 0;
+ Vec_PtrPush( p->vDecs, pNode );
+ Abc_NodeSetTravIdCurrent( pNode );
+ }
+ // explore the fanouts
+ Vec_PtrForEachEntry( p->vDecs, pNode, i )
+ {
+ // if the fanout has both fanins in the set, add it
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsPo(pFanout) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) )
+ {
+ Vec_PtrPush( p->vDecs, pFanout );
+ Abc_NodeSetTravIdCurrent( pFanout );
+ }
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeResubMffc_rec( Abc_Obj_t * pNode )
+{
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return 0;
+ Abc_NodeSetTravIdCurrent( pNode );
+ return 1 + Abc_NodeResubMffc_rec( Abc_ObjFanin0(pNode) ) +
+ Abc_NodeResubMffc_rec( Abc_ObjFanin1(pNode) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeResubMffc( Abc_ManRst_t * p, Vec_Ptr_t * vDecs, int nLeaves, Abc_Obj_t * pRoot )
+{
+ Abc_Obj_t * pObj;
+ int Counter, i, k;
+ // increment the traversal ID for the leaves
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ // label the leaves
+ Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // make sure the node is in the cone and is no one of the leaves
+ assert( Abc_NodeIsTravIdPrevious(pRoot) );
+ Counter = Abc_NodeResubMffc_rec( pRoot );
+ // move the labeled nodes to the end
+ Vec_PtrClear( p->vTemp );
+ k = 0;
+ Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves )
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ Vec_PtrPush( p->vTemp, pObj );
+ else
+ Vec_PtrWriteEntry( vDecs, k++, pObj );
+ // add the labeled nodes
+ Vec_PtrForEachEntry( p->vTemp, pObj, i )
+ Vec_PtrWriteEntry( vDecs, k++, pObj );
+ assert( k == Vec_PtrSize(p->vDecs) );
+ assert( pRoot == Vec_PtrEntryLast(p->vDecs) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeMffcSimulate( Vec_Ptr_t * vDecs, int nLeaves, Vec_Int_t * vRands, Vec_Int_t * vSims )
+{
+ Abc_Obj_t * pObj;
+ unsigned uData0, uData1, uData;
+ int i;
+ // initialize random simulation data
+ Vec_IntClear( vSims );
+ Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves )
+ {
+ uData = (unsigned)Vec_IntEntry( vRands, i );
+ pObj->pData = (void *)uData;
+ Vec_IntPush( vSims, uData );
+ }
+ // simulate
+ Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves )
+ {
+ uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData;
+ uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData;
+ uData = (Abc_ObjFaninC0(pObj)? ~uData0 : uData0) & (Abc_ObjFaninC1(pObj)? ~uData1 : uData1);
+ pObj->pData = (void *)uData;
+ Vec_IntPush( vSims, uData );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Full equality check.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeCheckFull( Abc_ManRst_t * p, Dec_Graph_t * pGraph )
+{
+ return 1;
+}
+/**Function*************************************************************
+
+ Synopsis [Detect contants.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcConstants( Abc_ManRst_t * p, Vec_Int_t * vSims )
+{
+ Dec_Graph_t * pGraph;
+ unsigned uRoot;
+ // get the root node
+ uRoot = (unsigned)Vec_IntEntryLast( vSims );
+ // get the graph if the node looks constant
+ if ( uRoot == 0 )
+ pGraph = Dec_GraphCreateConst0();
+ else if ( uRoot == ~(unsigned)0 )
+ pGraph = Dec_GraphCreateConst1();
+ // check the graph
+ if ( Abc_NodeCheckFull( p, pGraph ) )
+ return pGraph;
+ Dec_GraphFree( pGraph );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detect single non-overlaps.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcSingleVar( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+ Dec_Graph_t * pGraph;
+ unsigned uRoot, uNode;
+ int i;
+
+ Vec_IntClear( vOnes );
+ Vec_IntClear( p->vBinate );
+ uRoot = (unsigned)Vec_IntEntryLast( vSims );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ uNode = (unsigned)Vec_IntEntry( vSims, i );
+ if ( uRoot == uNode || uRoot == ~uNode )
+ {
+ pGraph = Dec_GraphCreate( 1 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, i );
+ Dec_GraphSetRoot( pGraph, Dec_IntToEdge( (int)(uRoot == ~uNode) ) );
+ // check the graph
+ if ( Abc_NodeCheckFull( p, pGraph ) )
+ return pGraph;
+ Dec_GraphFree( pGraph );
+ }
+ if ( (uRoot & uNode) == 0 )
+ Vec_IntPush( vOnes, i << 1 );
+ else if ( (uRoot & ~uNode) == 0 )
+ Vec_IntPush( vOnes, (i << 1) + 1 );
+ else
+ Vec_IntPush( p->vBinate, i );
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detect single non-overlaps.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcSingleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eNode0, eNode1, eRoot;
+ unsigned uRoot;
+ int i, k;
+ uRoot = (unsigned)Vec_IntEntryLast( vSims );
+ for ( i = 0; i < vOnes->nSize; i++ )
+ for ( k = i+1; k < vOnes->nSize; k++ )
+ if ( ~uRoot == ((unsigned)vOnes->pArray[i] | (unsigned)vOnes->pArray[k]) )
+ {
+ eNode0 = Dec_IntToEdge( vOnes->pArray[i] ^ 1 );
+ eNode1 = Dec_IntToEdge( vOnes->pArray[k] ^ 1 );
+ pGraph = Dec_GraphCreate( 2 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, eNode0.Node );
+ Dec_GraphNode( pGraph, 1 )->pFunc = Vec_PtrEntry( p->vDecs, eNode1.Node );
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( Abc_NodeCheckFull( p, pGraph ) )
+ return pGraph;
+ Dec_GraphFree( pGraph );
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detect single non-overlaps.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeMffcDoubleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes )
+{
+// Dec_Graph_t * pGraph;
+// unsigned uRoot, uNode;
+// int i;
+
+
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates resubstution of one cut.]
+
+ Description [Returns the graph to add if any.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeResubEval( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+ Dec_Graph_t * pGraph;
+ int nNodesSaved;
+
+ // collect the nodes in the cut
+ if ( !Abc_Abc_NodeResubCollectDivs( p, pRoot, pCut ) )
+ return NULL;
+
+ // label MFFC and count its size
+ nNodesSaved = Abc_NodeResubMffc( p, p->vDecs, pCut->nLeaves, pRoot );
+ assert( nNodesSaved > 0 );
+
+ // simulate MFFC
+ Abc_NodeMffcSimulate( p->vDecs, pCut->nLeaves, p->vRands, p->vSims );
+
+ // check for constant output
+ pGraph = Abc_NodeMffcConstants( p, p->vSims );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+
+ // check for one literal (fill up the ones array)
+ pGraph = Abc_NodeMffcSingleVar( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+ if ( nNodesSaved == 1 )
+ return NULL;
+
+ // look for one node
+ pGraph = Abc_NodeMffcSingleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved - 1;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+ if ( nNodesSaved == 2 )
+ return NULL;
+
+ // look for two nodes
+ pGraph = Abc_NodeMffcDoubleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved - 2;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+ if ( nNodesSaved == 3 )
+ return NULL;
+/*
+ // look for MUX/EXOR
+ pGraph = Abc_NodeMffcMuxNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved );
+ if ( pGraph )
+ {
+ p->nNodesGained += nNodesSaved - 1;
+ p->nNodesRestructured++;
+ return pGraph;
+ }
+*/
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resubstution.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList )
+{
+ Dec_Graph_t * pGraph, * pGraphBest = NULL;
+ Cut_Cut_t * pCut;
+ int nCuts;
+ p->nNodesConsidered++;
+
+ // count the number of cuts with four inputs or more
+ nCuts = 0;
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ nCuts += (int)(pCut->nLeaves > 3);
+ printf( "-----------------------------------\n" );
+ printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts );
+
+ // go through the interesting cuts
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ {
+ if ( pCut->nLeaves < 4 )
+ continue;
+ pGraph = Abc_NodeResubEval( p, pNode, pCut );
+ if ( pGraph == NULL )
+ continue;
+ if ( !pGraphBest || Dec_GraphNodeNum(pGraph) < Dec_GraphNodeNum(pGraphBest) )
+ {
+ if ( pGraphBest )
+ Dec_GraphFree(pGraphBest);
+ pGraphBest = pGraph;
+ }
+ else
+ Dec_GraphFree(pGraph);
+ }
+ return pGraphBest;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c
new file mode 100644
index 00000000..309c328d
--- /dev/null
+++ b/src/base/abci/abcResub.c
@@ -0,0 +1,1951 @@
+/**CFile****************************************************************
+
+ FileName [abcResub.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Resubstitution manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_RS_DIV1_MAX 150 // the max number of divisors to consider
+#define ABC_RS_DIV2_MAX 500 // the max number of pair-wise divisors to consider
+
+typedef struct Abc_ManRes_t_ Abc_ManRes_t;
+struct Abc_ManRes_t_
+{
+ // paramers
+ int nLeavesMax; // the max number of leaves in the cone
+ int nDivsMax; // the max number of divisors in the cone
+ // representation of the cone
+ Abc_Obj_t * pRoot; // the root of the cone
+ int nLeaves; // the number of leaves
+ int nDivs; // the number of all divisor (including leaves)
+ int nMffc; // the size of MFFC
+ int nLastGain; // the gain the number of nodes
+ Vec_Ptr_t * vDivs; // the divisors
+ // representation of the simulation info
+ int nBits; // the number of simulation bits
+ int nWords; // the number of unsigneds for siminfo
+ Vec_Ptr_t * vSims; // simulation info
+ unsigned * pInfo; // pointer to simulation info
+ // observability don't-cares
+ unsigned * pCareSet;
+ // internal divisor storage
+ Vec_Ptr_t * vDivs1UP; // the single-node unate divisors
+ Vec_Ptr_t * vDivs1UN; // the single-node unate divisors
+ Vec_Ptr_t * vDivs1B; // the single-node binate divisors
+ Vec_Ptr_t * vDivs2UP0; // the double-node unate divisors
+ Vec_Ptr_t * vDivs2UP1; // the double-node unate divisors
+ Vec_Ptr_t * vDivs2UN0; // the double-node unate divisors
+ Vec_Ptr_t * vDivs2UN1; // the double-node unate divisors
+ // other data
+ Vec_Ptr_t * vTemp; // temporary array of nodes
+ // runtime statistics
+ int timeCut;
+ int timeTruth;
+ int timeRes;
+ int timeDiv;
+ int timeMffc;
+ int timeSim;
+ int timeRes1;
+ int timeResD;
+ int timeRes2;
+ int timeRes3;
+ int timeNtk;
+ int timeTotal;
+ // improvement statistics
+ int nUsedNodeC;
+ int nUsedNode0;
+ int nUsedNode1Or;
+ int nUsedNode1And;
+ int nUsedNode2Or;
+ int nUsedNode2And;
+ int nUsedNode2OrAnd;
+ int nUsedNode2AndOr;
+ int nUsedNode3OrAnd;
+ int nUsedNode3AndOr;
+ int nUsedNodeTotal;
+ int nTotalDivs;
+ int nTotalLeaves;
+ int nTotalGain;
+ int nNodesBeg;
+ int nNodesEnd;
+};
+
+// external procedures
+static Abc_ManRes_t* Abc_ManResubStart( int nLeavesMax, int nDivsMax );
+static void Abc_ManResubStop( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, int fVerbose );
+static void Abc_ManResubCleanup( Abc_ManRes_t * p );
+static void Abc_ManResubPrint( Abc_ManRes_t * p );
+
+// other procedures
+static int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required );
+static void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords );
+static void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
+
+static void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required );
+static void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p );
+static Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required );
+static Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required );
+
+static Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax );
+static int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves );
+
+// don't-care manager
+extern void * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose );
+extern void Abc_NtkDontCareClear( void * p );
+extern void Abc_NtkDontCareFree( void * p );
+extern int Abc_NtkDontCareCompute( void * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth );
+
+extern int s_ResubTime;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental resynthesis of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_ManRes_t * pManRes;
+ Abc_ManCut_t * pManCut;
+ void * pManOdc = NULL;
+ Dec_Graph_t * pFForm;
+ Vec_Ptr_t * vLeaves;
+ Abc_Obj_t * pNode;
+ int clk, clkStart = clock();
+ int i, nNodes;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // cleanup the AIG
+ Abc_AigCleanup(pNtk->pManFunc);
+ // start the managers
+ pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 );
+ pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX );
+ if ( nLevelsOdc > 0 )
+ pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose );
+
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk, 0 );
+
+ if ( Abc_NtkLatchNum(pNtk) )
+ Abc_NtkForEachLatch(pNtk, pNode, i)
+ pNode->pNext = pNode->pData;
+
+ // resynthesize each node once
+ pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk);
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // skip the constant node
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
+ continue;
+ // skip the nodes with many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+
+ // compute a reconvergence-driven cut
+clk = clock();
+ vLeaves = Abc_NodeFindCut( pManCut, pNode, 0 );
+// vLeaves = Abc_CutFactorLarge( pNode, nCutMax );
+pManRes->timeCut += clock() - clk;
+/*
+ if ( fVerbose && vLeaves )
+ printf( "Node %6d : Leaves = %3d. Volume = %3d.\n", pNode->Id, Vec_PtrSize(vLeaves), Abc_CutVolumeCheck(pNode, vLeaves) );
+ if ( vLeaves == NULL )
+ continue;
+*/
+ // get the don't-cares
+ if ( pManOdc )
+ {
+clk = clock();
+ Abc_NtkDontCareClear( pManOdc );
+ Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet );
+pManRes->timeTruth += clock() - clk;
+ }
+
+ // evaluate this cut
+clk = clock();
+ pFForm = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose );
+// Vec_PtrFree( vLeaves );
+// Abc_ManResubCleanup( pManRes );
+pManRes->timeRes += clock() - clk;
+ if ( pFForm == NULL )
+ continue;
+ pManRes->nTotalGain += pManRes->nLastGain;
+/*
+ if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 )
+ {
+ printf( "%6d : L = %2d. V = %2d. Mffc = %2d. Divs = %3d. Up = %3d. Un = %3d. B = %3d.\n",
+ pNode->Id, pManRes->nLeaves, Abc_CutVolumeCheck(pNode, vLeaves), pManRes->nMffc, pManRes->nDivs,
+ pManRes->vDivs1UP->nSize, pManRes->vDivs1UN->nSize, pManRes->vDivs1B->nSize );
+ Abc_ManResubPrintDivs( pManRes, pNode, vLeaves );
+ }
+*/
+ // acceptable replacement found, update the graph
+clk = clock();
+ Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRes->nLastGain );
+pManRes->timeNtk += clock() - clk;
+ Dec_GraphFree( pFForm );
+ }
+ Extra_ProgressBarStop( pProgress );
+pManRes->timeTotal = clock() - clkStart;
+ pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk);
+
+ // print statistics
+ if ( fVerbose )
+ Abc_ManResubPrint( pManRes );
+
+ // delete the managers
+ Abc_ManResubStop( pManRes );
+ Abc_NtkManCutStop( pManCut );
+ if ( pManOdc ) Abc_NtkDontCareFree( pManOdc );
+
+ // clean the data field
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ pNode->pData = NULL;
+
+ if ( Abc_NtkLatchNum(pNtk) )
+ Abc_NtkForEachLatch(pNtk, pNode, i)
+ pNode->pData = pNode->pNext, pNode->pNext = NULL;
+
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkLevel( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRefactor: The network check has failed.\n" );
+ return 0;
+ }
+s_ResubTime = clock() - clkStart;
+ return 1;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManRes_t * Abc_ManResubStart( int nLeavesMax, int nDivsMax )
+{
+ Abc_ManRes_t * p;
+ unsigned * pData;
+ int i, k;
+ assert( sizeof(unsigned) == 4 );
+ p = ALLOC( Abc_ManRes_t, 1 );
+ memset( p, 0, sizeof(Abc_ManRes_t) );
+ p->nLeavesMax = nLeavesMax;
+ p->nDivsMax = nDivsMax;
+ p->vDivs = Vec_PtrAlloc( p->nDivsMax );
+ // allocate simulation info
+ p->nBits = (1 << p->nLeavesMax);
+ p->nWords = (p->nBits <= 32)? 1 : (p->nBits / 32);
+ p->pInfo = ALLOC( unsigned, p->nWords * (p->nDivsMax + 1) );
+ memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nLeavesMax );
+ p->vSims = Vec_PtrAlloc( p->nDivsMax );
+ for ( i = 0; i < p->nDivsMax; i++ )
+ Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords );
+ // assign the care set
+ p->pCareSet = p->pInfo + p->nDivsMax * p->nWords;
+ Abc_InfoFill( p->pCareSet, p->nWords );
+ // set elementary truth tables
+ for ( k = 0; k < p->nLeavesMax; k++ )
+ {
+ pData = p->vSims->pArray[k];
+ for ( i = 0; i < p->nBits; i++ )
+ if ( i & (1 << k) )
+ pData[i>>5] |= (1 << (i&31));
+ }
+ // create the remaining divisors
+ p->vDivs1UP = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs1UN = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs1B = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2UP0 = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2UP1 = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2UN0 = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2UN1 = Vec_PtrAlloc( p->nDivsMax );
+ p->vTemp = Vec_PtrAlloc( p->nDivsMax );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubStop( Abc_ManRes_t * p )
+{
+ Vec_PtrFree( p->vDivs );
+ Vec_PtrFree( p->vSims );
+ Vec_PtrFree( p->vDivs1UP );
+ Vec_PtrFree( p->vDivs1UN );
+ Vec_PtrFree( p->vDivs1B );
+ Vec_PtrFree( p->vDivs2UP0 );
+ Vec_PtrFree( p->vDivs2UP1 );
+ Vec_PtrFree( p->vDivs2UN0 );
+ Vec_PtrFree( p->vDivs2UN1 );
+ Vec_PtrFree( p->vTemp );
+ free( p->pInfo );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubPrint( Abc_ManRes_t * p )
+{
+ printf( "Used constants = %6d. ", p->nUsedNodeC ); PRT( "Cuts ", p->timeCut );
+ printf( "Used replacements = %6d. ", p->nUsedNode0 ); PRT( "Resub ", p->timeRes );
+ printf( "Used single ORs = %6d. ", p->nUsedNode1Or ); PRT( " Div ", p->timeDiv );
+ printf( "Used single ANDs = %6d. ", p->nUsedNode1And ); PRT( " Mffc ", p->timeMffc );
+ printf( "Used double ORs = %6d. ", p->nUsedNode2Or ); PRT( " Sim ", p->timeSim );
+ printf( "Used double ANDs = %6d. ", p->nUsedNode2And ); PRT( " 1 ", p->timeRes1 );
+ printf( "Used OR-AND = %6d. ", p->nUsedNode2OrAnd ); PRT( " D ", p->timeResD );
+ printf( "Used AND-OR = %6d. ", p->nUsedNode2AndOr ); PRT( " 2 ", p->timeRes2 );
+ printf( "Used OR-2ANDs = %6d. ", p->nUsedNode3OrAnd ); PRT( "Truth ", p->timeTruth ); //PRT( " 3 ", p->timeRes3 );
+ printf( "Used AND-2ORs = %6d. ", p->nUsedNode3AndOr ); PRT( "AIG ", p->timeNtk );
+ printf( "TOTAL = %6d. ", p->nUsedNodeC +
+ p->nUsedNode0 +
+ p->nUsedNode1Or +
+ p->nUsedNode1And +
+ p->nUsedNode2Or +
+ p->nUsedNode2And +
+ p->nUsedNode2OrAnd +
+ p->nUsedNode2AndOr +
+ p->nUsedNode3OrAnd +
+ p->nUsedNode3AndOr
+ ); PRT( "TOTAL ", p->timeTotal );
+ printf( "Total leaves = %8d.\n", p->nTotalLeaves );
+ printf( "Total divisors = %8d.\n", p->nTotalDivs );
+// printf( "Total gain = %8d.\n", p->nTotalGain );
+ printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubCollectDivs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vInternal )
+{
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent(pNode);
+ // collect the fanins
+ Abc_ManResubCollectDivs_rec( Abc_ObjFanin0(pNode), vInternal );
+ Abc_ManResubCollectDivs_rec( Abc_ObjFanin1(pNode), vInternal );
+ // collect the internal node
+ if ( pNode->fMarkA == 0 )
+ Vec_PtrPush( vInternal, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required )
+{
+ Abc_Obj_t * pNode, * pFanout;
+ int i, k, Limit, Counter;
+
+ Vec_PtrClear( p->vDivs1UP );
+ Vec_PtrClear( p->vDivs1UN );
+ Vec_PtrClear( p->vDivs1B );
+
+ // add the leaves of the cuts to the divisors
+ Vec_PtrClear( p->vDivs );
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ {
+ Vec_PtrPush( p->vDivs, pNode );
+ Abc_NodeSetTravIdCurrent( pNode );
+ }
+
+ // mark nodes in the MFFC
+ Vec_PtrForEachEntry( p->vTemp, pNode, i )
+ pNode->fMarkA = 1;
+ // collect the cone (without MFFC)
+ Abc_ManResubCollectDivs_rec( pRoot, p->vDivs );
+ // unmark the current MFFC
+ Vec_PtrForEachEntry( p->vTemp, pNode, i )
+ pNode->fMarkA = 0;
+
+ // check if the number of divisors is not exceeded
+ if ( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp) >= Vec_PtrSize(p->vSims) - p->nLeavesMax )
+ return 0;
+
+ // get the number of divisors to collect
+ Limit = Vec_PtrSize(p->vSims) - p->nLeavesMax - (Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp));
+
+ // explore the fanouts, which are not in the MFFC
+ Counter = 0;
+ Vec_PtrForEachEntry( p->vDivs, pNode, i )
+ {
+ if ( Abc_ObjFanoutNum(pNode) > 100 )
+ {
+// printf( "%d ", Abc_ObjFanoutNum(pNode) );
+ continue;
+ }
+ // if the fanout has both fanins in the set, add it
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsCo(pFanout) || (int)pFanout->Level > Required )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) )
+ {
+ if ( Abc_ObjFanin0(pFanout) == pRoot || Abc_ObjFanin1(pFanout) == pRoot )
+ continue;
+ Vec_PtrPush( p->vDivs, pFanout );
+ Abc_NodeSetTravIdCurrent( pFanout );
+ // quit computing divisors if there is too many of them
+ if ( ++Counter == Limit )
+ goto Quits;
+ }
+ }
+ }
+
+Quits :
+ // get the number of divisors
+ p->nDivs = Vec_PtrSize(p->vDivs);
+
+ // add the nodes in the MFFC
+ Vec_PtrForEachEntry( p->vTemp, pNode, i )
+ Vec_PtrPush( p->vDivs, pNode );
+ assert( pRoot == Vec_PtrEntryLast(p->vDivs) );
+
+ assert( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) <= Vec_PtrSize(p->vSims) - p->nLeavesMax );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pFanin, * pNode;
+ int i, k;
+ // print the nodes
+ Vec_PtrForEachEntry( p->vDivs, pNode, i )
+ {
+ if ( i < Vec_PtrSize(vLeaves) )
+ {
+ printf( "%6d : %c\n", pNode->Id, 'a'+i );
+ continue;
+ }
+ printf( "%6d : %2d = ", pNode->Id, i );
+ // find the first fanin
+ Vec_PtrForEachEntry( p->vDivs, pFanin, k )
+ if ( Abc_ObjFanin0(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+ // find the second fanin
+ Vec_PtrForEachEntry( p->vDivs, pFanin, k )
+ if ( Abc_ObjFanin1(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+ if ( pNode == pRoot )
+ printf( " root" );
+ printf( "\n" );
+ }
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData0, * puData1, * puData;
+ int i, k;
+ assert( Vec_PtrSize(vDivs) - nLeaves <= Vec_PtrSize(vSims) - nLeavesMax );
+ // simulate
+ Vec_PtrForEachEntry( vDivs, pObj, i )
+ {
+ if ( i < nLeaves )
+ { // initialize the leaf
+ pObj->pData = Vec_PtrEntry( vSims, i );
+ continue;
+ }
+ // set storage for the node's simulation info
+ pObj->pData = Vec_PtrEntry( vSims, i - nLeaves + nLeavesMax );
+ // get pointer to the simulation info
+ puData = pObj->pData;
+ puData0 = Abc_ObjFanin0(pObj)->pData;
+ puData1 = Abc_ObjFanin1(pObj)->pData;
+ // simulate
+ if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData0[k] & ~puData1[k];
+ else if ( Abc_ObjFaninC0(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData0[k] & puData1[k];
+ else if ( Abc_ObjFaninC1(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = puData0[k] & ~puData1[k];
+ else
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = puData0[k] & puData1[k];
+ }
+ // normalize
+ Vec_PtrForEachEntry( vDivs, pObj, i )
+ {
+ puData = pObj->pData;
+ pObj->fPhase = (puData[0] & 1);
+ if ( pObj->fPhase )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData[k];
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit0( Abc_Obj_t * pRoot, Abc_Obj_t * pObj )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot;
+ pGraph = Dec_GraphCreate( 1 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = pObj;
+ eRoot = Dec_EdgeCreate( 0, pObj->fPhase );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit1( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, int fOrGate )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, eNode0, eNode1;
+ assert( pObj0 != pObj1 );
+ assert( !Abc_ObjIsComplement(pObj0) );
+ assert( !Abc_ObjIsComplement(pObj1) );
+ pGraph = Dec_GraphCreate( 2 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = pObj0;
+ Dec_GraphNode( pGraph, 1 )->pFunc = pObj1;
+ eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase );
+ if ( fOrGate )
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ else
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit21( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, eNode0, eNode1, eNode2;
+ assert( pObj0 != pObj1 );
+ assert( !Abc_ObjIsComplement(pObj0) );
+ assert( !Abc_ObjIsComplement(pObj1) );
+ assert( !Abc_ObjIsComplement(pObj2) );
+ pGraph = Dec_GraphCreate( 3 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = pObj0;
+ Dec_GraphNode( pGraph, 1 )->pFunc = pObj1;
+ Dec_GraphNode( pGraph, 2 )->pFunc = pObj2;
+ eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase );
+ eNode2 = Dec_EdgeCreate( 2, pObj2->fPhase );
+ if ( fOrGate )
+ {
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode2, eRoot );
+ }
+ else
+ {
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode2, eRoot );
+ }
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit2( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, ePrev, eNode0, eNode1, eNode2;
+ assert( pObj0 != pObj1 );
+ assert( pObj0 != pObj2 );
+ assert( pObj1 != pObj2 );
+ assert( !Abc_ObjIsComplement(pObj0) );
+ pGraph = Dec_GraphCreate( 3 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0);
+ Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1);
+ Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2);
+ eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase );
+ if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+ {
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase );
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+ ePrev = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 );
+ }
+ else
+ {
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) );
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+ ePrev = Dec_GraphAddNodeAnd( pGraph, eNode1, eNode2 );
+ }
+ if ( fOrGate )
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, ePrev );
+ else
+ eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, ePrev );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit3( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, Abc_Obj_t * pObj3, int fOrGate )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, ePrev0, ePrev1, eNode0, eNode1, eNode2, eNode3;
+ assert( pObj0 != pObj1 );
+ assert( pObj2 != pObj3 );
+ pGraph = Dec_GraphCreate( 4 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0);
+ Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1);
+ Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2);
+ Dec_GraphNode( pGraph, 3 )->pFunc = Abc_ObjRegular(pObj3);
+ if ( Abc_ObjIsComplement(pObj0) && Abc_ObjIsComplement(pObj1) )
+ {
+ eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase );
+ ePrev0 = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) )
+ {
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase );
+ ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 );
+ }
+ else
+ {
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) );
+ ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 );
+ }
+ }
+ else
+ {
+ eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ^ Abc_ObjIsComplement(pObj0) );
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) );
+ ePrev0 = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) )
+ {
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase );
+ ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 );
+ }
+ else
+ {
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) );
+ ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 );
+ }
+ }
+ if ( fOrGate )
+ eRoot = Dec_GraphAddNodeOr( pGraph, ePrev0, ePrev1 );
+ else
+ eRoot = Dec_GraphAddNodeAnd( pGraph, ePrev0, ePrev1 );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives single-node unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData, * puDataR;
+ int i, w;
+ Vec_PtrClear( p->vDivs1UP );
+ Vec_PtrClear( p->vDivs1UN );
+ Vec_PtrClear( p->vDivs1B );
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs )
+ {
+ if ( (int)pObj->Level > Required - 1 )
+ continue;
+
+ puData = pObj->pData;
+ // check positive containment
+ for ( w = 0; w < p->nWords; w++ )
+// if ( puData[w] & ~puDataR[w] )
+ if ( puData[w] & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs1UP, pObj );
+ continue;
+ }
+ // check negative containment
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~puData[w] & puDataR[w] )
+ if ( ~puData[w] & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs1UN, pObj );
+ continue;
+ }
+ // add the node to binates
+ Vec_PtrPush( p->vDivs1B, pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives double-node unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1;
+ unsigned * puData0, * puData1, * puDataR;
+ int i, k, w;
+ Vec_PtrClear( p->vDivs2UP0 );
+ Vec_PtrClear( p->vDivs2UP1 );
+ Vec_PtrClear( p->vDivs2UN0 );
+ Vec_PtrClear( p->vDivs2UN1 );
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntry( p->vDivs1B, pObj0, i )
+ {
+ if ( (int)pObj0->Level > Required - 2 )
+ continue;
+
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1B, pObj1, k, i + 1 )
+ {
+ if ( (int)pObj1->Level > Required - 2 )
+ continue;
+
+ puData1 = pObj1->pData;
+
+ if ( Vec_PtrSize(p->vDivs2UP0) < ABC_RS_DIV2_MAX )
+ {
+ // get positive unate divisors
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & puData1[w]) & ~puDataR[w] )
+ if ( (puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UP0, pObj0 );
+ Vec_PtrPush( p->vDivs2UP1, pObj1 );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (~puData0[w] & puData1[w]) & ~puDataR[w] )
+ if ( (~puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2UP1, pObj1 );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] )
+ if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UP0, pObj0 );
+ Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | puData1[w]) & ~puDataR[w] )
+ if ( (puData0[w] | puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) );
+ }
+ }
+
+ if ( Vec_PtrSize(p->vDivs2UN0) < ABC_RS_DIV2_MAX )
+ {
+ // get negative unate divisors
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~(puData0[w] & puData1[w]) & puDataR[w] )
+ if ( ~(puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UN0, pObj0 );
+ Vec_PtrPush( p->vDivs2UN1, pObj1 );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~(~puData0[w] & puData1[w]) & puDataR[w] )
+ if ( ~(~puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2UN1, pObj1 );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] )
+ if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UN0, pObj0 );
+ Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) );
+ }
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ~(puData0[w] | puData1[w]) & puDataR[w] )
+ if ( ~(puData0[w] | puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) );
+ }
+ }
+ }
+ }
+// printf( "%d %d ", Vec_PtrSize(p->vDivs2UP0), Vec_PtrSize(p->vDivs2UN0) );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p )
+{
+ Dec_Graph_t * pGraph;
+ unsigned * upData;
+ int w;
+ upData = p->pRoot->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( upData[w] )
+ if ( upData[w] & p->pCareSet[w] ) // care set
+ break;
+ if ( w != p->nWords )
+ return NULL;
+ // get constant node graph
+ if ( p->pRoot->fPhase )
+ pGraph = Dec_GraphCreateConst1();
+ else
+ pGraph = Dec_GraphCreateConst0();
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData, * puDataR;
+ int i, w;
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs )
+ {
+ puData = pObj->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( puData[w] != puDataR[w] )
+ if ( (puData[w] ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ return Abc_ManResubQuit0( p->pRoot, pObj );
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1;
+ unsigned * puData0, * puData1, * puDataR;
+ int i, k, w;
+ puDataR = p->pRoot->pData;
+ // check positive unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | puData1[w]) != puDataR[w] )
+ if ( ((puData0[w] | puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ p->nUsedNode1Or++;
+ return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 1 );
+ }
+ }
+ }
+ // check negative unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & puData1[w]) != puDataR[w] )
+ if ( ((puData0[w] & puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ p->nUsedNode1And++;
+ return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 0 );
+ }
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObjMax, * pObjMin0, * pObjMin1;
+ unsigned * puData0, * puData1, * puData2, * puDataR;
+ int i, k, j, w, LevelMax;
+ puDataR = p->pRoot->pData;
+ // check positive unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UP, pObj2, j, k + 1 )
+ {
+ puData2 = pObj2->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | puData1[w] | puData2[w]) != puDataR[w] )
+ if ( ((puData0[w] | puData1[w] | puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) );
+ assert( LevelMax <= Required - 1 );
+
+ pObjMax = NULL;
+ if ( (int)pObj0->Level == LevelMax )
+ pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2;
+ if ( (int)pObj1->Level == LevelMax )
+ {
+ if ( pObjMax ) continue;
+ pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2;
+ }
+ if ( (int)pObj2->Level == LevelMax )
+ {
+ if ( pObjMax ) continue;
+ pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1;
+ }
+
+ p->nUsedNode2Or++;
+ return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 1 );
+ }
+ }
+ }
+ }
+ // check negative unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1UN, pObj2, j, k + 1 )
+ {
+ puData2 = pObj2->pData;
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & puData1[w] & puData2[w]) != puDataR[w] )
+ if ( ((puData0[w] & puData1[w] & puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ if ( w == p->nWords )
+ {
+ LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) );
+ assert( LevelMax <= Required - 1 );
+
+ pObjMax = NULL;
+ if ( (int)pObj0->Level == LevelMax )
+ pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2;
+ if ( (int)pObj1->Level == LevelMax )
+ {
+ if ( pObjMax ) continue;
+ pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2;
+ }
+ if ( (int)pObj2->Level == LevelMax )
+ {
+ if ( pObjMax ) continue;
+ pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1;
+ }
+
+ p->nUsedNode2And++;
+ return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 0 );
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1, * pObj2;
+ unsigned * puData0, * puData1, * puData2, * puDataR;
+ int i, k, w;
+ puDataR = p->pRoot->pData;
+ // check positive unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntry( p->vDivs2UP0, pObj1, k )
+ {
+ pObj2 = Vec_PtrEntry( p->vDivs2UP1, k );
+
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | (puData1[w] | puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] | (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else if ( Abc_ObjIsComplement(pObj1) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | (~puData1[w] & puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] | (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else if ( Abc_ObjIsComplement(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | (puData1[w] & ~puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] | (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] | (puData1[w] & puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] | (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ if ( w == p->nWords )
+ {
+ p->nUsedNode2OrAnd++;
+ return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 1 );
+ }
+ }
+ }
+ // check negative unate divisors
+ Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntry( p->vDivs2UN0, pObj1, k )
+ {
+ pObj2 = Vec_PtrEntry( p->vDivs2UN1, k );
+
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & (puData1[w] | puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] & (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else if ( Abc_ObjIsComplement(pObj1) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & (~puData1[w] & puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] & (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else if ( Abc_ObjIsComplement(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & (puData1[w] & ~puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] & (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ else
+ {
+ for ( w = 0; w < p->nWords; w++ )
+// if ( (puData0[w] & (puData1[w] & puData2[w])) != puDataR[w] )
+ if ( ((puData0[w] & (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ }
+ if ( w == p->nWords )
+ {
+ p->nUsedNode2AndOr++;
+ return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 0 );
+ }
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required )
+{
+ Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObj3;
+ unsigned * puData0, * puData1, * puData2, * puData3, * puDataR;
+ int i, k, w, Flag;
+ puDataR = p->pRoot->pData;
+ // check positive unate divisors
+ Vec_PtrForEachEntry( p->vDivs2UP0, pObj0, i )
+ {
+ pObj1 = Vec_PtrEntry( p->vDivs2UP1, i );
+ puData0 = Abc_ObjRegular(pObj0)->pData;
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2);
+
+ Vec_PtrForEachEntryStart( p->vDivs2UP0, pObj2, k, i + 1 )
+ {
+ pObj3 = Vec_PtrEntry( p->vDivs2UP1, k );
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ puData3 = Abc_ObjRegular(pObj3)->pData;
+
+ Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3);
+ assert( Flag < 16 );
+ switch( Flag )
+ {
+ case 0: // 0000
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 1: // 0001
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 2: // 0010
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 3: // 0011
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+
+ case 4: // 0100
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 5: // 0101
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 6: // 0110
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 7: // 0111
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+
+ case 8: // 1000
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 9: // 1001
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ if ( (((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 10: // 1010
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 11: // 1011
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+ if ( (((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+
+ case 12: // 1100
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set
+ break;
+ break;
+ case 13: // 1101
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+ break;
+ break;
+ case 14: // 1110
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+ break;
+ break;
+ case 15: // 1111
+ for ( w = 0; w < p->nWords; w++ )
+// if ( ((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] )
+ if ( (((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] )
+ break;
+ break;
+
+ }
+ if ( w == p->nWords )
+ {
+ p->nUsedNode3OrAnd++;
+ return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 1 );
+ }
+ }
+ }
+/*
+ // check negative unate divisors
+ Vec_PtrForEachEntry( p->vDivs2UN0, pObj0, i )
+ {
+ pObj1 = Vec_PtrEntry( p->vDivs2UN1, i );
+ puData0 = Abc_ObjRegular(pObj0)->pData;
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2);
+
+ Vec_PtrForEachEntryStart( p->vDivs2UN0, pObj2, k, i + 1 )
+ {
+ pObj3 = Vec_PtrEntry( p->vDivs2UN1, k );
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ puData3 = Abc_ObjRegular(pObj3)->pData;
+
+ Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3);
+ assert( Flag < 16 );
+ switch( Flag )
+ {
+ case 0: // 0000
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 1: // 0001
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 2: // 0010
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 3: // 0011
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+ break;
+ break;
+
+ case 4: // 0100
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 5: // 0101
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 6: // 0110
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 7: // 0111
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+ break;
+ break;
+
+ case 8: // 1000
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 9: // 1001
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 10: // 1010
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 11: // 1011
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+ break;
+ break;
+
+ case 12: // 1100
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] | puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 13: // 1101
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] | puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 14: // 1110
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] | puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ break;
+ case 15: // 1111
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] | puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] )
+ break;
+ break;
+
+ }
+ if ( w == p->nWords )
+ {
+ p->nUsedNode3AndOr++;
+ return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 0 );
+ }
+ }
+ }
+*/
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManResubCleanup( Abc_ManRes_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( p->vDivs, pObj, i )
+ pObj->pData = NULL;
+ Vec_PtrClear( p->vDivs );
+ p->pRoot = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates resubstution of one cut.]
+
+ Description [Returns the graph to add if any.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, bool fVerbose )
+{
+ extern int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside );
+ Dec_Graph_t * pGraph;
+ int Required;
+ int clk;
+
+ Required = fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY;
+
+ assert( nSteps >= 0 );
+ assert( nSteps <= 3 );
+ p->pRoot = pRoot;
+ p->nLeaves = Vec_PtrSize(vLeaves);
+ p->nLastGain = -1;
+
+ // collect the MFFC
+clk = clock();
+ p->nMffc = Abc_NodeMffsInside( pRoot, vLeaves, p->vTemp );
+p->timeMffc += clock() - clk;
+ assert( p->nMffc > 0 );
+
+ // collect the divisor nodes
+clk = clock();
+ if ( !Abc_ManResubCollectDivs( p, pRoot, vLeaves, Required ) )
+ return NULL;
+ p->timeDiv += clock() - clk;
+
+ p->nTotalDivs += p->nDivs;
+ p->nTotalLeaves += p->nLeaves;
+
+ // simulate the nodes
+clk = clock();
+ Abc_ManResubSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords );
+p->timeSim += clock() - clk;
+
+clk = clock();
+ // consider constants
+ if ( pGraph = Abc_ManResubQuit( p ) )
+ {
+ p->nUsedNodeC++;
+ p->nLastGain = p->nMffc;
+ return pGraph;
+ }
+
+ // consider equal nodes
+ if ( pGraph = Abc_ManResubDivs0( p ) )
+ {
+p->timeRes1 += clock() - clk;
+ p->nUsedNode0++;
+ p->nLastGain = p->nMffc;
+ return pGraph;
+ }
+ if ( nSteps == 0 || p->nMffc == 1 )
+ {
+p->timeRes1 += clock() - clk;
+ return NULL;
+ }
+
+ // get the one level divisors
+ Abc_ManResubDivsS( p, Required );
+
+ // consider one node
+ if ( pGraph = Abc_ManResubDivs1( p, Required ) )
+ {
+p->timeRes1 += clock() - clk;
+ p->nLastGain = p->nMffc - 1;
+ return pGraph;
+ }
+p->timeRes1 += clock() - clk;
+ if ( nSteps == 1 || p->nMffc == 2 )
+ return NULL;
+
+clk = clock();
+ // consider triples
+ if ( pGraph = Abc_ManResubDivs12( p, Required ) )
+ {
+p->timeRes2 += clock() - clk;
+ p->nLastGain = p->nMffc - 2;
+ return pGraph;
+ }
+p->timeRes2 += clock() - clk;
+
+ // get the two level divisors
+clk = clock();
+ Abc_ManResubDivsD( p, Required );
+p->timeResD += clock() - clk;
+
+ // consider two nodes
+clk = clock();
+ if ( pGraph = Abc_ManResubDivs2( p, Required ) )
+ {
+p->timeRes2 += clock() - clk;
+ p->nLastGain = p->nMffc - 2;
+ return pGraph;
+ }
+p->timeRes2 += clock() - clk;
+ if ( nSteps == 2 || p->nMffc == 3 )
+ return NULL;
+
+ // consider two nodes
+clk = clock();
+ if ( pGraph = Abc_ManResubDivs3( p, Required ) )
+ {
+p->timeRes3 += clock() - clk;
+ p->nLastGain = p->nMffc - 3;
+ return pGraph;
+ }
+p->timeRes3 += clock() - clk;
+ if ( nSteps == 3 || p->nLeavesMax == 4 )
+ return NULL;
+ return NULL;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the volume and checks if the cut is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CutVolumeCheck_rec( Abc_Obj_t * pObj )
+{
+ // quit if the node is visited (or if it is a leaf)
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // report the error
+ if ( Abc_ObjIsCi(pObj) )
+ printf( "Abc_CutVolumeCheck() ERROR: The set of nodes is not a cut!\n" );
+ // count the number of nodes in the leaves
+ return 1 + Abc_CutVolumeCheck_rec( Abc_ObjFanin0(pObj) ) +
+ Abc_CutVolumeCheck_rec( Abc_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the volume and checks if the cut is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the leaves
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // traverse the nodes starting from the given one and count them
+ return Abc_CutVolumeCheck_rec( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the factor cut of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_CutFactor_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+ if ( pObj->fMarkA )
+ return;
+ if ( Abc_ObjIsCi(pObj) || (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) )
+ {
+ Vec_PtrPush( vLeaves, pObj );
+ pObj->fMarkA = 1;
+ return;
+ }
+ Abc_CutFactor_rec( Abc_ObjFanin0(pObj), vLeaves );
+ Abc_CutFactor_rec( Abc_ObjFanin1(pObj), vLeaves );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the factor cut of the node.]
+
+ Description [Factor-cut is the cut at a node in terms of factor-nodes.
+ Factor-nodes are roots of the node trees (MUXes/EXORs are counted as single nodes).
+ Factor-cut is unique for the given node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_CutFactor( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vLeaves;
+ Abc_Obj_t * pObj;
+ int i;
+ assert( !Abc_ObjIsCi(pNode) );
+ vLeaves = Vec_PtrAlloc( 10 );
+ Abc_CutFactor_rec( Abc_ObjFanin0(pNode), vLeaves );
+ Abc_CutFactor_rec( Abc_ObjFanin1(pNode), vLeaves );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->fMarkA = 0;
+ return vLeaves;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cut computation.]
+
+ Description [This cut computation works as follows:
+ It starts with the factor cut at the node. If the factor-cut is large, quit.
+ It supports the set of leaves of the cut under construction and labels all nodes
+ in the cut under construction, including the leaves.
+ It computes the factor-cuts of the leaves and checks if it is easible to add any of them.
+ If it is, it randomly chooses one feasible and continues.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax )
+{
+ Vec_Ptr_t * vLeaves, * vFactors, * vFact, * vNext;
+ Vec_Int_t * vFeasible;
+ Abc_Obj_t * pLeaf, * pTemp;
+ int i, k, Counter, RandLeaf;
+ int BestCut, BestShare;
+ assert( Abc_ObjIsNode(pNode) );
+ // get one factor-cut
+ vLeaves = Abc_CutFactor( pNode );
+ if ( Vec_PtrSize(vLeaves) > nLeavesMax )
+ {
+ Vec_PtrFree(vLeaves);
+ return NULL;
+ }
+ if ( Vec_PtrSize(vLeaves) == nLeavesMax )
+ return vLeaves;
+ // initialize the factor cuts for the leaves
+ vFactors = Vec_PtrAlloc( nLeavesMax );
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ Abc_NodeSetTravIdCurrent( pLeaf );
+ if ( Abc_ObjIsCi(pLeaf) )
+ Vec_PtrPush( vFactors, NULL );
+ else
+ Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) );
+ }
+ // construct larger factor cuts
+ vFeasible = Vec_IntAlloc( nLeavesMax );
+ while ( 1 )
+ {
+ BestCut = -1;
+ // find the next feasible cut to add
+ Vec_IntClear( vFeasible );
+ Vec_PtrForEachEntry( vFactors, vFact, i )
+ {
+ if ( vFact == NULL )
+ continue;
+ // count the number of unmarked leaves of this factor cut
+ Counter = 0;
+ Vec_PtrForEachEntry( vFact, pTemp, k )
+ Counter += !Abc_NodeIsTravIdCurrent(pTemp);
+ // if the number of new leaves is smaller than the diff, it is feasible
+ if ( Counter <= nLeavesMax - Vec_PtrSize(vLeaves) + 1 )
+ {
+ Vec_IntPush( vFeasible, i );
+ if ( BestCut == -1 || BestShare < Vec_PtrSize(vFact) - Counter )
+ BestCut = i, BestShare = Vec_PtrSize(vFact) - Counter;
+ }
+ }
+ // quit if there is no feasible factor cuts
+ if ( Vec_IntSize(vFeasible) == 0 )
+ break;
+ // randomly choose one leaf and get its factor cut
+// RandLeaf = Vec_IntEntry( vFeasible, rand() % Vec_IntSize(vFeasible) );
+ // choose the cut that has most sharing with the other cuts
+ RandLeaf = BestCut;
+
+ pLeaf = Vec_PtrEntry( vLeaves, RandLeaf );
+ vNext = Vec_PtrEntry( vFactors, RandLeaf );
+ // unmark this leaf
+ Abc_NodeSetTravIdPrevious( pLeaf );
+ // remove this cut from the leaves and factor cuts
+ for ( i = RandLeaf; i < Vec_PtrSize(vLeaves)-1; i++ )
+ {
+ Vec_PtrWriteEntry( vLeaves, i, Vec_PtrEntry(vLeaves, i+1) );
+ Vec_PtrWriteEntry( vFactors, i, Vec_PtrEntry(vFactors,i+1) );
+ }
+ Vec_PtrShrink( vLeaves, Vec_PtrSize(vLeaves) -1 );
+ Vec_PtrShrink( vFactors, Vec_PtrSize(vFactors)-1 );
+ // add new leaves, compute their factor cuts
+ Vec_PtrForEachEntry( vNext, pLeaf, i )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pLeaf) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pLeaf );
+ Vec_PtrPush( vLeaves, pLeaf );
+ if ( Abc_ObjIsCi(pLeaf) )
+ Vec_PtrPush( vFactors, NULL );
+ else
+ Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) );
+ }
+ Vec_PtrFree( vNext );
+ assert( Vec_PtrSize(vLeaves) <= nLeavesMax );
+ if ( Vec_PtrSize(vLeaves) == nLeavesMax )
+ break;
+ }
+
+ // remove temporary storage
+ Vec_PtrForEachEntry( vFactors, vFact, i )
+ if ( vFact ) Vec_PtrFree( vFact );
+ Vec_PtrFree( vFactors );
+ Vec_IntFree( vFeasible );
+ return vLeaves;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRewrite.c b/src/base/abci/abcRewrite.c
new file mode 100644
index 00000000..b615f47e
--- /dev/null
+++ b/src/base/abci/abcRewrite.c
@@ -0,0 +1,414 @@
+/**CFile****************************************************************
+
+ FileName [abcRewrite.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Technology-independent resynthesis of the AIG based on DAG aware rewriting.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRewrite.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "rwr.h"
+#include "dec.h"
+
+/*
+ The ideas realized in this package are inspired by the paper:
+ Per Bjesse, Arne Boralv, "DAG-aware circuit compression for
+ formal verification", Proc. ICCAD 2004, pp. 42-49.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk );
+static void Abc_NodePrintCuts( Abc_Obj_t * pNode );
+static void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves );
+
+extern void Abc_PlaceBegin( Abc_Ntk_t * pNtk );
+extern void Abc_PlaceEnd( Abc_Ntk_t * pNtk );
+extern void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs incremental rewriting of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable )
+{
+ ProgressBar * pProgress;
+ Cut_Man_t * pManCut;
+ Rwr_Man_t * pManRwr;
+ Abc_Obj_t * pNode;
+ Vec_Ptr_t * vAddedCells = NULL, * vUpdatedNets = NULL;
+ Dec_Graph_t * pGraph;
+ int i, nNodes, nGain, fCompl;
+ int clk, clkStart = clock();
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // cleanup the AIG
+ Abc_AigCleanup(pNtk->pManFunc);
+/*
+ {
+ Vec_Vec_t * vParts;
+ vParts = Abc_NtkPartitionSmart( pNtk, 50, 1 );
+ Vec_VecFree( vParts );
+ }
+*/
+
+ // start placement package
+// if ( fPlaceEnable )
+// {
+// Abc_PlaceBegin( pNtk );
+// vAddedCells = Abc_AigUpdateStart( pNtk->pManFunc, &vUpdatedNets );
+// }
+
+ // start the rewriting manager
+ pManRwr = Rwr_ManStart( 0 );
+ if ( pManRwr == NULL )
+ return 0;
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk, 0 );
+ // start the cut manager
+clk = clock();
+ pManCut = Abc_NtkStartCutManForRewrite( pNtk );
+Rwr_ManAddTimeCuts( pManRwr, clock() - clk );
+ pNtk->pManCut = pManCut;
+
+ if ( fVeryVerbose )
+ Rwr_ScoresClean( pManRwr );
+
+ // resynthesize each node once
+ pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk);
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
+ continue;
+ // skip the nodes with many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+
+ // for each cut, try to resynthesize it
+ nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUpdateLevel, fUseZeros, fPlaceEnable );
+ if ( !(nGain > 0 || nGain == 0 && fUseZeros) )
+ continue;
+ // if we end up here, a rewriting step is accepted
+
+ // get hold of the new subgraph to be added to the AIG
+ pGraph = Rwr_ManReadDecs(pManRwr);
+ fCompl = Rwr_ManReadCompl(pManRwr);
+
+ // reset the array of the changed nodes
+ if ( fPlaceEnable )
+ Abc_AigUpdateReset( pNtk->pManFunc );
+
+ // complement the FF if needed
+ if ( fCompl ) Dec_GraphComplement( pGraph );
+clk = clock();
+ Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain );
+Rwr_ManAddTimeUpdate( pManRwr, clock() - clk );
+ if ( fCompl ) Dec_GraphComplement( pGraph );
+
+ // use the array of changed nodes to update placement
+// if ( fPlaceEnable )
+// Abc_PlaceUpdate( vAddedCells, vUpdatedNets );
+ }
+ Extra_ProgressBarStop( pProgress );
+Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart );
+ // print stats
+ pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk);
+ if ( fVerbose )
+ Rwr_ManPrintStats( pManRwr );
+// Rwr_ManPrintStatsFile( pManRwr );
+ if ( fVeryVerbose )
+ Rwr_ScoresReport( pManRwr );
+ // delete the managers
+ Rwr_ManStop( pManRwr );
+ Cut_ManStop( pManCut );
+ pNtk->pManCut = NULL;
+
+ // start placement package
+// if ( fPlaceEnable )
+// {
+// Abc_PlaceEnd( pNtk );
+// Abc_AigUpdateStop( pNtk->pManFunc );
+// }
+
+ // put the nodes into the DFS order and reassign their IDs
+ {
+// int clk = clock();
+ Abc_NtkReassignIds( pNtk );
+// PRT( "time", clock() - clk );
+ }
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkLevel( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRewrite: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk )
+{
+ static Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pManCut;
+ Abc_Obj_t * pObj;
+ int i;
+ // start the cut manager
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = 4; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 250; // the max number of cuts kept at a node
+ pParams->fTruth = 1; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 0; // compute sequential cuts
+ pParams->fDrop = 0; // drop cuts on the fly
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pManCut = Cut_ManStart( pParams );
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( pManCut, pObj->Id );
+ return pManCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the cuts at the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodePrintCuts( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vCuts;
+ Cut_Cut_t * pCut;
+ int k;
+
+ printf( "\nNode %s\n", Abc_ObjName(pNode) );
+ vCuts = (Vec_Ptr_t *)pNode->pCopy;
+ Vec_PtrForEachEntry( vCuts, pCut, k )
+ {
+ Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 );
+ printf( " " );
+ Cut_CutPrint( pCut, 0 );
+ printf( "\n" );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManRewritePrintDivs( Vec_Ptr_t * vDivs, int nLeaves )
+{
+ Abc_Obj_t * pFanin, * pNode, * pRoot;
+ int i, k;
+ pRoot = Vec_PtrEntryLast(vDivs);
+ // print the nodes
+ Vec_PtrForEachEntry( vDivs, pNode, i )
+ {
+ if ( i < nLeaves )
+ {
+ printf( "%6d : %c\n", pNode->Id, 'a'+i );
+ continue;
+ }
+ printf( "%6d : %2d = ", pNode->Id, i );
+ // find the first fanin
+ Vec_PtrForEachEntry( vDivs, pFanin, k )
+ if ( Abc_ObjFanin0(pNode) == pFanin )
+ break;
+ if ( k < nLeaves )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+ // find the second fanin
+ Vec_PtrForEachEntry( vDivs, pFanin, k )
+ if ( Abc_ObjFanin1(pNode) == pFanin )
+ break;
+ if ( k < nLeaves )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+ if ( pNode == pRoot )
+ printf( " root" );
+ printf( "\n" );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManShowCutCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vDivs )
+{
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent(pNode);
+ Abc_ManShowCutCone_rec( Abc_ObjFanin0(pNode), vDivs );
+ Abc_ManShowCutCone_rec( Abc_ObjFanin1(pNode), vDivs );
+ Vec_PtrPush( vDivs, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+ Abc_Ntk_t * pNtk = pNode->pNtk;
+ Abc_Obj_t * pObj;
+ Vec_Ptr_t * vDivs;
+ int i;
+ vDivs = Vec_PtrAlloc( 100 );
+ Abc_NtkIncrementTravId( pNtk );
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pObj) );
+ Vec_PtrPush( vDivs, Abc_ObjRegular(pObj) );
+ }
+ Abc_ManShowCutCone_rec( pNode, vDivs );
+ Abc_ManRewritePrintDivs( vDivs, Vec_PtrSize(vLeaves) );
+ Vec_PtrFree( vDivs );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RwrExpWithCut_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, int fUseA )
+{
+ if ( Vec_PtrFind(vLeaves, pNode) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pNode)) >= 0 )
+ {
+ if ( fUseA )
+ Abc_ObjRegular(pNode)->fMarkA = 1;
+ else
+ Abc_ObjRegular(pNode)->fMarkB = 1;
+ return;
+ }
+ assert( Abc_ObjIsNode(pNode) );
+ Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, fUseA );
+ Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, fUseA );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RwrExpWithCut( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pObj;
+ int i, CountA, CountB;
+ Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, 1 );
+ Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, 0 );
+ CountA = CountB = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ CountA += Abc_ObjRegular(pObj)->fMarkA;
+ CountB += Abc_ObjRegular(pObj)->fMarkB;
+ Abc_ObjRegular(pObj)->fMarkA = 0;
+ Abc_ObjRegular(pObj)->fMarkB = 0;
+ }
+ printf( "(%d,%d:%d) ", CountA, CountB, CountA+CountB-Vec_PtrSize(vLeaves) );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRr.c b/src/base/abci/abcRr.c
new file mode 100644
index 00000000..92adc718
--- /dev/null
+++ b/src/base/abci/abcRr.c
@@ -0,0 +1,999 @@
+/**CFile****************************************************************
+
+ FileName [abcRr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Redundancy removal.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fraig.h"
+#include "sim.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_RRMan_t_ Abc_RRMan_t;
+struct Abc_RRMan_t_
+{
+ // the parameters
+ Abc_Ntk_t * pNtk; // the network
+ int nFaninLevels; // the number of fanin levels
+ int nFanoutLevels; // the number of fanout levels
+ // the node/fanin/fanout
+ Abc_Obj_t * pNode; // the node
+ Abc_Obj_t * pFanin; // the fanin
+ Abc_Obj_t * pFanout; // the fanout
+ // the intermediate cones
+ Vec_Ptr_t * vFaninLeaves; // the leaves of the fanin cone
+ Vec_Ptr_t * vFanoutRoots; // the roots of the fanout cone
+ // the window
+ Vec_Ptr_t * vLeaves; // the leaves of the window
+ Vec_Ptr_t * vCone; // the internal nodes of the window
+ Vec_Ptr_t * vRoots; // the roots of the window
+ Abc_Ntk_t * pWnd; // the window derived for the edge
+ // the miter
+ Abc_Ntk_t * pMiter; // the miter derived from the window
+ Prove_Params_t * pParams; // the miter proving parameters
+ // statistical variables
+ int nNodesOld; // the old number of nodes
+ int nLevelsOld; // the old number of levels
+ int nEdgesTried; // the number of nodes tried
+ int nEdgesRemoved; // the number of nodes proved
+ int timeWindow; // the time to construct the window
+ int timeMiter; // the time to construct the miter
+ int timeProve; // the time to prove the miter
+ int timeUpdate; // the network update time
+ int timeTotal; // the total runtime
+};
+
+static Abc_RRMan_t * Abc_RRManStart();
+static void Abc_RRManStop( Abc_RRMan_t * p );
+static void Abc_RRManPrintStats( Abc_RRMan_t * p );
+static void Abc_RRManClean( Abc_RRMan_t * p );
+static int Abc_NtkRRProve( Abc_RRMan_t * p );
+static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout );
+static int Abc_NtkRRWindow( Abc_RRMan_t * p );
+
+static int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit );
+static int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout );
+static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit );
+static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit );
+static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots );
+
+static void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk );
+static void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Removes stuck-at redundancies.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_RRMan_t * p;
+ Abc_Obj_t * pNode, * pFanin, * pFanout;
+ int i, k, m, nNodes, RetValue, clk, clkTotal = clock();
+ // start the manager
+ p = Abc_RRManStart( nFaninLevels, nFanoutLevels );
+ p->pNtk = pNtk;
+ p->nFaninLevels = nFaninLevels;
+ p->nFanoutLevels = nFanoutLevels;
+ p->nNodesOld = Abc_NtkNodeNum(pNtk);
+ p->nLevelsOld = Abc_AigLevel(pNtk);
+ // remember latch values
+// Abc_NtkForEachLatch( pNtk, pNode, i )
+// pNode->pNext = pNode->pData;
+ // go through the nodes
+ Abc_NtkCleanCopy(pNtk);
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ Abc_NtkRRSimulateStart(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+ // skip the constant node
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
+ continue;
+ // skip the nodes with many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+ // construct the window
+ if ( !fUseFanouts )
+ {
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ {
+ // skip the nodes with only one fanout (tree nodes)
+ if ( Abc_ObjFanoutNum(pFanin) == 1 )
+ continue;
+/*
+ if ( pFanin->Id == 228 && pNode->Id == 2649 )
+ {
+ int k = 0;
+ }
+*/
+ p->nEdgesTried++;
+ Abc_RRManClean( p );
+ p->pNode = pNode;
+ p->pFanin = pFanin;
+ p->pFanout = NULL;
+
+ clk = clock();
+ RetValue = Abc_NtkRRWindow( p );
+ p->timeWindow += clock() - clk;
+ if ( !RetValue )
+ continue;
+/*
+ if ( pFanin->Id == 228 && pNode->Id == 2649 )
+ {
+ Abc_NtkShowAig( p->pWnd, 0 );
+ }
+*/
+ clk = clock();
+ RetValue = Abc_NtkRRProve( p );
+ p->timeMiter += clock() - clk;
+ if ( !RetValue )
+ continue;
+//printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k );
+
+ clk = clock();
+ Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout );
+ p->timeUpdate += clock() - clk;
+
+ p->nEdgesRemoved++;
+ break;
+ }
+ continue;
+ }
+ // use the fanouts
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ Abc_ObjForEachFanout( pNode, pFanout, m )
+ {
+ // skip the nodes with only one fanout (tree nodes)
+// if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 )
+// continue;
+
+ p->nEdgesTried++;
+ Abc_RRManClean( p );
+ p->pNode = pNode;
+ p->pFanin = pFanin;
+ p->pFanout = pFanout;
+
+ clk = clock();
+ RetValue = Abc_NtkRRWindow( p );
+ p->timeWindow += clock() - clk;
+ if ( !RetValue )
+ continue;
+
+ clk = clock();
+ RetValue = Abc_NtkRRProve( p );
+ p->timeMiter += clock() - clk;
+ if ( !RetValue )
+ continue;
+
+ clk = clock();
+ Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout );
+ p->timeUpdate += clock() - clk;
+
+ p->nEdgesRemoved++;
+ break;
+ }
+ }
+ Abc_NtkRRSimulateStop(pNtk);
+ Extra_ProgressBarStop( pProgress );
+ p->timeTotal = clock() - clkTotal;
+ if ( fVerbose )
+ Abc_RRManPrintStats( p );
+ Abc_RRManStop( p );
+ // restore latch values
+// Abc_NtkForEachLatch( pNtk, pNode, i )
+// pNode->pData = pNode->pNext, pNode->pNext = NULL;
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+ Abc_NtkLevel( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRR: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Start the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_RRMan_t * Abc_RRManStart()
+{
+ Abc_RRMan_t * p;
+ p = ALLOC( Abc_RRMan_t, 1 );
+ memset( p, 0, sizeof(Abc_RRMan_t) );
+ p->vFaninLeaves = Vec_PtrAlloc( 100 ); // the leaves of the fanin cone
+ p->vFanoutRoots = Vec_PtrAlloc( 100 ); // the roots of the fanout cone
+ p->vLeaves = Vec_PtrAlloc( 100 ); // the leaves of the window
+ p->vCone = Vec_PtrAlloc( 100 ); // the internal nodes of the window
+ p->vRoots = Vec_PtrAlloc( 100 ); // the roots of the window
+ p->pParams = ALLOC( Prove_Params_t, 1 );
+ memset( p->pParams, 0, sizeof(Prove_Params_t) );
+ Prove_ParamsSetDefault( p->pParams );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RRManStop( Abc_RRMan_t * p )
+{
+ Abc_RRManClean( p );
+ Vec_PtrFree( p->vFaninLeaves );
+ Vec_PtrFree( p->vFanoutRoots );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vCone );
+ Vec_PtrFree( p->vRoots );
+ free( p->pParams );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RRManPrintStats( Abc_RRMan_t * p )
+{
+ double Ratio = 100.0*(p->nNodesOld - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld;
+ printf( "Redundancy removal statistics:\n" );
+ printf( "Edges tried = %6d.\n", p->nEdgesTried );
+ printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried );
+ printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio );
+ printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) );
+ PRT( "Windowing ", p->timeWindow );
+ PRT( "Miter ", p->timeMiter );
+ PRT( " Construct ", p->timeMiter - p->timeProve );
+ PRT( " Prove ", p->timeProve );
+ PRT( "Update ", p->timeUpdate );
+ PRT( "TOTAL ", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Clean the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RRManClean( Abc_RRMan_t * p )
+{
+ p->pNode = NULL;
+ p->pFanin = NULL;
+ p->pFanout = NULL;
+ Vec_PtrClear( p->vFaninLeaves );
+ Vec_PtrClear( p->vFanoutRoots );
+ Vec_PtrClear( p->vLeaves );
+ Vec_PtrClear( p->vCone );
+ Vec_PtrClear( p->vRoots );
+ if ( p->pWnd ) Abc_NtkDelete( p->pWnd );
+ if ( p->pMiter ) Abc_NtkDelete( p->pMiter );
+ p->pWnd = NULL;
+ p->pMiter = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the miter is constant 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRProve( Abc_RRMan_t * p )
+{
+ Abc_Ntk_t * pWndCopy;
+ int RetValue, clk;
+// Abc_NtkShowAig( p->pWnd, 0 );
+ pWndCopy = Abc_NtkDup( p->pWnd );
+ Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL );
+ if ( !Abc_NtkIsDfsOrdered(pWndCopy) )
+ Abc_NtkReassignIds(pWndCopy);
+ p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1, 0 );
+ Abc_NtkDelete( pWndCopy );
+clk = clock();
+ RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams );
+p->timeProve += clock() - clk;
+ if ( RetValue == 1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the network after redundancy removal.]
+
+ Description [This procedure assumes that non-control value of the fanin
+ was proved redundant. It is okay to concentrate on non-control values
+ because the control values can be seen as redundancy of the fanout edge.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout )
+{
+ Abc_Obj_t * pNodeNew, * pFanoutNew;
+ assert( pFanout == NULL );
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( !Abc_ObjIsComplement(pFanin) );
+ assert( !Abc_ObjIsComplement(pFanout) );
+ // find the node after redundancy removal
+ if ( pFanin == Abc_ObjFanin0(pNode) )
+ pNodeNew = Abc_ObjChild1(pNode);
+ else if ( pFanin == Abc_ObjFanin1(pNode) )
+ pNodeNew = Abc_ObjChild0(pNode);
+ else assert( 0 );
+ // replace
+ if ( pFanout == NULL )
+ {
+ Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew, 1 );
+ return 1;
+ }
+ // find the fanout after redundancy removal
+ if ( pNode == Abc_ObjFanin0(pFanout) )
+ pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) );
+ else if ( pNode == Abc_ObjFanin1(pFanout) )
+ pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) );
+ else assert( 0 );
+ // replace
+ Abc_AigReplace( pNtk->pManFunc, pFanout, pFanoutNew, 1 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs window for checking RR.]
+
+ Description [If the window (p->pWnd) with the given scope (p->nFaninLevels,
+ p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1.
+ The levels are measured from the fanin node (pFanin) and the fanout node
+ (pEdgeFanout), respectively.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRWindow( Abc_RRMan_t * p )
+{
+ Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout;
+ int i, LevelMin, LevelMax, RetValue;
+
+ // get the edge
+ pEdgeFanout = p->pFanout? p->pFanout : p->pNode;
+ pEdgeFanin = p->pFanout? p->pNode : p->pFanin;
+ // get the minimum and maximum levels of the window
+ LevelMin = ABC_MAX( 0, ((int)p->pFanin->Level) - p->nFaninLevels );
+ LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels;
+
+ // start the TFI leaves with the fanin
+ Abc_NtkIncrementTravId( p->pNtk );
+ Abc_NodeSetTravIdCurrent( p->pFanin );
+ Vec_PtrPush( p->vFaninLeaves, p->pFanin );
+ // mark the TFI cone and collect the leaves down to the given level
+ while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) );
+
+ // mark the leaves with the new TravId
+ Abc_NtkIncrementTravId( p->pNtk );
+ Vec_PtrForEachEntry( p->vFaninLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // traverse the TFO cone of the leaves (while skipping the edge)
+ // (a) mark the nodes in the cone using the current TravId
+ // (b) collect the nodes that have external fanouts into p->vFanoutRoots
+ while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) );
+
+ // mark the fanout roots
+ Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i )
+ pObj->fMarkA = 1;
+ // collect roots reachable from the fanout (p->vRoots)
+ RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 );
+ // unmark the fanout roots
+ Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i )
+ pObj->fMarkA = 0;
+
+ // return if the window is infeasible
+ if ( RetValue == 0 )
+ return 0;
+
+ // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves)
+ // using the previous marks coming from the TFO cone
+ Abc_NtkIncrementTravId( p->pNtk );
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin );
+
+ // create a new network
+ p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the nodes in the TFI and collects their leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit )
+{
+ Abc_Obj_t * pObj, * pNext;
+ int i, k, LevelMax, nSize;
+ assert( LevelLimit >= 0 );
+ // find the maximum level of leaves
+ LevelMax = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ if ( LevelMax < (int)pObj->Level )
+ LevelMax = pObj->Level;
+ // if the nodes are all PIs, LevelMax == 0
+ if ( LevelMax <= LevelLimit )
+ return 0;
+ // expand the nodes with the minimum level
+ nSize = Vec_PtrSize(vLeaves);
+ Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize )
+ {
+ if ( LevelMax != (int)pObj->Level )
+ continue;
+ Abc_ObjForEachFanin( pObj, pNext, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vLeaves, pNext );
+ }
+ }
+ // remove old nodes (cannot remove a PI)
+ k = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ if ( LevelMax == (int)pObj->Level )
+ continue;
+ Vec_PtrWriteEntry( vLeaves, k++, pObj );
+ }
+ Vec_PtrShrink( vLeaves, k );
+ if ( Vec_PtrSize(vLeaves) > 2000 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the nodes in the TFO and collects their roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout )
+{
+ Abc_Obj_t * pObj, * pNext;
+ int i, k, LevelMin, nSize, fObjIsRoot;
+ // find the minimum level of leaves
+ LevelMin = ABC_INFINITY;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ if ( LevelMin > (int)pObj->Level )
+ LevelMin = pObj->Level;
+ // if the minimum level exceed the limit, we are done
+ if ( LevelMin > LevelLimit )
+ return 0;
+ // expand the nodes with the minimum level
+ nSize = Vec_PtrSize(vLeaves);
+ Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize )
+ {
+ if ( LevelMin != (int)pObj->Level )
+ continue;
+ fObjIsRoot = 0;
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ // check if the fanout is outside of the cone
+ if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit )
+ {
+ fObjIsRoot = 1;
+ continue;
+ }
+ // skip the edge under check
+ if ( pObj == pEdgeFanin && pNext == pEdgeFanout )
+ continue;
+ // skip the visited fanouts
+ if ( Abc_NodeIsTravIdCurrent(pNext) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vLeaves, pNext );
+ }
+ if ( fObjIsRoot )
+ Vec_PtrPush( vRoots, pObj );
+ }
+ // remove old nodes
+ k = 0;
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ {
+ if ( LevelMin == (int)pObj->Level )
+ continue;
+ Vec_PtrWriteEntry( vLeaves, k++, pObj );
+ }
+ Vec_PtrShrink( vLeaves, k );
+ if ( Vec_PtrSize(vLeaves) > 2000 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the roots in the TFO of the node.]
+
+ Description [Note that this procedure can be improved by
+ marking and skipping the visited nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ // if we encountered a node outside of the TFO cone of the fanins, quit
+ if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit )
+ return 0;
+ // if we encountered a node on the boundary, add it to the roots
+ if ( pNode->fMarkA )
+ {
+ Vec_PtrPushUnique( vRoots, pNode );
+ return 1;
+ }
+ // mark the node with the current TravId (needed to have all internal nodes marked)
+ Abc_NodeSetTravIdCurrent( pNode );
+ // traverse the fanouts
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the leaves and cone of the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ // add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit
+ if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit )
+ {
+ Abc_NodeSetTravIdCurrent( pNode );
+ Vec_PtrPush( vLeaves, pNode );
+ return;
+ }
+ // mark the node as visited
+ Abc_NodeSetTravIdCurrent( pNode );
+ // call for the node's fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit );
+ // add the node to the cone in topological order
+ Vec_PtrPush( vCone, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj;
+ int fCheck = 1;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+ // duplicate the name and the spec
+ pNtkNew->pName = Extra_UtilStrsav( "temp" );
+ // map the constant nodes
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ // create and map the PIs
+ Vec_PtrForEachEntry( vLeaves, pObj, i )
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ // copy the AND gates
+ Vec_PtrForEachEntry( vCone, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // compare the number of nodes before and after
+ if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) )
+ printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n",
+ Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) );
+ // create the POs
+ Vec_PtrForEachEntry( vRoots, pObj, i )
+ {
+ assert( !Abc_ObjIsComplement(pObj->pCopy) );
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy );
+ }
+ // add the PI/PO names
+ Abc_NtkAddDummyPiNames( pNtkNew );
+ Abc_NtkAddDummyPoNames( pNtkNew );
+ Abc_NtkAddDummyAssertNames( pNtkNew );
+ // check
+ if ( fCheck && !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkWindow: The network check has failed.\n" );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts simulation to detect non-redundant edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ unsigned uData, uData0, uData1;
+ int i;
+ Abc_AigConst1(pNtk)->pData = (void *)~((unsigned)0);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pData = (void *)SIM_RANDOM_UNSIGNED;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData;
+ uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData;
+ uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0;
+ uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1;
+ assert( pObj->pData == NULL );
+ pObj->pData = (void *)uData;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops simulation to detect non-redundant edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pData = NULL;
+}
+
+
+
+
+
+
+
+static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes );
+static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField );
+static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField );
+
+/**Function*************************************************************
+
+ Synopsis [Simulation to detect non-redundant edges.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vNodes, * vField;
+ Vec_Str_t * vTargets;
+ Abc_Obj_t * pObj;
+ unsigned uData, uData0, uData1;
+ int PrevCi, Phase, i, k;
+
+ // start the candidates
+ vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1);
+ Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1);
+ Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase );
+ }
+
+ // simulate patters and store them in copy
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)SIM_RANDOM_UNSIGNED;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData;
+ uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData;
+ uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0;
+ uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1;
+ pObj->pCopy = (Abc_Obj_t *)uData;
+ }
+ // store the result in data
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ {
+ uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData;
+ if ( Abc_ObjFaninC0(pObj) )
+ pObj->pData = (void *)~uData0;
+ else
+ pObj->pData = (void *)uData0;
+ }
+
+ // refine the candidates
+ for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i )
+ {
+ vNodes = Vec_PtrAlloc( 10 );
+ Abc_NtkIncrementTravId( pNtk );
+ for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ )
+ {
+ Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes );
+ if ( Vec_PtrSize(vNodes) > 128 )
+ break;
+ }
+ // collect the marked nodes in the topological order
+ vField = Vec_PtrAlloc( 10 );
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachCo( pNtk, pObj, k )
+ Sim_CollectNodes_rec( pObj, vField );
+
+ // simulate these nodes
+ Sim_SimulateCollected( vTargets, vNodes, vField );
+ // prepare for the next loop
+ Vec_PtrFree( vNodes );
+ }
+
+ // clean
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->pData = NULL;
+ return vTargets;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects nodes starting from the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pFanout;
+ char Entry;
+ int k;
+ if ( Abc_NodeIsTravIdCurrent(pRoot) )
+ return;
+ Abc_NodeSetTravIdCurrent( pRoot );
+ // save the reached targets
+ Entry = Vec_StrEntry(vTargets, pRoot->Id);
+ if ( Entry & 1 )
+ Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) );
+ if ( Entry & 2 )
+ Vec_PtrPush( vNodes, pRoot );
+ // explore the fanouts
+ Abc_ObjForEachFanout( pRoot, pFanout, k )
+ Sim_TraverseNodes_rec( pFanout, vTargets, vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects nodes starting from the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ if ( Abc_NodeIsTravIdCurrent(pRoot) )
+ return;
+ if ( !Abc_NodeIsTravIdPrevious(pRoot) )
+ return;
+ Abc_NodeSetTravIdCurrent( pRoot );
+ Abc_ObjForEachFanin( pRoot, pFanin, i )
+ Sim_CollectNodes_rec( pFanin, vField );
+ if ( !Abc_ObjIsCo(pRoot) )
+ pRoot->pData = (void *)Vec_PtrSize(vField);
+ Vec_PtrPush( vField, pRoot );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulate the given nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField )
+{
+ Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved;
+ Vec_Ptr_t * vSims;
+ unsigned * pUnsigned, * pUnsignedF;
+ int i, k, Phase, fCompl;
+ // get simulation info
+ vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 );
+ // simulate the nodes
+ Vec_PtrForEachEntry( vField, pObj, i )
+ {
+ if ( Abc_ObjIsCi(pObj) )
+ {
+ pUnsigned = Vec_PtrEntry( vSims, i );
+ for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+ pUnsigned[k] = (unsigned)pObj->pCopy;
+ continue;
+ }
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ pUnsigned = Vec_PtrEntry( vSims, i );
+ pUnsignedF = Vec_PtrEntry( vSims, (int)Abc_ObjFanin0(pObj)->pData );
+ if ( Abc_ObjFaninC0(pObj) )
+ for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+ pUnsigned[k] = ~pUnsignedF[k];
+ else
+ for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+ pUnsigned[k] = pUnsignedF[k];
+ // update targets
+ for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
+ {
+ if ( pUnsigned[k] == (unsigned)pObj->pData )
+ continue;
+ pDisproved = Vec_PtrEntry( vNodes, k );
+ fCompl = Abc_ObjIsComplement(pDisproved);
+ pDisproved = Abc_ObjRegular(pDisproved);
+ Phase = Vec_StrEntry( vTargets, pDisproved->Id );
+ if ( fCompl )
+ Phase = (Phase & 2);
+ else
+ Phase = (Phase & 1);
+ Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase );
+ }
+ continue;
+ }
+ // simulate the node
+ pFanin0 = Abc_ObjFanin0(pObj);
+ pFanin1 = Abc_ObjFanin1(pObj);
+ }
+}
+
+
+
+/*
+ {
+ unsigned uData;
+ if ( pFanin == Abc_ObjFanin0(pNode) )
+ {
+ uData = (unsigned)Abc_ObjFanin1(pNode)->pData;
+ uData = Abc_ObjFaninC1(pNode)? ~uData : uData;
+ }
+ else if ( pFanin == Abc_ObjFanin1(pNode) )
+ {
+ uData = (unsigned)Abc_ObjFanin0(pNode)->pData;
+ uData = Abc_ObjFaninC0(pNode)? ~uData : uData;
+ }
+ uData ^= (unsigned)pNode->pData;
+// Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" );
+ if ( Extra_WordCountOnes(uData) > 8 )
+ continue;
+ }
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c
new file mode 100644
index 00000000..58614584
--- /dev/null
+++ b/src/base/abci/abcSat.c
@@ -0,0 +1,884 @@
+/**CFile****************************************************************
+
+ FileName [abcSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures to solve the miter using the internal SAT sat_solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "satSolver.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes );
+extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );
+static nMuxes;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using an internal SAT sat_solver.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects )
+{
+ sat_solver * pSat;
+ lbool status;
+ int RetValue, clk;
+
+ if ( pNumConfs )
+ *pNumConfs = 0;
+ if ( pNumInspects )
+ *pNumInspects = 0;
+
+ assert( Abc_NtkLatchNum(pNtk) == 0 );
+
+// if ( Abc_NtkPoNum(pNtk) > 1 )
+// fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) );
+
+ // load clauses into the sat_solver
+ clk = clock();
+ pSat = Abc_NtkMiterSatCreate( pNtk, 0 );
+ if ( pSat == NULL )
+ return 1;
+//printf( "%d \n", pSat->clauses.size );
+//sat_solver_delete( pSat );
+//return 1;
+
+// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+// PRT( "Time", clock() - clk );
+
+ // simplify the problem
+ clk = clock();
+ status = sat_solver_simplify(pSat);
+// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+// PRT( "Time", clock() - clk );
+ if ( status == 0 )
+ {
+ sat_solver_delete( pSat );
+// printf( "The problem is UNSATISFIABLE after simplification.\n" );
+ return 1;
+ }
+
+ // solve the miter
+ clk = clock();
+ if ( fVerbose )
+ pSat->verbosity = 1;
+ status = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit, (sint64)0, (sint64)0 );
+ if ( status == l_Undef )
+ {
+// printf( "The problem timed out.\n" );
+ RetValue = -1;
+ }
+ else if ( status == l_True )
+ {
+// printf( "The problem is SATISFIABLE.\n" );
+ RetValue = 0;
+ }
+ else if ( status == l_False )
+ {
+// printf( "The problem is UNSATISFIABLE.\n" );
+ RetValue = 1;
+ }
+ else
+ assert( 0 );
+// PRT( "SAT sat_solver time", clock() - clk );
+// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts );
+
+ // if the problem is SAT, get the counterexample
+ if ( status == l_True )
+ {
+// Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk );
+ Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk );
+ pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+ Vec_IntFree( vCiIds );
+ }
+ // free the sat_solver
+ if ( fVerbose )
+ Sat_SolverPrintStats( stdout, pSat );
+
+ if ( pNumConfs )
+ *pNumConfs = (int)pSat->stats.conflicts;
+ if ( pNumInspects )
+ *pNumInspects = (int)pSat->stats.inspects;
+
+sat_solver_store_write( pSat, "trace.cnf" );
+sat_solver_store_free( pSat );
+
+ sat_solver_delete( pSat );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of CI IDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vCiIds;
+ Abc_Obj_t * pObj;
+ int i;
+ vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ Vec_IntPush( vCiIds, (int)pObj->pCopy );
+ return vCiIds;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Adds trivial clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkClauseTriv( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+{
+//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses );
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) );
+// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) );
+ return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds trivial clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkClauseTop( sat_solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars )
+{
+ Abc_Obj_t * pNode;
+ int i;
+//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses );
+ vVars->nSize = 0;
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) );
+// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) );
+ return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds trivial clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkClauseAnd( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, Vec_Int_t * vVars )
+{
+ int fComp1, Var, Var1, i;
+//printf( "Adding AND %d. (%d) %d\n", pNode->Id, vSuper->nSize+1, (int)pSat->sat_solver_stats.clauses );
+
+ assert( !Abc_ObjIsComplement( pNode ) );
+ assert( Abc_ObjIsNode( pNode ) );
+
+// nVars = sat_solver_nvars(pSat);
+ Var = (int)pNode->pCopy;
+// Var = pNode->Id;
+
+// assert( Var < nVars );
+ for ( i = 0; i < vSuper->nSize; i++ )
+ {
+ // get the predecessor nodes
+ // get the complemented attributes of the nodes
+ fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]);
+ // determine the variable numbers
+ Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy;
+// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id;
+
+ // check that the variables are in the SAT manager
+// assert( Var1 < nVars );
+
+ // suppose the AND-gate is A * B = C
+ // add !A => !C or A + !C
+ // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 );
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(Var1, fComp1) );
+ Vec_IntPush( vVars, toLitCond(Var, 1 ) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ }
+
+ // add A & B => C or !A + !B + C
+// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 );
+ vVars->nSize = 0;
+ for ( i = 0; i < vSuper->nSize; i++ )
+ {
+ // get the predecessor nodes
+ // get the complemented attributes of the nodes
+ fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]);
+ // determine the variable numbers
+ Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy;
+// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id;
+ // add this variable to the array
+ Vec_IntPush( vVars, toLitCond(Var1, !fComp1) );
+ }
+ Vec_IntPush( vVars, toLitCond(Var, 0) );
+ return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds trivial clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkClauseMux( sat_solver * pSat, Abc_Obj_t * pNode, Abc_Obj_t * pNodeC, Abc_Obj_t * pNodeT, Abc_Obj_t * pNodeE, Vec_Int_t * vVars )
+{
+ int VarF, VarI, VarT, VarE, fCompT, fCompE;
+//printf( "Adding mux %d. %d\n", pNode->Id, (int)pSat->sat_solver_stats.clauses );
+
+ assert( !Abc_ObjIsComplement( pNode ) );
+ assert( Abc_NodeIsMuxType( pNode ) );
+ // get the variable numbers
+ VarF = (int)pNode->pCopy;
+ VarI = (int)pNodeC->pCopy;
+ VarT = (int)Abc_ObjRegular(pNodeT)->pCopy;
+ VarE = (int)Abc_ObjRegular(pNodeE)->pCopy;
+// VarF = (int)pNode->Id;
+// VarI = (int)pNodeC->Id;
+// VarT = (int)Abc_ObjRegular(pNodeT)->Id;
+// VarE = (int)Abc_ObjRegular(pNodeE)->Id;
+
+ // get the complementation flags
+ fCompT = Abc_ObjIsComplement(pNodeT);
+ fCompE = Abc_ObjIsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+ // create four clauses
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarI, 1) );
+ Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) );
+ Vec_IntPush( vVars, toLitCond(VarF, 0) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarI, 1) );
+ Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) );
+ Vec_IntPush( vVars, toLitCond(VarF, 1) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarI, 0) );
+ Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) );
+ Vec_IntPush( vVars, toLitCond(VarF, 0) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarI, 0) );
+ Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) );
+ Vec_IntPush( vVars, toLitCond(VarF, 1) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return 1;
+ }
+
+ // two additional clauses
+ // t' & e' -> f' t + e + f'
+ // t & e -> f t' + e' + f
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) );
+ Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) );
+ Vec_IntPush( vVars, toLitCond(VarF, 1) );
+ if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
+ return 0;
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) );
+ Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) );
+ Vec_IntPush( vVars, toLitCond(VarF, 0) );
+ return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux )
+{
+ int RetValue1, RetValue2, i;
+ // check if the node is visited
+ if ( Abc_ObjRegular(pNode)->fMarkB )
+ {
+ // check if the node occurs in the same polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == pNode )
+ return 1;
+ // check if the node is present in the opposite polarity
+ for ( i = 0; i < vSuper->nSize; i++ )
+ if ( vSuper->pArray[i] == Abc_ObjNot(pNode) )
+ return -1;
+ assert( 0 );
+ return 0;
+ }
+ // if the new node is complemented or a PI, another gate begins
+ if ( !fFirst )
+ if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || fStopAtMux && Abc_NodeIsMuxType(pNode) )
+ {
+ Vec_PtrPush( vSuper, pNode );
+ Abc_ObjRegular(pNode)->fMarkB = 1;
+ return 0;
+ }
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ // go through the branches
+ RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux );
+ RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux );
+ if ( RetValue1 == -1 || RetValue2 == -1 )
+ return -1;
+ // return 1 if at least one branch has a duplicate
+ return RetValue1 || RetValue2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes )
+{
+ int RetValue, i;
+ assert( !Abc_ObjIsComplement(pNode) );
+ // collect the nodes in the implication supergate
+ Vec_PtrClear( vNodes );
+ RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux );
+ assert( vNodes->nSize > 1 );
+ // unmark the visited nodes
+ for ( i = 0; i < vNodes->nSize; i++ )
+ Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
+ // if we found the node and its complement in the same implication supergate,
+ // return empty set of nodes (meaning that we should use constant-0 node)
+ if ( RetValue == -1 )
+ vNodes->nSize = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the factor of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkNodeFactor( Abc_Obj_t * pObj, int nLevelMax )
+{
+// nLevelMax = ((nLevelMax)/2)*3;
+ assert( (int)pObj->Level <= nLevelMax );
+// return (int)(100000000.0 * pow(0.999, nLevelMax - pObj->Level));
+ return (int)(100000000.0 * (1 + 0.01 * pObj->Level));
+// return (int)(100000000.0 / ((nLevelMax)/2)*3 - pObj->Level);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the SAT sat_solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE;
+ Vec_Ptr_t * vNodes, * vSuper;
+ Vec_Int_t * vVars;
+ int i, k, fUseMuxes = 1;
+ int clk1 = clock();
+// int fOrderCiVarsFirst = 0;
+ int nLevelsMax = Abc_AigLevel(pNtk);
+ int RetValue = 0;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // clean the CI node pointers
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy = NULL;
+
+ // start the data structures
+ vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the sat_solver
+ vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate
+ vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause
+
+ // add the clause for the constant node
+ pNode = Abc_AigConst1(pNtk);
+ pNode->fMarkA = 1;
+ pNode->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pNode );
+ Abc_NtkClauseTriv( pSat, pNode, vVars );
+/*
+ // add the PI variables first
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ pNode->fMarkA = 1;
+ pNode->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pNode );
+ }
+*/
+ // collect the nodes that need clauses and top-level assignments
+ Vec_PtrClear( vSuper );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ // get the fanin
+ pFanin = Abc_ObjFanin0(pNode);
+ // create the node's variable
+ if ( pFanin->fMarkA == 0 )
+ {
+ pFanin->fMarkA = 1;
+ pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ // add the trivial clause
+ Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) );
+ }
+ if ( !Abc_NtkClauseTop( pSat, vSuper, vVars ) )
+ goto Quits;
+
+
+ // add the clauses
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( !Abc_AigNodeIsAnd(pNode) )
+ continue;
+//printf( "%d ", pNode->Id );
+
+ // add the clauses
+ if ( fUseMuxes && Abc_NodeIsMuxType(pNode) )
+ {
+ nMuxes++;
+
+ pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
+ Vec_PtrClear( vSuper );
+ Vec_PtrPush( vSuper, pNodeC );
+ Vec_PtrPush( vSuper, pNodeT );
+ Vec_PtrPush( vSuper, pNodeE );
+ // add the fanin nodes to explore
+ Vec_PtrForEachEntry( vSuper, pFanin, k )
+ {
+ pFanin = Abc_ObjRegular(pFanin);
+ if ( pFanin->fMarkA == 0 )
+ {
+ pFanin->fMarkA = 1;
+ pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ }
+ // add the clauses
+ if ( !Abc_NtkClauseMux( pSat, pNode, pNodeC, pNodeT, pNodeE, vVars ) )
+ goto Quits;
+ }
+ else
+ {
+ // get the supergate
+ Abc_NtkCollectSupergate( pNode, fUseMuxes, vSuper );
+ // add the fanin nodes to explore
+ Vec_PtrForEachEntry( vSuper, pFanin, k )
+ {
+ pFanin = Abc_ObjRegular(pFanin);
+ if ( pFanin->fMarkA == 0 )
+ {
+ pFanin->fMarkA = 1;
+ pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ }
+ // add the clauses
+ if ( vSuper->nSize == 0 )
+ {
+ if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) )
+// if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) )
+ goto Quits;
+ }
+ else
+ {
+ if ( !Abc_NtkClauseAnd( pSat, pNode, vSuper, vVars ) )
+ goto Quits;
+ }
+ }
+ }
+/*
+ // set preferred variables
+ if ( fOrderCiVarsFirst )
+ {
+ int * pPrefVars = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ int nVars = 0;
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ {
+ if ( pNode->fMarkA == 0 )
+ continue;
+ pPrefVars[nVars++] = (int)pNode->pCopy;
+ }
+ nVars = ABC_MIN( nVars, 10 );
+ ASat_SolverSetPrefVars( pSat, pPrefVars, nVars );
+ }
+*/
+ RetValue = 1;
+Quits :
+ // delete
+ Vec_IntFree( vVars );
+ Vec_PtrFree( vNodes );
+ Vec_PtrFree( vSuper );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the SAT sat_solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes )
+{
+ sat_solver * pSat;
+ Abc_Obj_t * pNode;
+ int RetValue, i, clk = clock();
+
+ assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) );
+ if ( Abc_NtkIsBddLogic(pNtk) )
+ return Abc_NtkMiterSatCreateLogic(pNtk, fAllPrimes);
+
+ nMuxes = 0;
+ pSat = sat_solver_new();
+//sat_solver_store_alloc( pSat );
+ RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk );
+sat_solver_store_mark_roots( pSat );
+
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ pNode->fMarkA = 0;
+// ASat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 );
+ if ( RetValue == 0 )
+ {
+ sat_solver_delete(pSat);
+ return NULL;
+ }
+// printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
+// PRT( "Creating sat_solver", clock() - clk );
+ return pSat;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Adds clauses for the internal node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+{
+ Abc_Obj_t * pFanin;
+ int i, c, nFanins;
+ int RetValue;
+ char * pCube;
+
+ nFanins = Abc_ObjFaninNum( pNode );
+ assert( nFanins == Abc_SopGetVarNum( pSop0 ) );
+
+// if ( nFanins == 0 )
+ if ( Cudd_Regular(pNode->pData) == Cudd_ReadOne(pNode->pNtk->pManFunc) )
+ {
+ vVars->nSize = 0;
+// if ( Abc_SopIsConst1(pSop1) )
+ if ( !Cudd_IsComplement(pNode->pData) )
+ Vec_IntPush( vVars, toLit(pNode->Id) );
+ else
+ Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+ return 1;
+ }
+
+ // add clauses for the negative phase
+ for ( c = 0; ; c++ )
+ {
+ // get the cube
+ pCube = pSop0 + c * (nFanins + 3);
+ if ( *pCube == 0 )
+ break;
+ // add the clause
+ vVars->nSize = 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pCube[i] == '0' )
+ Vec_IntPush( vVars, toLit(pFanin->Id) );
+ else if ( pCube[i] == '1' )
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+ }
+ Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+ }
+
+ // add clauses for the positive phase
+ for ( c = 0; ; c++ )
+ {
+ // get the cube
+ pCube = pSop1 + c * (nFanins + 3);
+ if ( *pCube == 0 )
+ break;
+ // add the clause
+ vVars->nSize = 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pCube[i] == '0' )
+ Vec_IntPush( vVars, toLit(pFanin->Id) );
+ else if ( pCube[i] == '1' )
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+ }
+ Vec_IntPush( vVars, toLit(pNode->Id) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds clauses for the PO node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+{
+ Abc_Obj_t * pFanin;
+ int RetValue;
+
+ pFanin = Abc_ObjFanin0(pNode);
+ if ( Abc_ObjFaninC0(pNode) )
+ {
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLit(pFanin->Id) );
+ Vec_IntPush( vVars, toLit(pNode->Id) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+ }
+ else
+ {
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, toLit(pNode->Id) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLit(pFanin->Id) );
+ Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+ }
+
+ vVars->nSize = 0;
+ Vec_IntPush( vVars, toLit(pNode->Id) );
+ RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ if ( !RetValue )
+ {
+ printf( "The CNF is trivially UNSAT.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the SAT sat_solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes )
+{
+ sat_solver * pSat;
+ Extra_MmFlex_t * pMmFlex;
+ Abc_Obj_t * pNode;
+ Vec_Str_t * vCube;
+ Vec_Int_t * vVars;
+ char * pSop0, * pSop1;
+ int i;
+
+ assert( Abc_NtkIsBddLogic(pNtk) );
+
+ // transfer the IDs to the copy field
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ pNode->pCopy = (void *)pNode->Id;
+
+ // start the data structures
+ pSat = sat_solver_new();
+sat_solver_store_alloc( pSat );
+ pMmFlex = Extra_MmFlexStart();
+ vCube = Vec_StrAlloc( 100 );
+ vVars = Vec_IntAlloc( 100 );
+
+ // add clauses for each internal nodes
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // derive SOPs for both phases of the node
+ Abc_NodeBddToCnf( pNode, pMmFlex, vCube, fAllPrimes, &pSop0, &pSop1 );
+ // add the clauses to the sat_solver
+ if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) )
+ {
+ sat_solver_delete( pSat );
+ pSat = NULL;
+ goto finish;
+ }
+ }
+ // add clauses for each PO
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ {
+ if ( !Abc_NodeAddClausesTop( pSat, pNode, vVars ) )
+ {
+ sat_solver_delete( pSat );
+ pSat = NULL;
+ goto finish;
+ }
+ }
+sat_solver_store_mark_roots( pSat );
+
+finish:
+ // delete
+ Vec_StrFree( vCube );
+ Vec_IntFree( vVars );
+ Extra_MmFlexStop( pMmFlex );
+ return pSat;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c
new file mode 100644
index 00000000..c77f8dea
--- /dev/null
+++ b/src/base/abci/abcStrash.c
@@ -0,0 +1,478 @@
+/**CFile****************************************************************
+
+ FileName [abcStrash.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Strashing of the current network.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "extra.h"
+#include "dec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reapplies structural hashing to the AIG.]
+
+ Description [Because of the structural hashing, this procedure should not
+ change the number of nodes. It is useful to detect the bugs in the original AIG.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup )
+{
+ extern int timeRetime;
+ Abc_Ntk_t * pNtkAig;
+ Abc_Obj_t * pObj;
+ 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" );
+ // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // restrash the nodes (assuming a topological order of the old network)
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // finalize the network
+ Abc_NtkFinalize( pNtk, pNtkAig );
+ // print warning about self-feed latches
+// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+ // perform cleanup if requested
+ if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+ printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+//timeRetime = clock() - timeRetime;
+// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
+// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
+ return pNtkAig;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reapplies structural hashing to the AIG.]
+
+ Description [Because of the structural hashing, this procedure should not
+ change the number of nodes. It is useful to detect the bugs in the original AIG.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup )
+{
+ extern int timeRetime;
+ Abc_Ntk_t * pNtkAig;
+ Abc_Obj_t * pObj;
+ 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" );
+ // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // complement the 1-values registers
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( Abc_LatchIsInit1(pObj) )
+ Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy);
+ // 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
+ Abc_NtkFinalize( pNtk, pNtkAig );
+ // complement the 1-valued registers
+ Abc_NtkForEachLatch( pNtkAig, pObj, i )
+ if ( Abc_LatchIsInit1(pObj) )
+ Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 );
+ // set all constant-0 values
+ Abc_NtkForEachLatch( pNtkAig, pObj, i )
+ Abc_LatchSetInit0( pObj );
+
+ // print warning about self-feed latches
+// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+ // perform cleanup if requested
+ if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
+ printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+//timeRetime = clock() - timeRetime;
+// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
+// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
+ return pNtkAig;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms logic network into structurally hashed AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord )
+{
+ Abc_Ntk_t * pNtkAig;
+ int nNodes;
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+ // consider the special case when the network is already structurally hashed
+ if ( Abc_NtkIsStrash(pNtk) )
+ return Abc_NtkRestrash( pNtk, fCleanup );
+ // convert the node representation in the logic network to the AIG form
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ printf( "Converting to AIGs has failed.\n" );
+ return NULL;
+ }
+ // perform strashing
+// Abc_NtkCleanCopy( pNtk );
+ pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord );
+ Abc_NtkFinalize( pNtk, pNtkAig );
+ // print warning about self-feed latches
+// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
+// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
+ // perform cleanup if requested
+ nNodes = fCleanup? Abc_AigCleanup(pNtkAig->pManFunc) : 0;
+// if ( nNodes )
+// printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
+ // duplicate EXDC
+ if ( pNtk->pExdc )
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkStrash: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Appends the second network to the first.]
+
+ Description [Modifies the first network by adding the logic of the second.
+ Performs structural hashing while appending the networks. Does not change
+ the second network. Returns 0 if the appending failed, 1 otherise.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos )
+{
+ Abc_Obj_t * pObj;
+ char * pName;
+ int i, nNewCis;
+ // the first network should be an AIG
+ assert( Abc_NtkIsStrash(pNtk1) );
+ assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) );
+ if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) )
+ {
+ printf( "Converting to AIGs has failed.\n" );
+ return 0;
+ }
+ // check that the networks have the same PIs
+ // reorder PIs of pNtk2 according to pNtk1
+ if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) )
+ printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" );
+ // perform strashing
+ nNewCis = 0;
+ Abc_NtkCleanCopy( pNtk2 );
+ if ( Abc_NtkIsStrash(pNtk2) )
+ Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1);
+ Abc_NtkForEachCi( pNtk2, pObj, i )
+ {
+ pName = Abc_ObjName(pObj);
+ pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj));
+ if ( pObj->pCopy == NULL )
+ {
+ pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1);
+ nNewCis++;
+ }
+ }
+ if ( nNewCis )
+ printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis );
+ // add pNtk2 to pNtk1 while strashing
+ if ( Abc_NtkIsLogic(pNtk2) )
+ Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 );
+ else
+ Abc_NtkForEachNode( pNtk2, pObj, i )
+ pObj->pCopy = Abc_AigAnd( pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ // add the COs of the second network
+ if ( fAddPos )
+ {
+ Abc_NtkForEachPo( pNtk2, pObj, i )
+ {
+ Abc_NtkDupObj( pNtk1, pObj, 0 );
+ Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
+ Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj->pCopy), NULL );
+ }
+ }
+ else
+ {
+ Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew;
+ int fCompl, iNodeId;
+ // OR the choices
+ Abc_NtkForEachCo( pNtk2, pObj, i )
+ {
+ iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
+ assert( iNodeId >= 0 );
+ pObjOld = Abc_NtkObj( pNtk1, iNodeId );
+ // derive the new driver
+ pDriverOld = Abc_ObjChild0( pObjOld );
+ pDriverNew = Abc_ObjChild0Copy( pObj );
+ pDriverNew = Abc_AigOr( pNtk1->pManFunc, pDriverOld, pDriverNew );
+ if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) )
+ continue;
+ // replace the old driver by the new driver
+ fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase;
+ Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) );
+ }
+ }
+ // make sure that everything is okay
+ if ( !Abc_NtkCheck( pNtk1 ) )
+ {
+ printf( "Abc_NtkAppend: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the network for strashing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord )
+{
+ ProgressBar * pProgress;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNodeOld;
+ int i, clk = clock();
+ assert( Abc_NtkIsLogic(pNtkOld) );
+ assert( Abc_NtkIsStrash(pNtkNew) );
+// vNodes = Abc_NtkDfs( pNtkOld, fAllNodes );
+ vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes );
+//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) );
+//PRT( "Time", clock() - clk );
+ pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+ Vec_PtrForEachEntry( vNodes, pNodeOld, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the AIG from one manager into another.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj )
+{
+ assert( !Hop_IsComplement(pObj) );
+ if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
+ return;
+ Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) );
+ Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) );
+ pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) );
+ assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
+ Hop_ObjSetMarkA( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node.]
+
+ Description [Assume the network is in the AIG form]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord )
+{
+ Hop_Man_t * pMan;
+ Hop_Obj_t * pRoot;
+ Abc_Obj_t * pFanin;
+ int i;
+ assert( Abc_ObjIsNode(pNodeOld) );
+ assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) );
+ // get the local AIG manager and the local root node
+ pMan = pNodeOld->pNtk->pManFunc;
+ pRoot = pNodeOld->pData;
+ // check the constant case
+ if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) )
+ return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) );
+ // perform special case-strashing using the record of AIG subgraphs
+ if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() )
+ {
+ extern Vec_Int_t * Abc_NtkRecMemory();
+ extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars );
+ int nVars = Abc_NtkRecVarNum();
+ Vec_Int_t * vMemory = Abc_NtkRecMemory();
+ unsigned * pTruth = Abc_ConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 );
+ assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept
+ if ( Hop_IsComplement(pRoot) )
+ Extra_TruthNot( pTruth, pTruth, nVars );
+ if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) )
+ return pNodeOld->pCopy;
+ }
+ // set elementary variables
+ Abc_ObjForEachFanin( pNodeOld, pFanin, i )
+ Hop_IthVar(pMan, i)->pData = pFanin->pCopy;
+ // strash the AIG of this node
+ Abc_NodeStrash_rec( pNtkNew->pManFunc, Hop_Regular(pRoot) );
+ Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
+ // return the final node
+ return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
+}
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Copies the topmost levels of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut )
+{
+ assert( !Abc_ObjIsComplement(pNode) );
+ if ( pNode->pCopy )
+ return pNode->pCopy;
+ if ( pNode->Level <= (unsigned)LevelCut )
+ return pNode->pCopy = Abc_NtkCreatePi( pNtkNew );
+ Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut );
+ Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut );
+ return pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copies the topmost levels of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjNew, * pPoNew;
+ int LevelCut;
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkCoNum(pNtk) == 1 );
+ // get the cutoff level
+ 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);
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
+ // create PIs below the cut and nodes above the cut
+ Abc_NtkCleanCopy( pNtk );
+ pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut );
+ pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) );
+ // add the PO node and name
+ pPoNew = Abc_NtkCreatePo(pNtkNew);
+ Abc_ObjAddFanin( pPoNew, pObjNew );
+ Abc_NtkAddDummyPiNames( pNtkNew );
+ Abc_ObjAssignName( pPoNew, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL );
+ // make sure everything is okay
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ {
+ printf( "Abc_NtkTopmost: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkNew );
+ return NULL;
+ }
+ return pNtkNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcSweep.c b/src/base/abci/abcSweep.c
new file mode 100644
index 00000000..1ae8745b
--- /dev/null
+++ b/src/base/abci/abcSweep.c
@@ -0,0 +1,948 @@
+/**CFile****************************************************************
+
+ FileName [abcDsd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Technology dependent sweep.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fraig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+static stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose );
+static void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose );
+static void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose );
+static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose );
+static int Abc_NodeDroppingCost( Abc_Obj_t * pNode );
+
+static int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes );
+static void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose );
+static void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 );
+static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Sweping functionally equivalence nodes.]
+
+ Description [Removes gates with equivalent functionality. Works for
+ both technology-independent and mapped networks. If the flag is set,
+ allows adding inverters at the gate outputs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose )
+{
+ Fraig_Params_t Params;
+ Abc_Ntk_t * pNtkAig;
+ Fraig_Man_t * pMan;
+ stmm_table * tEquiv;
+ Abc_Obj_t * pObj;
+ int i, fUseTrick;
+
+ assert( !Abc_NtkIsStrash(pNtk) );
+
+ // save gate assignments
+ fUseTrick = 0;
+ if ( Abc_NtkIsMappedLogic(pNtk) )
+ {
+ fUseTrick = 1;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pNext = pObj->pData;
+ }
+ // derive the AIG
+ pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ // reconstruct gate assignments
+ if ( fUseTrick )
+ {
+ extern void * Abc_FrameReadLibGen();
+ Hop_ManStop( pNtk->pManFunc );
+ pNtk->pManFunc = Abc_FrameReadLibGen();
+ pNtk->ntkFunc = ABC_FUNC_MAP;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ pObj->pData = pObj->pNext, pObj->pNext = NULL;
+ }
+
+ // perform fraiging of the AIG
+ Fraig_ParamsSetDefault( &Params );
+ pMan = Abc_NtkToFraig( pNtkAig, &Params, 0, 0 );
+ // cannot use EXDC with FRAIG because it can create classes of equivalent FRAIG nodes
+ // with representative nodes that do not correspond to the nodes with the current network
+
+ // update FRAIG using EXDC
+ if ( fExdc )
+ {
+ if ( pNtk->pExdc == NULL )
+ printf( "Warning: Networks has no EXDC.\n" );
+ else
+ Abc_NtkFraigSweepUsingExdc( pMan, pNtk );
+ }
+ // assign levels to the nodes of the network
+ Abc_NtkLevel( pNtk );
+
+ // collect the classes of equivalent nets
+ tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose );
+
+ // transform the network into the equivalent one
+ Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose );
+ stmm_free_table( tEquiv );
+
+ // free the manager
+ Fraig_ManFree( pMan );
+ Abc_NtkDelete( pNtkAig );
+
+ // cleanup the dangling nodes
+ if ( Abc_NtkHasMapping(pNtk) )
+ Abc_NtkCleanup( pNtk, fVerbose );
+ else
+ Abc_NtkSweep( pNtk, fVerbose );
+
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkFraigSweep: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sweep the network using EXDC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
+{
+ Fraig_Node_t * gNodeExdc, * gNode, * gNodeRes;
+ Abc_Obj_t * pNode, * pNodeAig;
+ int i;
+ extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkExdc );
+
+ assert( pNtk->pExdc );
+ // derive FRAIG node representing don't-cares in the EXDC network
+ gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc );
+ // update the node pointers
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ // skip the constant input nodes
+ if ( Abc_ObjFaninNum(pNode) == 0 )
+ continue;
+ // get the strashed node
+ pNodeAig = pNode->pCopy;
+ // skip the dangling nodes
+ if ( pNodeAig == NULL )
+ continue;
+ // get the FRAIG node
+ gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) );
+ // perform ANDing with EXDC
+ gNodeRes = Fraig_NodeAnd( pMan, gNode, Fraig_Not(gNodeExdc) );
+ // write the node back
+ Abc_ObjRegular(pNodeAig)->pCopy = (Abc_Obj_t *)Fraig_NotCond( gNodeRes, Abc_ObjIsComplement(pNodeAig) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects equivalence classses of node in the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose )
+{
+ Abc_Obj_t * pList, * pNode, * pNodeAig;
+ Fraig_Node_t * gNode;
+ Abc_Obj_t ** ppSlot;
+ stmm_table * tStrash2Net;
+ stmm_table * tResult;
+ stmm_generator * gen;
+ int c, Counter;
+
+ // create mapping of strashed nodes into the corresponding network nodes
+ tStrash2Net = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+ Abc_NtkForEachNode( pNtk, pNode, c )
+ {
+ // skip the constant input nodes
+ if ( Abc_ObjFaninNum(pNode) == 0 )
+ continue;
+ // get the strashed node
+ pNodeAig = pNode->pCopy;
+ // skip the dangling nodes
+ if ( pNodeAig == NULL )
+ continue;
+ // skip the nodes that fanout into COs
+ if ( Abc_NodeFindCoFanout(pNode) )
+ continue;
+ // get the FRAIG node
+ gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) );
+ if ( !stmm_find_or_add( tStrash2Net, (char *)Fraig_Regular(gNode), (char ***)&ppSlot ) )
+ *ppSlot = NULL;
+ // add the node to the list
+ pNode->pNext = *ppSlot;
+ *ppSlot = pNode;
+ // mark the node if it is complemented
+ pNode->fPhase = Fraig_IsComplement(gNode);
+ }
+
+ // print the classes
+ c = 0;
+ Counter = 0;
+ tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash);
+ stmm_foreach_item( tStrash2Net, gen, (char **)&gNode, (char **)&pList )
+ {
+ // skip the trival classes
+ if ( pList == NULL || pList->pNext == NULL )
+ continue;
+ // add the non-trival class
+ stmm_insert( tResult, (char *)pList, NULL );
+ // count nodes in the non-trival classes
+ for ( pNode = pList; pNode; pNode = pNode->pNext )
+ Counter++;
+
+ if ( fVeryVerbose )
+ {
+ printf( "Class %2d : {", c );
+ for ( pNode = pList; pNode; pNode = pNode->pNext )
+ {
+ pNode->pCopy = NULL;
+ printf( " %s", Abc_ObjName(pNode) );
+ printf( "(%c)", pNode->fPhase? '-' : '+' );
+ printf( "(%d)", pNode->Level );
+ }
+ printf( " }\n" );
+ c++;
+ }
+ }
+ if ( fVerbose || fVeryVerbose )
+ {
+ printf( "Sweeping stats for network \"%s\":\n", pNtk->pName );
+ printf( "Internal nodes = %d. Different functions (up to compl) = %d.\n", Abc_NtkNodeNum(pNtk), stmm_count(tStrash2Net) );
+ printf( "Non-trivial classes = %d. Nodes in non-trivial classes = %d.\n", stmm_count(tResult), Counter );
+ }
+ stmm_free_table( tStrash2Net );
+ return tResult;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the network using the equivalence relation on nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose )
+{
+ stmm_generator * gen;
+ Abc_Obj_t * pList;
+ if ( stmm_count(tEquiv) == 0 )
+ return;
+ // merge nodes in the classes
+ if ( Abc_NtkHasMapping( pNtk ) )
+ {
+ Abc_NtkDelayTrace( pNtk );
+ stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL )
+ Abc_NtkFraigMergeClassMapped( pNtk, pList, fUseInv, fVerbose );
+ }
+ else
+ {
+ stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL )
+ Abc_NtkFraigMergeClass( pNtk, pList, fUseInv, fVerbose );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the list of one-phase equivalent nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose )
+{
+ Abc_Obj_t * pListDir, * pListInv;
+ Abc_Obj_t * pNodeMin, * pNode, * pNext;
+ float Arrival1, Arrival2;
+
+ assert( pChain );
+ assert( pChain->pNext );
+
+ // divide the nodes into two parts:
+ // those that need the invertor and those that don't need
+ pListDir = pListInv = NULL;
+ for ( pNode = pChain, pNext = pChain->pNext;
+ pNode;
+ pNode = pNext, pNext = pNode? pNode->pNext : NULL )
+ {
+ // check to which class the node belongs
+ if ( pNode->fPhase == 1 )
+ {
+ pNode->pNext = pListDir;
+ pListDir = pNode;
+ }
+ else
+ {
+ pNode->pNext = pListInv;
+ pListInv = pNode;
+ }
+ }
+
+ // find the node with the smallest number of logic levels
+ pNodeMin = pListDir;
+ for ( pNode = pListDir; pNode; pNode = pNode->pNext )
+ {
+ Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst;
+ Arrival2 = Abc_NodeReadArrival(pNode )->Worst;
+// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
+// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 );
+ if ( Arrival1 > Arrival2 ||
+ Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level ||
+ Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level &&
+ Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) )
+ pNodeMin = pNode;
+ }
+
+ // move the fanouts of the direct nodes
+ for ( pNode = pListDir; pNode; pNode = pNode->pNext )
+ if ( pNode != pNodeMin )
+ Abc_ObjTransferFanout( pNode, pNodeMin );
+
+ // find the node with the smallest number of logic levels
+ pNodeMin = pListInv;
+ for ( pNode = pListInv; pNode; pNode = pNode->pNext )
+ {
+ Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst;
+ Arrival2 = Abc_NodeReadArrival(pNode )->Worst;
+// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
+// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 );
+ if ( Arrival1 > Arrival2 ||
+ Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level ||
+ Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level &&
+ Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) )
+ pNodeMin = pNode;
+ }
+
+ // move the fanouts of the direct nodes
+ for ( pNode = pListInv; pNode; pNode = pNode->pNext )
+ if ( pNode != pNodeMin )
+ Abc_ObjTransferFanout( pNode, pNodeMin );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Process one equivalence class of nodes.]
+
+ Description [This function does not remove the nodes. It only switches
+ around the connections.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose )
+{
+ Abc_Obj_t * pListDir, * pListInv;
+ Abc_Obj_t * pNodeMin, * pNodeMinInv;
+ Abc_Obj_t * pNode, * pNext;
+
+ assert( pChain );
+ assert( pChain->pNext );
+
+ // find the node with the smallest number of logic levels
+ pNodeMin = pChain;
+ for ( pNode = pChain->pNext; pNode; pNode = pNode->pNext )
+ if ( pNodeMin->Level > pNode->Level ||
+ ( pNodeMin->Level == pNode->Level &&
+ Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) )
+ pNodeMin = pNode;
+
+ // divide the nodes into two parts:
+ // those that need the invertor and those that don't need
+ pListDir = pListInv = NULL;
+ for ( pNode = pChain, pNext = pChain->pNext;
+ pNode;
+ pNode = pNext, pNext = pNode? pNode->pNext : NULL )
+ {
+ if ( pNode == pNodeMin )
+ continue;
+ // check to which class the node belongs
+ if ( pNodeMin->fPhase == pNode->fPhase )
+ {
+ pNode->pNext = pListDir;
+ pListDir = pNode;
+ }
+ else
+ {
+ pNode->pNext = pListInv;
+ pListInv = pNode;
+ }
+ }
+
+ // move the fanouts of the direct nodes
+ for ( pNode = pListDir; pNode; pNode = pNode->pNext )
+ Abc_ObjTransferFanout( pNode, pNodeMin );
+
+ // skip if there are no inverted nodes
+ if ( pListInv == NULL )
+ return;
+
+ // add the invertor
+ pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin );
+
+ // move the fanouts of the inverted nodes
+ for ( pNode = pListInv; pNode; pNode = pNode->pNext )
+ Abc_ObjTransferFanout( pNode, pNodeMinInv );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of literals saved if this node becomes useless.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeDroppingCost( Abc_Obj_t * pNode )
+{
+ return 1;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Removes dangling nodes.]
+
+ Description [Returns the number of nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Vec_Ptr_t * vNodes;
+ int Counter;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // mark the nodes reachable from the POs
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ Counter = Abc_NtkReduceNodes( pNtk, vNodes );
+ if ( fVerbose )
+ printf( "Cleanup removed %d dangling nodes.\n", Counter );
+ Vec_PtrFree( vNodes );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Preserves the nodes collected in the array.]
+
+ Description [Returns the number of nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pNode;
+ int i, Counter;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // mark the nodes reachable from the POs
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ pNode->fMarkA = 1;
+ // remove the non-marked nodes
+ Counter = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( pNode->fMarkA == 0 )
+ {
+ Abc_NtkDeleteObj( pNode );
+ Counter++;
+ }
+ // unmark the remaining nodes
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ pNode->fMarkA = 0;
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ printf( "Abc_NtkCleanup: The network check has failed.\n" );
+ return Counter;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Tranditional sweep of the network.]
+
+ Description [Propagates constant and single-input node, removes dangling nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode, * pFanout, * pDriver;
+ int i, nNodesOld;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // convert network to BDD representation
+ if ( !Abc_NtkToBdd(pNtk) )
+ {
+ fprintf( stdout, "Converting to BDD has failed.\n" );
+ return 1;
+ }
+ // perform cleanup
+ nNodesOld = Abc_NtkNodeNum(pNtk);
+ Abc_NtkCleanup( pNtk, 0 );
+ // prepare nodes for sweeping
+ Abc_NtkRemoveDupFanins(pNtk);
+ Abc_NtkMinimumBase(pNtk);
+ // collect sweepable nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( Abc_ObjFaninNum(pNode) < 2 )
+ Vec_PtrPush( vNodes, pNode );
+ // sweep the nodes
+ while ( Vec_PtrSize(vNodes) > 0 )
+ {
+ // get any sweepable node
+ pNode = Vec_PtrPop(vNodes);
+ if ( !Abc_ObjIsNode(pNode) )
+ continue;
+ // get any non-CO fanout of this node
+ pFanout = Abc_NodeFindNonCoFanout(pNode);
+ if ( pFanout == NULL )
+ continue;
+ assert( Abc_ObjIsNode(pFanout) );
+ // transform the function of the fanout
+ if ( Abc_ObjFaninNum(pNode) == 0 )
+ Abc_NodeConstantInput( pFanout, pNode, Abc_NodeIsConst0(pNode) );
+ else
+ {
+ assert( Abc_ObjFaninNum(pNode) == 1 );
+ pDriver = Abc_ObjFanin0(pNode);
+ if ( Abc_NodeIsInv(pNode) )
+ Abc_NodeComplementInput( pFanout, pNode );
+ Abc_ObjPatchFanin( pFanout, pNode, pDriver );
+ }
+ Abc_NodeRemoveDupFanins( pFanout );
+ Abc_NodeMinimumBase( pFanout );
+ // check if the fanout should be added
+ if ( Abc_ObjFaninNum(pFanout) < 2 )
+ Vec_PtrPush( vNodes, pFanout );
+ // check if the node has other fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 0 )
+ Vec_PtrPush( vNodes, pNode );
+ else
+ Abc_NtkDeleteObj_rec( pNode, 1 );
+ }
+ Vec_PtrFree( vNodes );
+ // sweep a node into its CO fanout if all of this is true:
+ // (a) this node is a single-input node
+ // (b) the driver of the node has only one fanout (this node)
+ // (c) the driver is a node
+ Abc_NtkForEachCo( pNtk, pFanout, i )
+ {
+ pNode = Abc_ObjFanin0(pFanout);
+ if ( Abc_ObjFaninNum(pNode) != 1 )
+ continue;
+ pDriver = Abc_ObjFanin0(pNode);
+ if ( !(Abc_ObjFanoutNum(pDriver) == 1 && Abc_ObjIsNode(pDriver)) )
+ continue;
+ // trasform this CO
+ if ( Abc_NodeIsInv(pNode) )
+ pDriver->pData = Cudd_Not(pDriver->pData);
+ Abc_ObjPatchFanin( pFanout, pNode, pDriver );
+ }
+ // perform cleanup
+ Abc_NtkCleanup( pNtk, 0 );
+ // report
+ if ( fVerbose )
+ printf( "Sweep removed %d nodes.\n", nNodesOld - Abc_NtkNodeNum(pNtk) );
+ return nNodesOld - Abc_NtkNodeNum(pNtk);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Replaces the local function by its cofactor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 )
+{
+ DdManager * dd = pNode->pNtk->pManFunc;
+ DdNode * bVar, * bTemp;
+ int iFanin;
+ assert( Abc_NtkIsBddLogic(pNode->pNtk) );
+ if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
+ {
+ printf( "Node %s should be among", Abc_ObjName(pFanin) );
+ printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
+ return;
+ }
+ bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iFanin), fConst0 );
+ pNode->pData = Cudd_Cofactor( dd, bTemp = pNode->pData, bVar ); Cudd_Ref( pNode->pData );
+ Cudd_RecursiveDeref( dd, bTemp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Changes the polarity of one fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
+{
+ DdManager * dd = pNode->pNtk->pManFunc;
+ DdNode * bVar, * bCof0, * bCof1;
+ int iFanin;
+ assert( Abc_NtkIsBddLogic(pNode->pNtk) );
+ if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
+ {
+ printf( "Node %s should be among", Abc_ObjName(pFanin) );
+ printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
+ return;
+ }
+ bVar = Cudd_bddIthVar( dd, iFanin );
+ bCof0 = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 );
+ bCof1 = Cudd_Cofactor( dd, pNode->pData, bVar ); Cudd_Ref( bCof1 );
+ Cudd_RecursiveDeref( dd, pNode->pData );
+ pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 ); Cudd_Ref( pNode->pData );
+ Cudd_RecursiveDeref( dd, bCof0 );
+ Cudd_RecursiveDeref( dd, bCof1 );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Removes all objects whose trav ID is not current.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NodeRemoveNonCurrentObjects( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int Counter, i;
+ int fVerbose = 0;
+
+ // report on the nodes to be deleted
+ if ( fVerbose )
+ {
+ printf( "These nodes will be deleted: \n" );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent( pObj ) )
+ {
+ printf( " " );
+ Abc_ObjPrint( stdout, pObj );
+ }
+ }
+
+ // delete the nodes
+ Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( !Abc_NodeIsTravIdCurrent( pObj ) )
+ {
+ Abc_NtkDeleteObj( pObj );
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the fanin of this latch is a constant.]
+
+ Description [Returns 0/1 if constant; -1 if not a constant.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSetTravId_rec( Abc_Obj_t * pObj )
+{
+ Abc_NodeSetTravIdCurrent(pObj);
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ return;
+ assert( Abc_ObjFaninNum(pObj) == 1 );
+ Abc_NtkSetTravId_rec( Abc_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if the fanin of this latch is a constant.]
+
+ Description [Returns 0/1 if constant; -1 if not a constant.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCheckConstant_rec( Abc_Obj_t * pObj )
+{
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ {
+ if ( !Abc_ObjIsNode(pObj) )
+ return -1;
+ if ( Abc_NodeIsConst0(pObj) )
+ return 0;
+ if ( Abc_NodeIsConst1(pObj) )
+ return 1;
+ assert( 0 );
+ return -1;
+ }
+ if ( Abc_ObjIsLatch(pObj) || Abc_ObjFaninNum(pObj) > 1 )
+ return -1;
+ if ( !Abc_ObjIsNode(pObj) || Abc_NodeIsBuf(pObj) )
+ return Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) );
+ if ( Abc_NodeIsInv(pObj) )
+ {
+ int RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) );
+ if ( RetValue == 0 )
+ return 1;
+ if ( RetValue == 1 )
+ return 0;
+ return RetValue;
+ }
+ assert( 0 );
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes redundant latches.]
+
+ Description [The redundant latches are of two types:
+ - Latches fed by a constant which matches the init value of the latch.
+ - Latches fed by a constant which does not match the init value of the latch
+ can be all replaced by one latch.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkLatchSweep( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pFanin, * pLatch, * pLatchPivot = NULL;
+ int Counter, RetValue, i;
+ Counter = 0;
+ // go through the latches
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ // check if the latch has constant input
+ RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pLatch) );
+ if ( RetValue == -1 )
+ continue;
+ // found a latch with constant fanin
+ if ( (RetValue == 1 && Abc_LatchIsInit0(pLatch)) ||
+ (RetValue == 0 && Abc_LatchIsInit1(pLatch)) )
+ {
+ // fanin constant differs from the latch init value
+ if ( pLatchPivot == NULL )
+ {
+ pLatchPivot = pLatch;
+ continue;
+ }
+ if ( Abc_LatchInit(pLatch) != Abc_LatchInit(pLatchPivot) ) // add inverter
+ pFanin = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanout0(pLatchPivot) );
+ else
+ pFanin = Abc_ObjFanout0(pLatchPivot);
+ }
+ else
+ pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+ // replace latch
+ Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pFanin );
+ // delete the extra nodes
+ Abc_NtkDeleteObj_rec( Abc_ObjFanout0(pLatch), 0 );
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces autonumnous logic by free inputs.]
+
+ Description [Assumes that non-autonomous logic is marked with
+ the current ID.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode, * pFanin;
+ Vec_Ptr_t * vNodes;
+ int i, k, Counter;
+ // collect the nodes that feed into the reachable logic
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ {
+ // skip non-visited fanins
+ if ( !Abc_NodeIsTravIdCurrent(pNode) )
+ continue;
+ // look for non-visited fanins
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ {
+ // skip visited fanins
+ if ( Abc_NodeIsTravIdCurrent(pFanin) )
+ continue;
+ // skip constants and latches fed by constants
+ if ( Abc_NtkCheckConstant_rec(pFanin) != -1 ||
+ (Abc_ObjIsBo(pFanin) && Abc_NtkCheckConstant_rec(Abc_ObjFanin0(Abc_ObjFanin0(pFanin))) != -1) )
+ {
+ Abc_NtkSetTravId_rec( pFanin );
+ continue;
+ }
+ assert( !Abc_ObjIsLatch(pFanin) );
+ Vec_PtrPush( vNodes, pFanin );
+ }
+ }
+ Vec_PtrUniqify( vNodes, Abc_ObjPointerCompare );
+ // replace these nodes by the PIs
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ pFanin = Abc_NtkCreatePi(pNtk);
+ Abc_ObjAssignName( pFanin, Abc_ObjName(pFanin), NULL );
+ Abc_NodeSetTravIdCurrent( pFanin );
+ Abc_ObjTransferFanout( pNode, pFanin );
+ }
+ Counter = Vec_PtrSize(vNodes);
+ Vec_PtrFree( vNodes );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sequential cleanup.]
+
+ Description [Performs three tasks:
+ - Removes logic that does not feed into POs.
+ - Removes latches driven by constant values equal to the initial state.
+ - Replaces the autonomous components by additional PI variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose )
+{
+ Vec_Ptr_t * vNodes;
+ int Counter;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // mark the nodes reachable from the POs
+ vNodes = Abc_NtkDfsSeq( pNtk );
+ Vec_PtrFree( vNodes );
+ // remove the non-marked nodes
+ Counter = Abc_NodeRemoveNonCurrentObjects( pNtk );
+ if ( fVerbose )
+ printf( "Cleanup removed %4d dangling objects.\n", Counter );
+ // check if some of the latches can be removed
+ if ( fLatchSweep )
+ {
+ Counter = Abc_NtkLatchSweep( pNtk );
+ if ( fVerbose )
+ printf( "Cleanup removed %4d redundant latches.\n", Counter );
+ }
+ // detect the autonomous components
+ if ( fAutoSweep )
+ {
+ vNodes = Abc_NtkDfsSeqReverse( pNtk );
+ Vec_PtrFree( vNodes );
+ // replace them by PIs
+ Counter = Abc_NtkReplaceAutonomousLogic( pNtk );
+ if ( fVerbose )
+ printf( "Cleanup added %4d additional PIs.\n", Counter );
+ // remove the non-marked nodes
+ Counter = Abc_NodeRemoveNonCurrentObjects( pNtk );
+ if ( fVerbose )
+ printf( "Cleanup removed %4d autonomous objects.\n", Counter );
+ }
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ printf( "Abc_NtkCleanupSeq: The network check has failed.\n" );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcSymm.c b/src/base/abci/abcSymm.c
new file mode 100644
index 00000000..0f76065c
--- /dev/null
+++ b/src/base/abci/abcSymm.c
@@ -0,0 +1,229 @@
+/**CFile****************************************************************
+
+ FileName [abcSymm.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Computation of two-variable symmetries.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcSymm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose );
+static void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose );
+static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose );
+static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [The top level procedure to compute symmetries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose )
+{
+ if ( fUseBdds || fNaive )
+ Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose );
+ else
+ Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Symmetry computation using simulation and SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose );
+ int nSymms = Sim_ComputeTwoVarSymms( pNtk, fVerbose );
+ printf( "The total number of symmetries is %d.\n", nSymms );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Symmetry computation using BDDs (both naive and smart).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose )
+{
+ DdManager * dd;
+ int clk, clkBdd, clkSym;
+ int fGarbCollect = 1;
+
+ // compute the global functions
+clk = clock();
+ dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, fVerbose );
+ printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) );
+ Cudd_AutodynDisable( dd );
+ if ( !fGarbCollect )
+ Cudd_DisableGarbageCollection( dd );
+ Cudd_zddVarsFromBddVars( dd, 2 );
+clkBdd = clock() - clk;
+ // create the collapsed network
+clk = clock();
+ Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose );
+clkSym = clock() - clk;
+ // undo the global functions
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
+printf( "Statistics of BDD-based symmetry detection:\n" );
+printf( "Algorithm = %s. Reordering = %s. Garbage collection = %s.\n",
+ fNaive? "naive" : "fast", fReorder? "yes" : "no", fGarbCollect? "yes" : "no" );
+PRT( "Constructing BDDs", clkBdd );
+PRT( "Computing symms ", clkSym );
+PRT( "TOTAL ", clkBdd + clkSym );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Symmetry computation using BDDs (both naive and smart).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose )
+{
+ Extra_SymmInfo_t * pSymms;
+ Abc_Obj_t * pNode;
+ DdNode * bFunc;
+ int nSymms = 0;
+ int nSupps = 0;
+ int i;
+
+ // compute symmetry info for each PO
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+// bFunc = pNtk->vFuncsGlob->pArray[i];
+ bFunc = Abc_ObjGlobalBdd( pNode );
+ nSupps += Cudd_SupportSize( dd, bFunc );
+ if ( Cudd_IsConstant(bFunc) )
+ continue;
+ if ( fNaive )
+ pSymms = Extra_SymmPairsComputeNaive( dd, bFunc );
+ else
+ pSymms = Extra_SymmPairsCompute( dd, bFunc );
+ nSymms += pSymms->nSymms;
+ if ( fVerbose )
+ {
+ printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms );
+ Ntk_NetworkSymmsPrint( pNtk, pSymms );
+ }
+//Extra_SymmPairsPrint( pSymms );
+ Extra_SymmPairsDissolve( pSymms );
+ }
+ printf( "Total number of vars in functional supports = %8d.\n", nSupps );
+ printf( "Total number of two-variable symmetries = %8d.\n", nSymms );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Printing symmetry groups from the symmetry data structure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms )
+{
+ char ** pInputNames;
+ int * pVarTaken;
+ int i, k, nVars, nSize, fStart;
+
+ // get variable names
+ nVars = Abc_NtkCiNum(pNtk);
+ pInputNames = Abc_NtkCollectCioNames( pNtk, 0 );
+
+ // alloc the array of marks
+ pVarTaken = ALLOC( int, nVars );
+ memset( pVarTaken, 0, sizeof(int) * nVars );
+
+ // print the groups
+ fStart = 1;
+ nSize = pSymms->nVars;
+ for ( i = 0; i < nSize; i++ )
+ {
+ // skip the variable already considered
+ if ( pVarTaken[i] )
+ continue;
+ // find all the vars symmetric with this one
+ for ( k = 0; k < nSize; k++ )
+ {
+ if ( k == i )
+ continue;
+ if ( pSymms->pSymms[i][k] == 0 )
+ continue;
+ // vars i and k are symmetric
+ assert( pVarTaken[k] == 0 );
+ // there is a new symmetry pair
+ if ( fStart == 1 )
+ { // start a new symmetry class
+ fStart = 0;
+ printf( " { %s", pInputNames[ pSymms->pVars[i] ] );
+ // mark the var as taken
+ pVarTaken[i] = 1;
+ }
+ printf( " %s", pInputNames[ pSymms->pVars[k] ] );
+ // mark the var as taken
+ pVarTaken[k] = 1;
+ }
+ if ( fStart == 0 )
+ {
+ printf( " }" );
+ fStart = 1;
+ }
+ }
+ printf( "\n" );
+
+ free( pInputNames );
+ free( pVarTaken );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c
new file mode 100644
index 00000000..967e4617
--- /dev/null
+++ b/src/base/abci/abcTiming.c
@@ -0,0 +1,905 @@
+/**CFile****************************************************************
+
+ FileName [abcTiming.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Computation of timing info for mapped circuits.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "main.h"
+#include "mio.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Abc_ManTime_t_
+{
+ Abc_Time_t tArrDef;
+ Abc_Time_t tReqDef;
+ Vec_Ptr_t * vArrs;
+ Vec_Ptr_t * vReqs;
+};
+
+// static functions
+static Abc_ManTime_t * Abc_ManTimeStart();
+static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive );
+void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk );
+
+void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode );
+
+// accessing the arrival and required times of a node
+static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; }
+static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the arrival time of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode )
+{
+ assert( pNode->pNtk->pManTime );
+ return Abc_NodeArrival(pNode);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the arrival time of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode )
+{
+ assert( pNode->pNtk->pManTime );
+ return Abc_NodeRequired(pNode);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the arrival time of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk )
+{
+ assert( pNtk->pManTime );
+ return &pNtk->pManTime->tArrDef;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the arrival time of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk )
+{
+ assert( pNtk->pManTime );
+ return &pNtk->pManTime->tReqDef;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default arrival time for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall )
+{
+ if ( Rise == 0.0 && Fall == 0.0 )
+ return;
+ if ( pNtk->pManTime == NULL )
+ pNtk->pManTime = Abc_ManTimeStart();
+ pNtk->pManTime->tArrDef.Rise = Rise;
+ pNtk->pManTime->tArrDef.Fall = Fall;
+ pNtk->pManTime->tArrDef.Worst = ABC_MAX( Rise, Fall );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default arrival time for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall )
+{
+ if ( Rise == 0.0 && Fall == 0.0 )
+ return;
+ if ( pNtk->pManTime == NULL )
+ pNtk->pManTime = Abc_ManTimeStart();
+ pNtk->pManTime->tReqDef.Rise = Rise;
+ pNtk->pManTime->tReqDef.Rise = Fall;
+ pNtk->pManTime->tReqDef.Worst = ABC_MAX( Rise, Fall );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the arrival time for an object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall )
+{
+ Vec_Ptr_t * vTimes;
+ Abc_Time_t * pTime;
+ if ( pNtk->pManTime == NULL )
+ pNtk->pManTime = Abc_ManTimeStart();
+ if ( pNtk->pManTime->tArrDef.Rise == Rise && pNtk->pManTime->tArrDef.Fall == Fall )
+ return;
+ Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 );
+ // set the arrival time
+ vTimes = pNtk->pManTime->vArrs;
+ pTime = vTimes->pArray[ObjId];
+ pTime->Rise = Rise;
+ pTime->Fall = Rise;
+ pTime->Worst = ABC_MAX( Rise, Fall );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the arrival time for an object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall )
+{
+ Vec_Ptr_t * vTimes;
+ Abc_Time_t * pTime;
+ if ( pNtk->pManTime == NULL )
+ pNtk->pManTime = Abc_ManTimeStart();
+ if ( pNtk->pManTime->tReqDef.Rise == Rise && pNtk->pManTime->tReqDef.Fall == Fall )
+ return;
+ Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 );
+ // set the required time
+ vTimes = pNtk->pManTime->vReqs;
+ pTime = vTimes->pArray[ObjId];
+ pTime->Rise = Rise;
+ pTime->Fall = Rise;
+ pTime->Worst = ABC_MAX( Rise, Fall );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finalizes the timing manager after setting arr/req times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ Abc_Time_t ** ppTimes, * pTime;
+ int i;
+ if ( pNtk->pManTime == NULL )
+ return;
+ Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 );
+ // set the default timing
+ ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ pTime = ppTimes[pObj->Id];
+ if ( pTime->Worst != -ABC_INFINITY )
+ continue;
+ *pTime = pNtk->pManTime->tArrDef;
+ }
+ // set the default timing
+ ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray;
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pTime = ppTimes[pObj->Id];
+ if ( pTime->Worst != -ABC_INFINITY )
+ continue;
+ *pTime = pNtk->pManTime->tReqDef;
+ }
+ // set the 0 arrival times for latch outputs and constant nodes
+ ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
+ Abc_NtkForEachLatchOutput( pNtk, pObj, i )
+ {
+ pTime = ppTimes[pObj->Id];
+ pTime->Fall = pTime->Rise = pTime->Worst = 0.0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the timing manager for delay trace.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ Abc_Time_t ** ppTimes, * pTime;
+ int i;
+ // if there is no timing manager, allocate and initialize
+ if ( pNtk->pManTime == NULL )
+ {
+ pNtk->pManTime = Abc_ManTimeStart();
+ Abc_NtkTimeInitialize( pNtk );
+ return;
+ }
+ // if timing manager is given, expand it if necessary
+ Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 );
+ // clean arrivals except for PIs
+ ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ pTime = ppTimes[pObj->Id];
+ pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY;
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ pTime = ppTimes[pObj->Id];
+ pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY;
+ }
+ // clean required except for POs
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManTime_t * Abc_ManTimeStart()
+{
+ Abc_ManTime_t * p;
+ p = ALLOC( Abc_ManTime_t, 1 );
+ memset( p, 0, sizeof(Abc_ManTime_t) );
+ p->vArrs = Vec_PtrAlloc( 0 );
+ p->vReqs = Vec_PtrAlloc( 0 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManTimeStop( Abc_ManTime_t * p )
+{
+ if ( p->vArrs->nSize > 0 )
+ {
+ free( p->vArrs->pArray[0] );
+ Vec_PtrFree( p->vArrs );
+ }
+ if ( p->vReqs->nSize > 0 )
+ {
+ free( p->vReqs->pArray[0] );
+ Vec_PtrFree( p->vReqs );
+ }
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the timing manager with the PI/PO timing info.]
+
+ Description [The PIs/POs of the new network should be allocated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew )
+{
+ Abc_Obj_t * pObj;
+ Abc_Time_t ** ppTimesOld, ** ppTimesNew;
+ int i;
+ if ( pNtkOld->pManTime == NULL )
+ return;
+ assert( Abc_NtkPiNum(pNtkOld) == Abc_NtkPiNum(pNtkNew) );
+ assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) );
+ assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) );
+ // create the new timing manager
+ pNtkNew->pManTime = Abc_ManTimeStart();
+ Abc_ManTimeExpand( pNtkNew->pManTime, Abc_NtkObjNumMax(pNtkNew), 0 );
+ // set the default timing
+ pNtkNew->pManTime->tArrDef = pNtkOld->pManTime->tArrDef;
+ pNtkNew->pManTime->tReqDef = pNtkOld->pManTime->tReqDef;
+ // set the CI timing
+ ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vArrs->pArray;
+ ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vArrs->pArray;
+ Abc_NtkForEachCi( pNtkOld, pObj, i )
+ *ppTimesNew[ Abc_NtkCi(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ];
+ // set the CO timing
+ ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vReqs->pArray;
+ ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vReqs->pArray;
+ Abc_NtkForEachCo( pNtkOld, pObj, i )
+ *ppTimesNew[ Abc_NtkCo(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Expends the storage for timing information.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive )
+{
+ Vec_Ptr_t * vTimes;
+ Abc_Time_t * ppTimes, * ppTimesOld, * pTime;
+ int nSizeOld, nSizeNew, i;
+
+ nSizeOld = p->vArrs->nSize;
+ if ( nSizeOld >= nSize )
+ return;
+ nSizeNew = fProgressive? 2 * nSize : nSize;
+ if ( nSizeNew < 100 )
+ nSizeNew = 100;
+
+ vTimes = p->vArrs;
+ Vec_PtrGrow( vTimes, nSizeNew );
+ vTimes->nSize = nSizeNew;
+ ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0];
+ ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew );
+ for ( i = 0; i < nSizeNew; i++ )
+ vTimes->pArray[i] = ppTimes + i;
+ for ( i = nSizeOld; i < nSizeNew; i++ )
+ {
+ pTime = vTimes->pArray[i];
+ pTime->Rise = -ABC_INFINITY;
+ pTime->Fall = -ABC_INFINITY;
+ pTime->Worst = -ABC_INFINITY;
+ }
+
+ vTimes = p->vReqs;
+ Vec_PtrGrow( vTimes, nSizeNew );
+ vTimes->nSize = nSizeNew;
+ ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0];
+ ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew );
+ for ( i = 0; i < nSizeNew; i++ )
+ vTimes->pArray[i] = ppTimes + i;
+ for ( i = nSizeOld; i < nSizeNew; i++ )
+ {
+ pTime = vTimes->pArray[i];
+ pTime->Rise = -ABC_INFINITY;
+ pTime->Fall = -ABC_INFINITY;
+ pTime->Worst = -ABC_INFINITY;
+ }
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets the CI node levels according to the arrival info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld )
+{
+ Abc_Obj_t * pNodeOld, * pNodeNew;
+ float tAndDelay;
+ int i;
+ if ( pNtkOld->pManTime == NULL )
+ return;
+ if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen()) == NULL )
+ return;
+ tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen());
+ Abc_NtkForEachPi( pNtkOld, pNodeOld, i )
+ {
+ pNodeNew = pNodeOld->pCopy;
+ pNodeNew->Level = (int)(Abc_NodeArrival(pNodeOld)->Worst / tAndDelay);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the CI node levels according to the arrival info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk )
+{
+ Abc_Time_t * p;
+ Abc_Obj_t * pNode;
+ int i;
+ p = ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) );
+ memset( p, 0, sizeof(Abc_Time_t) * Abc_NtkCiNum(pNtk) );
+ if ( pNtk->pManTime == NULL )
+ return p;
+ // set the PI arrival times
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ p[i] = *Abc_NodeArrival(pNode);
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets the CI node levels according to the arrival info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk )
+{
+ float * p;
+ Abc_Obj_t * pNode;
+ int i;
+ p = ALLOC( float, Abc_NtkCiNum(pNtk) );
+ memset( p, 0, sizeof(float) * Abc_NtkCiNum(pNtk) );
+ if ( pNtk->pManTime == NULL )
+ return p;
+ // set the PI arrival times
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ p[i] = Abc_NodeArrival(pNode)->Worst;
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pNode, * pDriver;
+ Vec_Ptr_t * vNodes;
+ Abc_Time_t * pTime;
+ float tArrivalMax;
+ int i;
+
+ assert( Abc_NtkIsMappedLogic(pNtk) );
+
+ Abc_NtkTimePrepare( pNtk );
+ vNodes = Abc_NtkDfs( pNtk, 1 );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ Abc_NodeDelayTraceArrival( vNodes->pArray[i] );
+ Vec_PtrFree( vNodes );
+
+ // get the latest arrival times
+ tArrivalMax = -ABC_INFINITY;
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+ pDriver = Abc_ObjFanin0(pNode);
+ pTime = Abc_NodeArrival(pDriver);
+ if ( tArrivalMax < pTime->Worst )
+ tArrivalMax = pTime->Worst;
+ }
+ return tArrivalMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ Abc_Time_t * pTimeIn, * pTimeOut;
+ float tDelayBlockRise, tDelayBlockFall;
+ Mio_PinPhase_t PinPhase;
+ Mio_Pin_t * pPin;
+ int i;
+
+ // start the arrival time of the node
+ pTimeOut = Abc_NodeArrival(pNode);
+ pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY;
+ // go through the pins of the gate
+ pPin = Mio_GateReadPins(pNode->pData);
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ pTimeIn = Abc_NodeArrival(pFanin);
+ // get the interesting parameters of this pin
+ PinPhase = Mio_PinReadPhase(pPin);
+ tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
+ tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );
+ // compute the arrival times of the positive phase
+ if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present
+ {
+ if ( pTimeOut->Rise < pTimeIn->Rise + tDelayBlockRise )
+ pTimeOut->Rise = pTimeIn->Rise + tDelayBlockRise;
+ if ( pTimeOut->Fall < pTimeIn->Fall + tDelayBlockFall )
+ pTimeOut->Fall = pTimeIn->Fall + tDelayBlockFall;
+ }
+ if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present
+ {
+ if ( pTimeOut->Rise < pTimeIn->Fall + tDelayBlockRise )
+ pTimeOut->Rise = pTimeIn->Fall + tDelayBlockRise;
+ if ( pTimeOut->Fall < pTimeIn->Rise + tDelayBlockFall )
+ pTimeOut->Fall = pTimeIn->Rise + tDelayBlockFall;
+ }
+ pPin = Mio_PinReadNext(pPin);
+ }
+ pTimeOut->Worst = ABC_MAX( pTimeOut->Rise, pTimeOut->Fall );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the level of the node using its fanin levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjLevelNew( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i, Level = 0;
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Level = ABC_MAX( Level, Abc_ObjLevel(pFanin) );
+ return Level + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the reverse level of the node using its fanout levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i, LevelCur, Level = 0;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ LevelCur = Abc_ObjReverseLevel( pFanout );
+ Level = ABC_MAX( Level, LevelCur );
+ }
+ return Level + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns required level of the node.]
+
+ Description [Converts the reverse levels of the node into its required
+ level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjRequiredLevel( Abc_Obj_t * pObj )
+{
+ Abc_Ntk_t * pNtk = pObj->pNtk;
+ assert( pNtk->vLevelsR );
+ return pNtk->LevelMax + 1 - Abc_ObjReverseLevel(pObj);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the reverse level of the node.]
+
+ Description [The reverse level is the level of the node in reverse
+ topological order, starting from the COs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjReverseLevel( Abc_Obj_t * pObj )
+{
+ Abc_Ntk_t * pNtk = pObj->pNtk;
+ assert( pNtk->vLevelsR );
+ Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
+ return Vec_IntEntry(pNtk->vLevelsR, pObj->Id);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the reverse level of the node.]
+
+ Description [The reverse level is the level of the node in reverse
+ topological order, starting from the COs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR )
+{
+ Abc_Ntk_t * pNtk = pObj->pNtk;
+ assert( pNtk->vLevelsR );
+ Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
+ Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares for the computation of required levels.]
+
+ Description [This procedure should be called before the required times
+ are used. It starts internal data structures, which records the level
+ from the COs of the network nodes in reverse topologogical order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i;
+ // remember the maximum number of direct levels
+ pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease;
+ // start the reverse levels
+ pNtk->vLevelsR = Vec_IntAlloc( 0 );
+ Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 );
+ // compute levels in reverse topological order
+ vNodes = Abc_NtkDfsReverse( pNtk );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) );
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the data structures used to compute required levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk )
+{
+ assert( pNtk->vLevelsR );
+ Vec_IntFree( pNtk->vLevelsR );
+ pNtk->vLevelsR = NULL;
+ pNtk->LevelMax = 0;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Incrementally updates level of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
+{
+ Abc_Obj_t * pFanout, * pTemp;
+ int LevelOld, Lev, k, m;
+ // check if level has changed
+ LevelOld = Abc_ObjLevel(pObjNew);
+ if ( LevelOld == Abc_ObjLevelNew(pObjNew) )
+ return;
+ // start the data structure for level update
+ // we cannot fail to visit a node when using this structure because the
+ // nodes are stored by their _old_ levels, which are assumed to be correct
+ Vec_VecClear( vLevels );
+ Vec_VecPush( vLevels, LevelOld, pObjNew );
+ pObjNew->fMarkA = 1;
+ // recursively update level
+ Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld )
+ {
+ pTemp->fMarkA = 0;
+ assert( Abc_ObjLevel(pTemp) == Lev );
+ Abc_ObjSetLevel( pTemp, Abc_ObjLevelNew(pTemp) );
+ // if the level did not change, no need to check the fanout levels
+ if ( Abc_ObjLevel(pTemp) == Lev )
+ continue;
+ // schedule fanout for level update
+ Abc_ObjForEachFanout( pTemp, pFanout, m )
+ {
+ if ( !Abc_ObjIsCo(pFanout) && !pFanout->fMarkA )
+ {
+ assert( Abc_ObjLevel(pFanout) >= Lev );
+ Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout );
+ pFanout->fMarkA = 1;
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Incrementally updates level of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
+{
+ Abc_Obj_t * pFanin, * pTemp;
+ int LevelOld, LevFanin, Lev, k, m;
+ // check if level has changed
+ LevelOld = Abc_ObjReverseLevel(pObjNew);
+ if ( LevelOld == Abc_ObjReverseLevelNew(pObjNew) )
+ return;
+ // start the data structure for level update
+ // we cannot fail to visit a node when using this structure because the
+ // nodes are stored by their _old_ levels, which are assumed to be correct
+ Vec_VecClear( vLevels );
+ Vec_VecPush( vLevels, LevelOld, pObjNew );
+ pObjNew->fMarkA = 1;
+ // recursively update level
+ Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld )
+ {
+ pTemp->fMarkA = 0;
+ LevelOld = Abc_ObjReverseLevel(pTemp);
+ assert( LevelOld == Lev );
+ Abc_ObjSetReverseLevel( pTemp, Abc_ObjReverseLevelNew(pTemp) );
+ // if the level did not change, no need to check the fanout levels
+ if ( Abc_ObjReverseLevel(pTemp) == Lev )
+ continue;
+ // schedule fanins for level update
+ Abc_ObjForEachFanin( pTemp, pFanin, m )
+ {
+ if ( !Abc_ObjIsCi(pFanin) && !pFanin->fMarkA )
+ {
+ LevFanin = Abc_ObjReverseLevel( pFanin );
+ assert( LevFanin >= Lev );
+ Vec_VecPush( vLevels, LevFanin, pFanin );
+ pFanin->fMarkA = 1;
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Replaces the node and incrementally updates levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
+{
+ // replace the old node by the new node
+ pObjNew->Level = pObj->Level;
+ Abc_ObjReplace( pObj, pObjNew );
+ // update the level of the node
+ Abc_NtkUpdateLevel( pObjNew, vLevels );
+ Abc_ObjSetReverseLevel( pObjNew, 0 );
+ Abc_NtkUpdateReverseLevel( pObjNew, vLevels );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcUnate.c b/src/base/abci/abcUnate.c
new file mode 100644
index 00000000..20804d19
--- /dev/null
+++ b/src/base/abci/abcUnate.c
@@ -0,0 +1,155 @@
+/**CFile****************************************************************
+
+ FileName [abcUnate.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose );
+static void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Detects unate variables of the multi-output function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose )
+{
+ if ( fUseBdds || fUseNaive )
+ Abc_NtkPrintUnateBdd( pNtk, fUseNaive, fVerbose );
+ else
+ Abc_NtkPrintUnateSat( pNtk, fVerbose );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detects unate variables using BDDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose )
+{
+ Abc_Obj_t * pNode;
+ Extra_UnateInfo_t * p;
+ DdManager * dd; // the BDD manager used to hold shared BDDs
+// DdNode ** pbGlobal; // temporary storage for global BDDs
+ int TotalSupps = 0;
+ int TotalUnate = 0;
+ int i, clk = clock();
+ int clkBdd, clkUnate;
+
+ // compute the global BDDs
+ dd = Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose);
+ if ( dd == NULL )
+ return;
+clkBdd = clock() - clk;
+
+ // get information about the network
+// dd = pNtk->pManGlob;
+// dd = Abc_NtkGlobalBddMan( pNtk );
+// pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob );
+
+ // print the size of the BDDs
+ printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+ // perform naive BDD-based computation
+ if ( fUseNaive )
+ {
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+// p = Extra_UnateComputeSlow( dd, pbGlobal[i] );
+ p = Extra_UnateComputeSlow( dd, Abc_ObjGlobalBdd(pNode) );
+ if ( fVerbose )
+ Extra_UnateInfoPrint( p );
+ TotalSupps += p->nVars;
+ TotalUnate += p->nUnate;
+ Extra_UnateInfoDissolve( p );
+ }
+ }
+ // perform smart BDD-based computation
+ else
+ {
+ // create ZDD variables in the manager
+ Cudd_zddVarsFromBddVars( dd, 2 );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ {
+// p = Extra_UnateComputeFast( dd, pbGlobal[i] );
+ p = Extra_UnateComputeFast( dd, Abc_ObjGlobalBdd(pNode) );
+ if ( fVerbose )
+ Extra_UnateInfoPrint( p );
+ TotalSupps += p->nVars;
+ TotalUnate += p->nUnate;
+ Extra_UnateInfoDissolve( p );
+ }
+ }
+clkUnate = clock() - clk - clkBdd;
+
+ // print stats
+ printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n",
+ Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), TotalSupps, TotalUnate );
+ PRT( "Glob BDDs", clkBdd );
+ PRT( "Unateness", clkUnate );
+ PRT( "Total ", clock() - clk );
+
+ // deref the PO functions
+// Abc_NtkFreeGlobalBdds( pNtk );
+ // stop the global BDD manager
+// Extra_StopManager( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detects unate variables using SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose )
+{
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c
new file mode 100644
index 00000000..ea0a4cd2
--- /dev/null
+++ b/src/base/abci/abcUnreach.c
@@ -0,0 +1,349 @@
+/**CFile****************************************************************
+
+ FileName [abcUnreach.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Computes unreachable states for small benchmarks.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcUnreach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose );
+static DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose );
+static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bRelation, DdNode * bInitial, bool fVerbose );
+static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Extracts sequential DCs of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose )
+{
+ int fReorder = 1;
+ DdManager * dd;
+ DdNode * bRelation, * bInitial, * bUnreach;
+
+ // remove EXDC network if present
+ if ( pNtk->pExdc )
+ {
+ Abc_NtkDelete( pNtk->pExdc );
+ pNtk->pExdc = NULL;
+ }
+
+ // compute the global BDDs of the latches
+ dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
+ if ( dd == NULL )
+ return 0;
+ if ( fVerbose )
+ printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+ // create the transition relation (dereferenced global BDDs)
+ bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose ); Cudd_Ref( bRelation );
+ // create the initial state and the variable map
+ bInitial = Abc_NtkInitStateAndVarMap( dd, pNtk, fVerbose ); Cudd_Ref( bInitial );
+ // compute the unreachable states
+ bUnreach = Abc_NtkComputeUnreachable( dd, pNtk, bRelation, bInitial, fVerbose ); Cudd_Ref( bUnreach );
+ Cudd_RecursiveDeref( dd, bRelation );
+ Cudd_RecursiveDeref( dd, bInitial );
+
+ // reorder and disable reordering
+ if ( fReorder )
+ {
+ if ( fVerbose )
+ fprintf( stdout, "BDD nodes in the unreachable states before reordering %d.\n", Cudd_DagSize(bUnreach) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+ Cudd_AutodynDisable( dd );
+ if ( fVerbose )
+ fprintf( stdout, "BDD nodes in the unreachable states after reordering %d.\n", Cudd_DagSize(bUnreach) );
+ }
+
+ // allocate ZDD variables
+ Cudd_zddVarsFromBddVars( dd, 2 );
+ // create the EXDC network representing the unreachable states
+ if ( pNtk->pExdc )
+ Abc_NtkDelete( pNtk->pExdc );
+ pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach );
+ Cudd_RecursiveDeref( dd, bUnreach );
+ Extra_StopManager( dd );
+// pNtk->pManGlob = NULL;
+
+ // make sure that everything is okay
+ if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) )
+ {
+ printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" );
+ Abc_NtkDelete( pNtk->pExdc );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the transition relation of the network.]
+
+ Description [Assumes that the global BDDs are computed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose )
+{
+ DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs;
+ Abc_Obj_t * pNode;
+ int fReorder = 1;
+ int i;
+
+ // extand the BDD manager to represent NS variables
+ assert( dd->size == Abc_NtkCiNum(pNtk) );
+ Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 );
+
+ // enable reordering
+ if ( fReorder )
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ else
+ Cudd_AutodynDisable( dd );
+
+ // compute the transition relation
+ bRel = b1; Cudd_Ref( bRel );
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ {
+ bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i );
+// bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd );
+ bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd );
+ bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+ // free the global BDDs
+// Abc_NtkFreeGlobalBdds( pNtk );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
+
+ // quantify the PI variables
+ bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs );
+ bRel = Cudd_bddExistAbstract( dd, bTemp = bRel, bInputs ); Cudd_Ref( bRel );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bInputs );
+
+ // reorder and disable reordering
+ if ( fReorder )
+ {
+ if ( fVerbose )
+ fprintf( stdout, "BDD nodes in the transition relation before reordering %d.\n", Cudd_DagSize(bRel) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ Cudd_AutodynDisable( dd );
+ if ( fVerbose )
+ fprintf( stdout, "BDD nodes in the transition relation after reordering %d.\n", Cudd_DagSize(bRel) );
+ }
+ Cudd_Deref( bRel );
+ return bRel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the initial state and sets up the variable map.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose )
+{
+ DdNode ** pbVarsX, ** pbVarsY;
+ DdNode * bTemp, * bProd, * bVar;
+ Abc_Obj_t * pLatch;
+ int i;
+
+ // set the variable mapping for Cudd_bddVarMap()
+ pbVarsX = ALLOC( DdNode *, dd->size );
+ pbVarsY = ALLOC( DdNode *, dd->size );
+ bProd = b1; Cudd_Ref( bProd );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ];
+ pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ];
+ // get the initial value of the latch
+ bVar = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) );
+ bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) );
+ FREE( pbVarsX );
+ FREE( pbVarsY );
+
+ Cudd_Deref( bProd );
+ return bProd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of unreachable states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bTrans, DdNode * bInitial, bool fVerbose )
+{
+ DdNode * bRelation, * bReached, * bCubeCs;
+ DdNode * bCurrent, * bNext, * bTemp;
+ int nIters, nMints;
+
+ // perform reachability analisys
+ bCurrent = bInitial; Cudd_Ref( bCurrent );
+ bReached = bInitial; Cudd_Ref( bReached );
+ bRelation = bTrans; Cudd_Ref( bRelation );
+ bCubeCs = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) ); Cudd_Ref( bCubeCs );
+ for ( nIters = 1; ; nIters++ )
+ {
+ // compute the next states
+ bNext = Cudd_bddAndAbstract( dd, bRelation, bCurrent, bCubeCs ); Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( dd, bCurrent );
+ // remap these states into the current state vars
+ bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // check if there are any new states
+ if ( Cudd_bddLeq( dd, bNext, bReached ) )
+ break;
+ // get the new states
+ bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+ // minimize the new states with the reached states
+// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+// Cudd_RecursiveDeref( dd, bTemp );
+ // add to the reached states
+ bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bNext );
+ // minimize the transition relation
+// bRelation = Cudd_bddConstrain( dd, bTemp = bRelation, Cudd_Not(bReached) ); Cudd_Ref( bRelation );
+// Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_RecursiveDeref( dd, bRelation );
+ Cudd_RecursiveDeref( dd, bCubeCs );
+ Cudd_RecursiveDeref( dd, bNext );
+ // report the stats
+ if ( fVerbose )
+ {
+ nMints = (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) );
+ fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters );
+ fprintf( stdout, "The number of minterms in the reachable state set = %d. (%6.2f %%)\n", nMints, 100.0*nMints/(1<<Abc_NtkLatchNum(pNtk)) );
+ }
+//PRB( dd, bReached );
+ Cudd_Deref( bReached );
+ return Cudd_Not( bReached );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the EXDC network.]
+
+ Description [The set of unreachable states depends on CS variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNode, * pNodeNew;
+ int * pPermute;
+ int i;
+
+ // start the new network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
+ pNtkNew->pName = Extra_UtilStrsav( "exdc" );
+ pNtkNew->pSpec = NULL;
+
+ // create PIs corresponding to LOs
+ Abc_NtkForEachLatchOutput( pNtk, pNode, i )
+ Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pNode), NULL );
+ // cannot ADD POs here because pLatch->pCopy point to the PIs
+
+ // create a new node
+ pNodeNew = Abc_NtkCreateNode(pNtkNew);
+ // add the fanins corresponding to latch outputs
+ Abc_NtkForEachLatchOutput( pNtk, pNode, i )
+ Abc_ObjAddFanin( pNodeNew, pNode->pCopy );
+
+ // create the logic function
+ pPermute = ALLOC( int, dd->size );
+ for ( i = 0; i < dd->size; i++ )
+ pPermute[i] = -1;
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ pPermute[Abc_NtkPiNum(pNtk) + i] = i;
+ // remap the functions
+ pNodeNew->pData = Extra_TransferPermute( dd, pNtkNew->pManFunc, bUnreach, pPermute ); Cudd_Ref( pNodeNew->pData );
+ free( pPermute );
+ Abc_NodeMinimumBase( pNodeNew );
+
+ // for each CO, create PO (skip POs equal to CIs because of name conflict)
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+ Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL );
+ Abc_NtkForEachLatchInput( pNtk, pNode, i )
+ Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL );
+
+ // link to the POs of the network
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ Abc_NtkForEachLatchInput( pNtk, pNode, i )
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+
+ // remove the extra nodes
+ Abc_AigCleanup( pNtkNew->pManFunc );
+
+ // fix the problem with complemented and duplicated CO edges
+ Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
+
+ // transform the network to the SOP representation
+ if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
+ {
+ printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
+ return pNtkNew;
+// return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c
new file mode 100644
index 00000000..9c9bbcfd
--- /dev/null
+++ b/src/base/abci/abcVerify.c
@@ -0,0 +1,1018 @@
+/**CFile****************************************************************
+
+ FileName [abcVerify.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Combinational and sequential verification for two networks.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcVerify.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fraig.h"
+#include "sim.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel );
+extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Verifies combinational equivalence by brute-force SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit )
+{
+ extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+ Abc_Ntk_t * pMiter;
+ Abc_Ntk_t * pCnf;
+ int RetValue;
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiter );
+ printf( "Networks are equivalent after structural hashing.\n" );
+ return;
+ }
+
+ // convert the miter into a CNF
+ pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 );
+ Abc_NtkDelete( pMiter );
+ if ( pCnf == NULL )
+ {
+ printf( "Renoding for CNF has failed.\n" );
+ return;
+ }
+
+ // solve the CNF using the SAT solver
+ RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL );
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (SAT solver timed out).\n" );
+ else if ( RetValue == 0 )
+ printf( "Networks are NOT EQUIVALENT after SAT.\n" );
+ else
+ printf( "Networks are equivalent after SAT.\n" );
+ if ( pCnf->pModel )
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel );
+ FREE( pCnf->pModel );
+ Abc_NtkDelete( pCnf );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Verifies sequential equivalence by fraiging followed by SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose )
+{
+ Prove_Params_t Params, * pParams = &Params;
+// Fraig_Params_t Params;
+// Fraig_Man_t * pMan;
+ Abc_Ntk_t * pMiter;
+ int RetValue;
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
+ if ( RetValue == 1 )
+ {
+ printf( "Networks are equivalent after structural hashing.\n" );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
+/*
+ // convert the miter into a FRAIG
+ Fraig_ParamsSetDefault( &Params );
+ Params.fVerbose = fVerbose;
+ Params.nSeconds = nSeconds;
+// Params.fFuncRed = 0;
+// Params.nPatsRand = 0;
+// Params.nPatsDyna = 0;
+ pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 );
+ Fraig_ManProveMiter( pMan );
+
+ // analyze the result
+ RetValue = Fraig_ManCheckMiter( pMan );
+ // report the result
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (SAT solver timed out on the final miter).\n" );
+ else if ( RetValue == 1 )
+ printf( "Networks are equivalent after fraiging.\n" );
+ else if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, Fraig_ManReadModel(pMan) );
+ }
+ else assert( 0 );
+ // delete the fraig manager
+ Fraig_ManFree( pMan );
+ // delete the miter
+ Abc_NtkDelete( pMiter );
+*/
+ // solve the CNF using the SAT solver
+ Prove_ParamsSetDefault( pParams );
+ pParams->nItersMax = 5;
+// RetValue = Abc_NtkMiterProve( &pMiter, pParams );
+// pParams->fVerbose = 1;
+ RetValue = Abc_NtkIvyProve( &pMiter, pParams );
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (resource limits is reached).\n" );
+ else if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ else
+ printf( "Networks are NOT EQUIVALENT.\n" );
+ free( pSimInfo );
+ }
+ else
+ printf( "Networks are equivalent.\n" );
+ if ( pMiter->pModel )
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies sequential equivalence by fraiging followed by SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose )
+{
+ extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ Prove_Params_t Params, * pParams = &Params;
+ Abc_Ntk_t * pMiter, * pMiterPart;
+ Abc_Obj_t * pObj;
+ int i, RetValue, Status, nOutputs;
+
+ // solve the CNF using the SAT solver
+ Prove_ParamsSetDefault( pParams );
+ pParams->nItersMax = 5;
+ // pParams->fVerbose = 1;
+
+ assert( nPartSize > 0 );
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
+ if ( RetValue == 1 )
+ {
+ printf( "Networks are equivalent after structural hashing.\n" );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+ // solve the problem iteratively for each output of the miter
+ Status = 1;
+ nOutputs = 0;
+ Abc_NtkForEachPo( pMiter, pObj, i )
+ {
+ if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) )
+ {
+ if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0
+ RetValue = 1;
+ else
+ RetValue = 0;
+ pMiterPart = NULL;
+ }
+ else
+ {
+ // get the cone of this output
+ pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 );
+ if ( Abc_ObjFaninC0(pObj) )
+ Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 );
+ // solve the cone
+ // RetValue = Abc_NtkMiterProve( &pMiterPart, pParams );
+ RetValue = Abc_NtkIvyProve( &pMiterPart, pParams );
+ }
+
+ if ( RetValue == -1 )
+ {
+ printf( "Networks are undecided (resource limits is reached).\r" );
+ Status = -1;
+ }
+ else if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ else
+ printf( "Networks are NOT EQUIVALENT. \n" );
+ free( pSimInfo );
+ Status = 0;
+ break;
+ }
+ else
+ {
+ printf( "Finished part %5d (out of %5d)\r", i+1, Abc_NtkPoNum(pMiter) );
+ nOutputs += nPartSize;
+ }
+// if ( pMiter->pModel )
+// Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ if ( pMiterPart )
+ Abc_NtkDelete( pMiterPart );
+ }
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+ if ( Status == 1 )
+ printf( "Networks are equivalent. \n" );
+ else if ( Status == -1 )
+ printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) );
+ Abc_NtkDelete( pMiter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies sequential equivalence by fraiging followed by SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose )
+{
+ extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd );
+ extern Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose );
+ extern void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOnePtr );
+ extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
+ extern void * Abc_FrameGetGlobalFrame();
+
+ Vec_Ptr_t * vParts, * vOnePtr;
+ Vec_Int_t * vOne;
+ Prove_Params_t Params, * pParams = &Params;
+ Abc_Ntk_t * pMiter, * pMiterPart;
+ int i, RetValue, Status, nOutputs;
+
+ // solve the CNF using the SAT solver
+ Prove_ParamsSetDefault( pParams );
+ pParams->nItersMax = 5;
+ // pParams->fVerbose = 1;
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 1 );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
+ Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
+ if ( RetValue == 1 )
+ {
+ printf( "Networks are equivalent after structural hashing.\n" );
+ Abc_NtkDelete( pMiter );
+ return;
+ }
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
+
+ // partition the outputs
+ vParts = Abc_NtkPartitionSmart( pMiter, 300, 0 );
+
+ // fraig each partition
+ Status = 1;
+ nOutputs = 0;
+ vOnePtr = Vec_PtrAlloc( 1000 );
+ Vec_PtrForEachEntry( vParts, vOne, i )
+ {
+ // get this part of the miter
+ Abc_NtkConvertCos( pMiter, vOne, vOnePtr );
+ pMiterPart = Abc_NtkCreateConeArray( pMiter, vOnePtr, 0 );
+ Abc_NtkCombinePos( pMiterPart, 0 );
+ // check the miter for being constant
+ RetValue = Abc_NtkMiterIsConstant( pMiterPart );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after partitioning.\n" );
+ Abc_NtkDelete( pMiterPart );
+ break;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiterPart );
+ continue;
+ }
+ printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r",
+ i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pMiterPart), Abc_NtkPoNum(pMiterPart),
+ Abc_NtkNodeNum(pMiterPart), Abc_AigLevel(pMiterPart) );
+ // solve the problem
+ RetValue = Abc_NtkIvyProve( &pMiterPart, pParams );
+ if ( RetValue == -1 )
+ {
+ printf( "Networks are undecided (resource limits is reached).\r" );
+ Status = -1;
+ }
+ else if ( RetValue == 0 )
+ {
+ int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel );
+ if ( pSimInfo[0] != 1 )
+ printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
+ else
+ printf( "Networks are NOT EQUIVALENT. \n" );
+ free( pSimInfo );
+ Status = 0;
+ Abc_NtkDelete( pMiterPart );
+ break;
+ }
+ else
+ {
+// printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) );
+ nOutputs += Vec_IntSize(vOne);
+ }
+ Abc_NtkDelete( pMiterPart );
+ }
+ printf( " \r" );
+ Vec_VecFree( (Vec_Vec_t *)vParts );
+ Vec_PtrFree( vOnePtr );
+
+ Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );
+
+ if ( Status == 1 )
+ printf( "Networks are equivalent. \n" );
+ else if ( Status == -1 )
+ printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) );
+ Abc_NtkDelete( pMiter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies sequential equivalence by brute-force SAT.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames )
+{
+ extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
+ Abc_Ntk_t * pMiter;
+ Abc_Ntk_t * pFrames;
+ Abc_Ntk_t * pCnf;
+ int RetValue;
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ Abc_NtkDelete( pMiter );
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ return;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiter );
+ printf( "Networks are equivalent after structural hashing.\n" );
+ return;
+ }
+
+ // create the timeframes
+ pFrames = Abc_NtkFrames( pMiter, nFrames, 1 );
+ Abc_NtkDelete( pMiter );
+ if ( pFrames == NULL )
+ {
+ printf( "Frames computation has failed.\n" );
+ return;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pFrames );
+ if ( RetValue == 0 )
+ {
+ Abc_NtkDelete( pFrames );
+ printf( "Networks are NOT EQUIVALENT after framing.\n" );
+ return;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pFrames );
+ printf( "Networks are equivalent after framing.\n" );
+ return;
+ }
+
+ // convert the miter into a CNF
+ pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 );
+ Abc_NtkDelete( pFrames );
+ if ( pCnf == NULL )
+ {
+ printf( "Renoding for CNF has failed.\n" );
+ return;
+ }
+
+ // solve the CNF using the SAT solver
+ RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL );
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (SAT solver timed out).\n" );
+ else if ( RetValue == 0 )
+ printf( "Networks are NOT EQUIVALENT after SAT.\n" );
+ else
+ printf( "Networks are equivalent after SAT.\n" );
+ Abc_NtkDelete( pCnf );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies combinational equivalence by fraiging followed by SAT]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose )
+{
+ Fraig_Params_t Params;
+ Fraig_Man_t * pMan;
+ Abc_Ntk_t * pMiter;
+ Abc_Ntk_t * pFrames;
+ int RetValue;
+
+ // get the miter of the two networks
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
+ if ( pMiter == NULL )
+ {
+ printf( "Miter computation has failed.\n" );
+ return 0;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
+ // report the error
+ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames );
+ Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames );
+ FREE( pMiter->pModel );
+ Abc_NtkDelete( pMiter );
+ return 0;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pMiter );
+ printf( "Networks are equivalent after structural hashing.\n" );
+ return 1;
+ }
+
+ // create the timeframes
+ pFrames = Abc_NtkFrames( pMiter, nFrames, 1 );
+ Abc_NtkDelete( pMiter );
+ if ( pFrames == NULL )
+ {
+ printf( "Frames computation has failed.\n" );
+ return 0;
+ }
+ RetValue = Abc_NtkMiterIsConstant( pFrames );
+ if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after framing.\n" );
+ // report the error
+ pFrames->pModel = Abc_NtkVerifyGetCleanModel( pFrames, 1 );
+// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pFrames->pModel, nFrames );
+ FREE( pFrames->pModel );
+ Abc_NtkDelete( pFrames );
+ return 0;
+ }
+ if ( RetValue == 1 )
+ {
+ Abc_NtkDelete( pFrames );
+ printf( "Networks are equivalent after framing.\n" );
+ return 1;
+ }
+
+ // convert the miter into a FRAIG
+ Fraig_ParamsSetDefault( &Params );
+ Params.fVerbose = fVerbose;
+ Params.nSeconds = nSeconds;
+// Params.fFuncRed = 0;
+// Params.nPatsRand = 0;
+// Params.nPatsDyna = 0;
+ pMan = Abc_NtkToFraig( pFrames, &Params, 0, 0 );
+ Fraig_ManProveMiter( pMan );
+
+ // analyze the result
+ RetValue = Fraig_ManCheckMiter( pMan );
+ // report the result
+ if ( RetValue == -1 )
+ printf( "Networks are undecided (SAT solver timed out on the final miter).\n" );
+ else if ( RetValue == 1 )
+ printf( "Networks are equivalent after fraiging.\n" );
+ else if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, Fraig_ManReadModel(pMan), nFrames );
+ }
+ else assert( 0 );
+ // delete the fraig manager
+ Fraig_ManFree( pMan );
+ // delete the miter
+ Abc_NtkDelete( pFrames );
+ return RetValue == 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns a dummy pattern full of zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames )
+{
+ int * pModel = ALLOC( int, Abc_NtkCiNum(pNtk) * nFrames );
+ memset( pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) * nFrames );
+ return pModel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the PO values under the given input pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel )
+{
+ Abc_Obj_t * pNode;
+ int * pValues, Value0, Value1, i;
+ int fStrashed = 0;
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk = Abc_NtkStrash(pNtk, 0, 0, 0);
+ fStrashed = 1;
+ }
+/*
+ printf( "Counter example: " );
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ printf( " %d", pModel[i] );
+ printf( "\n" );
+*/
+ // increment the trav ID
+ Abc_NtkIncrementTravId( pNtk );
+ // set the CI values
+ Abc_AigConst1(pNtk)->pCopy = (void *)1;
+ Abc_NtkForEachCi( pNtk, pNode, i )
+ pNode->pCopy = (void *)pModel[i];
+ // simulate in the topological order
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Value0 = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode);
+ Value1 = ((int)Abc_ObjFanin1(pNode)->pCopy) ^ Abc_ObjFaninC1(pNode);
+ pNode->pCopy = (void *)(Value0 & Value1);
+ }
+ // fill the output values
+ pValues = ALLOC( int, Abc_NtkCoNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pNode, i )
+ pValues[i] = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode);
+ if ( fStrashed )
+ Abc_NtkDelete( pNtk );
+ return pValues;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Reports mismatch between the two networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNode;
+ int * pValues1, * pValues2;
+ int nErrors, nPrinted, i, iNode = -1;
+
+ assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) );
+ assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) );
+ // get the CO values under this model
+ pValues1 = Abc_NtkVerifySimulatePattern( pNtk1, pModel );
+ pValues2 = Abc_NtkVerifySimulatePattern( pNtk2, pModel );
+ // count the mismatches
+ nErrors = 0;
+ for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ )
+ nErrors += (int)( pValues1[i] != pValues2[i] );
+ printf( "Verification failed for at least %d outputs: ", nErrors );
+ // print the first 3 outputs
+ nPrinted = 0;
+ for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ )
+ if ( pValues1[i] != pValues2[i] )
+ {
+ if ( iNode == -1 )
+ iNode = i;
+ printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) );
+ if ( ++nPrinted == 3 )
+ break;
+ }
+ if ( nPrinted != nErrors )
+ printf( " ..." );
+ printf( "\n" );
+ // report mismatch for the first output
+ if ( iNode >= 0 )
+ {
+ printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n",
+ Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] );
+ printf( "Input pattern: " );
+ // collect PIs in the cone
+ pNode = Abc_NtkCo(pNtk1,iNode);
+ vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 );
+ // set the PI numbers
+ Abc_NtkForEachCi( pNtk1, pNode, i )
+ pNode->pCopy = (void*)i;
+ // print the model
+ pNode = Vec_PtrEntry( vNodes, 0 );
+ if ( Abc_ObjIsCi(pNode) )
+ {
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ assert( Abc_ObjIsCi(pNode) );
+ printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)pNode->pCopy] );
+ }
+ }
+ printf( "\n" );
+ Vec_PtrFree( vNodes );
+ }
+ free( pValues1 );
+ free( pValues2 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the COs in the support of the PO in the given frame.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkGetSeqPoSupp( Abc_Ntk_t * pNtk, int iFrame, int iNumPo )
+{
+ Abc_Ntk_t * pFrames;
+ Abc_Obj_t * pObj, * pNodePo;
+ Vec_Ptr_t * vSupp;
+ int i, k;
+ // get the timeframes of the network
+ pFrames = Abc_NtkFrames( pNtk, iFrame + 1, 0 );
+//Abc_NtkShowAig( pFrames );
+
+ // get the PO of the timeframes
+ pNodePo = Abc_NtkPo( pFrames, iFrame * Abc_NtkPoNum(pNtk) + iNumPo );
+ // set the support
+ vSupp = Abc_NtkNodeSupport( pFrames, &pNodePo, 1 );
+ // mark the support of the frames
+ Abc_NtkForEachCi( pFrames, pObj, i )
+ pObj->pCopy = NULL;
+ Vec_PtrForEachEntry( vSupp, pObj, i )
+ pObj->pCopy = (void *)1;
+ // mark the support of the network if the support of the timeframes is marked
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = NULL;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( Abc_NtkBox(pFrames, i)->pCopy )
+ pObj->pCopy = (void *)1;
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ for ( k = 0; k <= iFrame; k++ )
+ if ( Abc_NtkPi(pFrames, k*Abc_NtkPiNum(pNtk) + i)->pCopy )
+ pObj->pCopy = (void *)1;
+ // free stuff
+ Vec_PtrFree( vSupp );
+ Abc_NtkDelete( pFrames );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports mismatch between the two sequential networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames )
+{
+ Vec_Ptr_t * vInfo1, * vInfo2;
+ Abc_Obj_t * pObj, * pObjError, * pObj1, * pObj2;
+ int ValueError1, ValueError2;
+ unsigned * pPats1, * pPats2;
+ int i, o, k, nErrors, iFrameError, iNodePo, nPrinted;
+ int fRemove1 = 0, fRemove2 = 0;
+
+ if ( !Abc_NtkIsStrash(pNtk1) )
+ fRemove1 = 1, pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 );
+ if ( !Abc_NtkIsStrash(pNtk2) )
+ fRemove2 = 1, pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 );
+
+ // simulate sequential circuits
+ vInfo1 = Sim_SimulateSeqModel( pNtk1, nFrames, pModel );
+ vInfo2 = Sim_SimulateSeqModel( pNtk2, nFrames, pModel );
+
+ // look for a discrepancy in the PO values
+ nErrors = 0;
+ pObjError = NULL;
+ for ( i = 0; i < nFrames; i++ )
+ {
+ if ( pObjError )
+ break;
+ Abc_NtkForEachPo( pNtk1, pObj1, o )
+ {
+ pObj2 = Abc_NtkPo( pNtk2, o );
+ pPats1 = Sim_SimInfoGet(vInfo1, pObj1);
+ pPats2 = Sim_SimInfoGet(vInfo2, pObj2);
+ if ( pPats1[i] == pPats2[i] )
+ continue;
+ nErrors++;
+ if ( pObjError == NULL )
+ {
+ pObjError = pObj1;
+ iFrameError = i;
+ iNodePo = o;
+ ValueError1 = (pPats1[i] > 0);
+ ValueError2 = (pPats2[i] > 0);
+ }
+ }
+ }
+
+ if ( pObjError == NULL )
+ {
+ printf( "No output mismatches detected.\n" );
+ Sim_UtilInfoFree( vInfo1 );
+ Sim_UtilInfoFree( vInfo2 );
+ if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+ if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
+ return;
+ }
+
+ printf( "Verification failed for at least %d output%s of frame %d: ", nErrors, (nErrors>1? "s":""), iFrameError+1 );
+ // print the first 3 outputs
+ nPrinted = 0;
+ Abc_NtkForEachPo( pNtk1, pObj1, o )
+ {
+ pObj2 = Abc_NtkPo( pNtk2, o );
+ pPats1 = Sim_SimInfoGet(vInfo1, pObj1);
+ pPats2 = Sim_SimInfoGet(vInfo2, pObj2);
+ if ( pPats1[iFrameError] == pPats2[iFrameError] )
+ continue;
+ printf( " %s", Abc_ObjName(pObj1) );
+ if ( ++nPrinted == 3 )
+ break;
+ }
+ if ( nPrinted != nErrors )
+ printf( " ..." );
+ printf( "\n" );
+
+ // mark CIs of the networks in the cone of influence of this output
+ Abc_NtkGetSeqPoSupp( pNtk1, iFrameError, iNodePo );
+ Abc_NtkGetSeqPoSupp( pNtk2, iFrameError, iNodePo );
+
+ // report mismatch for the first output
+ printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n",
+ Abc_ObjName(pObjError), ValueError1, ValueError2 );
+
+ printf( "The cone of influence of output %s in Network1:\n", Abc_ObjName(pObjError) );
+ printf( "PIs: " );
+ Abc_NtkForEachPi( pNtk1, pObj, i )
+ if ( pObj->pCopy )
+ printf( "%s ", Abc_ObjName(pObj) );
+ printf( "\n" );
+ printf( "Latches: " );
+ Abc_NtkForEachLatch( pNtk1, pObj, i )
+ if ( pObj->pCopy )
+ printf( "%s ", Abc_ObjName(pObj) );
+ printf( "\n" );
+
+ printf( "The cone of influence of output %s in Network2:\n", Abc_ObjName(pObjError) );
+ printf( "PIs: " );
+ Abc_NtkForEachPi( pNtk2, pObj, i )
+ if ( pObj->pCopy )
+ printf( "%s ", Abc_ObjName(pObj) );
+ printf( "\n" );
+ printf( "Latches: " );
+ Abc_NtkForEachLatch( pNtk2, pObj, i )
+ if ( pObj->pCopy )
+ printf( "%s ", Abc_ObjName(pObj) );
+ printf( "\n" );
+
+ // print the patterns
+ for ( i = 0; i <= iFrameError; i++ )
+ {
+ printf( "Frame %d: ", i+1 );
+
+ printf( "PI(1):" );
+ Abc_NtkForEachPi( pNtk1, pObj, k )
+ if ( pObj->pCopy )
+ printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 );
+ printf( " " );
+ printf( "L(1):" );
+ Abc_NtkForEachLatch( pNtk1, pObj, k )
+ if ( pObj->pCopy )
+ printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 );
+ printf( " " );
+ printf( "%s(1):", Abc_ObjName(pObjError) );
+ printf( "%d", Sim_SimInfoGet(vInfo1, pObjError)[i] > 0 );
+
+ printf( " " );
+
+ printf( "PI(2):" );
+ Abc_NtkForEachPi( pNtk2, pObj, k )
+ if ( pObj->pCopy )
+ printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 );
+ printf( " " );
+ printf( "L(2):" );
+ Abc_NtkForEachLatch( pNtk2, pObj, k )
+ if ( pObj->pCopy )
+ printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 );
+ printf( " " );
+ printf( "%s(2):", Abc_ObjName(pObjError) );
+ printf( "%d", Sim_SimInfoGet(vInfo2, pObjError)[i] > 0 );
+
+ printf( "\n" );
+ }
+ Abc_NtkForEachCi( pNtk1, pObj, i )
+ pObj->pCopy = NULL;
+ Abc_NtkForEachCi( pNtk2, pObj, i )
+ pObj->pCopy = NULL;
+
+ Sim_UtilInfoFree( vInfo1 );
+ Sim_UtilInfoFree( vInfo2 );
+ if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
+ if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates buggy miter emailed by Mike.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkSimulteBuggyMiter( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ int * pModel1, * pModel2, * pResult1, * pResult2;
+ char * vPiValues1 = "01001011100000000011010110101000000";
+ char * vPiValues2 = "11001101011101011111110100100010001";
+
+ assert( strlen(vPiValues1) == (unsigned)Abc_NtkPiNum(pNtk) );
+ assert( 1 == Abc_NtkPoNum(pNtk) );
+
+ pModel1 = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pModel1[i] = vPiValues1[i] - '0';
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pModel1[Abc_NtkPiNum(pNtk)+i] = ((int)pObj->pData) - 1;
+
+ pResult1 = Abc_NtkVerifySimulatePattern( pNtk, pModel1 );
+ printf( "Value = %d\n", pResult1[0] );
+
+ pModel2 = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pModel2[i] = vPiValues2[i] - '0';
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pModel2[Abc_NtkPiNum(pNtk)+i] = pResult1[Abc_NtkPoNum(pNtk)+i];
+
+ pResult2 = Abc_NtkVerifySimulatePattern( pNtk, pModel2 );
+ printf( "Value = %d\n", pResult2[0] );
+
+ free( pModel1 );
+ free( pModel2 );
+ free( pResult1 );
+ free( pResult2 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcXsim.c b/src/base/abci/abcXsim.c
new file mode 100644
index 00000000..5d9e4634
--- /dev/null
+++ b/src/base/abci/abcXsim.c
@@ -0,0 +1,227 @@
+/**CFile****************************************************************
+
+ FileName [abcXsim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Using X-valued simulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcXsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define XVS0 ABC_INIT_ZERO
+#define XVS1 ABC_INIT_ONE
+#define XVSX ABC_INIT_DC
+
+static inline void Abc_ObjSetXsim( Abc_Obj_t * pObj, int Value ) { pObj->pCopy = (void *)Value; }
+static inline int Abc_ObjGetXsim( Abc_Obj_t * pObj ) { return (int)pObj->pCopy; }
+static inline int Abc_XsimInv( int Value )
+{
+ if ( Value == XVS0 )
+ return XVS1;
+ if ( Value == XVS1 )
+ return XVS0;
+ assert( Value == XVSX );
+ return XVSX;
+}
+static inline int Abc_XsimAnd( int Value0, int Value1 )
+{
+ if ( Value0 == XVS0 || Value1 == XVS0 )
+ return XVS0;
+ if ( Value0 == XVSX || Value1 == XVSX )
+ return XVSX;
+ assert( Value0 == XVS1 && Value1 == XVS1 );
+ return XVS1;
+}
+static inline int Abc_XsimRand2()
+{
+ return (rand() & 1) ? XVS1 : XVS0;
+}
+static inline int Abc_XsimRand3()
+{
+ int RetValue;
+ do {
+ RetValue = rand() & 3;
+ } while ( RetValue == 0 );
+ return RetValue;
+}
+static inline int Abc_ObjGetXsimFanin0( Abc_Obj_t * pObj )
+{
+ int RetValue;
+ RetValue = Abc_ObjGetXsim(Abc_ObjFanin0(pObj));
+ return Abc_ObjFaninC0(pObj)? Abc_XsimInv(RetValue) : RetValue;
+}
+static inline int Abc_ObjGetXsimFanin1( Abc_Obj_t * pObj )
+{
+ int RetValue;
+ RetValue = Abc_ObjGetXsim(Abc_ObjFanin1(pObj));
+ return Abc_ObjFaninC1(pObj)? Abc_XsimInv(RetValue) : RetValue;
+}
+static inline void Abc_XsimPrint( FILE * pFile, int Value )
+{
+ if ( Value == XVS0 )
+ {
+ fprintf( pFile, "0" );
+ return;
+ }
+ if ( Value == XVS1 )
+ {
+ fprintf( pFile, "1" );
+ return;
+ }
+ assert( Value == XVSX );
+ fprintf( pFile, "x" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs X-valued simulation of the sequential network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ int i, f;
+ assert( Abc_NtkIsStrash(pNtk) );
+ srand( 0x12341234 );
+ // start simulation
+ Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 );
+ if ( fXInputs )
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, XVSX );
+ }
+ else
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+ }
+ if ( fXState )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX );
+ }
+ else
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) );
+ }
+ // simulate and print the result
+ fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" );
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) );
+ // print out
+ fprintf( stdout, "%2d : ", f );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) );
+ fprintf( stdout, " : " );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+// if ( Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) != XVSX )
+// printf( " %s=", Abc_ObjName(pObj) );
+ Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) );
+ }
+ fprintf( stdout, " : " );
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) );
+ if ( Abc_NtkAssertNum(pNtk) )
+ {
+ fprintf( stdout, " : " );
+ Abc_NtkForEachAssert( pNtk, pObj, i )
+ Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) );
+ }
+ fprintf( stdout, "\n" );
+ // assign input values
+ if ( fXInputs )
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, XVSX );
+ }
+ else
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+ }
+ // transfer the latch values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cycles the circuit to create a new initial state.]
+
+ Description [Simulates the circuit with random input for the given
+ number of timeframes to get a better initial state.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ int i, f;
+ assert( Abc_NtkIsStrash(pNtk) );
+ srand( 0x12341234 );
+ // initialize the values
+ Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 );
+ // simulate for the given number of timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) );
+ // assign input values
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+ // transfer the latch values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) );
+ }
+ // set the final values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pData = (void *)Abc_ObjGetXsim(Abc_ObjFanout0(pObj));
+}
+
+///////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abc_.c b/src/base/abci/abc_.c
new file mode 100644
index 00000000..75ec88c3
--- /dev/null
+++ b/src/base/abci/abc_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [abc_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abc_new.h b/src/base/abci/abc_new.h
new file mode 100644
index 00000000..3460bb38
--- /dev/null
+++ b/src/base/abci/abc_new.h
@@ -0,0 +1,23 @@
+struct Abc_Obj_t_ // 6 words
+{
+ Abc_Obj_t * pCopy; // the copy of this object
+ Abc_Ntk_t * pNtk; // the host network
+ int Id; // the object ID
+ int TravId; // the traversal ID
+ int nRefs; // the number of fanouts
+ unsigned Type : 4; // the object type
+ unsigned fMarkA : 1; // the multipurpose mark
+ unsigned fMarkB : 1; // the multipurpose mark
+ unsigned fPhase : 1; // the flag to mark the phase of equivalent node
+ unsigned fPersist: 1; // marks the persistant AIG node
+ unsigned nFanins : 24; // the level of the node
+ Abc_Obj_t * Fanins[0]; // the array of fanins
+};
+
+struct Abc_Pin_t_ // 4 words
+{
+ Abc_Pin_t * pNext;
+ Abc_Pin_t * pPrev;
+ Abc_Obj_t * pFanin;
+ Abc_Obj_t * pFanout;
+};
diff --git a/src/base/abci/module.make b/src/base/abci/module.make
new file mode 100644
index 00000000..4558119e
--- /dev/null
+++ b/src/base/abci/module.make
@@ -0,0 +1,54 @@
+SRC += src/base/abci/abc.c \
+ src/base/abci/abcAttach.c \
+ src/base/abci/abcAuto.c \
+ src/base/abci/abcBalance.c \
+ src/base/abci/abcBmc.c \
+ src/base/abci/abcCas.c \
+ src/base/abci/abcClpBdd.c \
+ src/base/abci/abcClpSop.c \
+ src/base/abci/abcCut.c \
+ src/base/abci/abcDar.c \
+ src/base/abci/abcDebug.c \
+ src/base/abci/abcDress.c \
+ src/base/abci/abcDsd.c \
+ src/base/abci/abcEspresso.c \
+ src/base/abci/abcExtract.c \
+ src/base/abci/abcFpga.c \
+ src/base/abci/abcFpgaFast.c \
+ src/base/abci/abcFraig.c \
+ src/base/abci/abcFxu.c \
+ src/base/abci/abcGen.c \
+ src/base/abci/abcHaig.c \
+ src/base/abci/abcIf.c \
+ src/base/abci/abcIvy.c \
+ src/base/abci/abcLut.c \
+ src/base/abci/abcMap.c \
+ src/base/abci/abcMini.c \
+ src/base/abci/abcMiter.c \
+ src/base/abci/abcMulti.c \
+ src/base/abci/abcNtbdd.c \
+ src/base/abci/abcOdc.c \
+ src/base/abci/abcOrder.c \
+ src/base/abci/abcPart.c \
+ src/base/abci/abcPrint.c \
+ src/base/abci/abcProve.c \
+ src/base/abci/abcQbf.c \
+ src/base/abci/abcQuant.c \
+ src/base/abci/abcRec.c \
+ src/base/abci/abcReconv.c \
+ src/base/abci/abcRefactor.c \
+ src/base/abci/abcRenode.c \
+ src/base/abci/abcReorder.c \
+ src/base/abci/abcRestruct.c \
+ src/base/abci/abcResub.c \
+ src/base/abci/abcRewrite.c \
+ src/base/abci/abcRr.c \
+ src/base/abci/abcSat.c \
+ src/base/abci/abcStrash.c \
+ src/base/abci/abcSweep.c \
+ src/base/abci/abcSymm.c \
+ src/base/abci/abcTiming.c \
+ src/base/abci/abcUnate.c \
+ src/base/abci/abcUnreach.c \
+ src/base/abci/abcVerify.c \
+ src/base/abci/abcXsim.c