summaryrefslogtreecommitdiffstats
path: root/src/base/abci
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/abci')
-rw-r--r--src/base/abci/abc.c10812
-rw-r--r--src/base/abci/abcAttach.c12
-rw-r--r--src/base/abci/abcAuto.c239
-rw-r--r--src/base/abci/abcBalance.c427
-rw-r--r--src/base/abci/abcBmc.c115
-rw-r--r--src/base/abci/abcCas.c111
-rw-r--r--src/base/abci/abcClpBdd.c (renamed from src/base/abci/abcCollapse.c)63
-rw-r--r--src/base/abci/abcClpSop.c53
-rw-r--r--src/base/abci/abcCut.c494
-rw-r--r--src/base/abci/abcDar.c1196
-rw-r--r--src/base/abci/abcDebug.c208
-rw-r--r--src/base/abci/abcDress.c209
-rw-r--r--src/base/abci/abcDsd.c102
-rw-r--r--src/base/abci/abcEspresso.c250
-rw-r--r--src/base/abci/abcExtract.c51
-rw-r--r--src/base/abci/abcFpga.c44
-rw-r--r--src/base/abci/abcFpgaFast.c190
-rw-r--r--src/base/abci/abcFraig.c446
-rw-r--r--src/base/abci/abcFxu.c19
-rw-r--r--src/base/abci/abcGen.c511
-rw-r--r--src/base/abci/abcHaig.c179
-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.c100
-rw-r--r--src/base/abci/abcMeasure.c478
-rw-r--r--src/base/abci/abcMini.c153
-rw-r--r--src/base/abci/abcMiter.c778
-rw-r--r--src/base/abci/abcMulti.c643
-rw-r--r--src/base/abci/abcMv.c369
-rw-r--r--src/base/abci/abcNtbdd.c389
-rw-r--r--src/base/abci/abcOdc.c1134
-rw-r--r--src/base/abci/abcOrder.c131
-rw-r--r--src/base/abci/abcPart.c890
-rw-r--r--src/base/abci/abcPlace.c255
-rw-r--r--src/base/abci/abcPrint.c536
-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.c32
-rw-r--r--src/base/abci/abcRefactor.c51
-rw-r--r--src/base/abci/abcRenode.c651
-rw-r--r--src/base/abci/abcReorder.c102
-rw-r--r--src/base/abci/abcRestruct.c1497
-rw-r--r--src/base/abci/abcResub.c1952
-rw-r--r--src/base/abci/abcRewrite.c281
-rw-r--r--src/base/abci/abcRr.c999
-rw-r--r--src/base/abci/abcSat.c776
-rw-r--r--src/base/abci/abcStrash.c441
-rw-r--r--src/base/abci/abcSweep.c586
-rw-r--r--src/base/abci/abcSymm.c29
-rw-r--r--src/base/abci/abcTiming.c250
-rw-r--r--src/base/abci/abcUnate.c155
-rw-r--r--src/base/abci/abcUnreach.c70
-rw-r--r--src/base/abci/abcVerify.c817
-rw-r--r--src/base/abci/abcXsim.c224
-rw-r--r--src/base/abci/abc_.c5
-rw-r--r--src/base/abci/abc_new.h23
-rw-r--r--src/base/abci/module.make34
60 files changed, 32329 insertions, 2814 deletions
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index e067a646..f0905155 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -23,81 +23,178 @@
#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_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_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_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandShowAig ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_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_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_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
-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_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandOneOutput ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandOneNode ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
-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_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_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandDar ( Abc_Frame_t * pAbc, int argc, char ** argv );
-
-static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+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_CommandEliminate ( 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_CommandInter ( 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_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_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_CommandDRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandFlowRetime ( 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_CommandSim ( 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_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandIndcut ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEnlarge ( 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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -113,78 +210,178 @@ static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv
***********************************************************************/
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, "Printing", "show_aig", Abc_CommandShowAig, 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", "eliminate", Abc_CommandEliminate, 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", "sat", Abc_CommandSat, 0 );
Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 );
- Cmd_CommandAdd( pAbc, "Various", "one_output", Abc_CommandOneOutput, 1 );
- Cmd_CommandAdd( pAbc, "Various", "one_node", Abc_CommandOneNode, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "cone", Abc_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", "inter", Abc_CommandInter, 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", "haig", Abc_CommandHaig, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "mini", Abc_CommandMini, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "qbf", Abc_CommandQbf, 0 );
+
Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_store", Abc_CommandFraigStore, 0 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_restore", Abc_CommandFraigRestore, 1 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 );
+ Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 );
+
+ Cmd_CommandAdd( pAbc, "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, "Sequential", "seq", Abc_CommandSeq, 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", "dretime", Abc_CommandDRetime, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "fretime", Abc_CommandFlowRetime, 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, "Sequential", "sim", Abc_CommandSim, 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", "iprove", Abc_CommandIProve, 1 );
+ Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "bmc", Abc_CommandBmc, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "indcut", Abc_CommandIndcut, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "enlarge", Abc_CommandEnlarge, 1 );
+
+// Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 );
+// Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 );
// Rwt_Man4ExploreStart();
// Map_Var3Print();
// Map_Var4Test();
- Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 );
- Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 );
- Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 );
- Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 );
+// Abc_NtkPrint256();
+// Kit_TruthCountMintermsPrecomp();
+// Kit_DsdPrecompute4Vars();
+
{
extern void Dar_LibStart();
Dar_LibStart();
}
-}
+}
/**Function*************************************************************
@@ -199,16 +396,20 @@ void Abc_Init( Abc_Frame_t * pAbc )
***********************************************************************/
void Abc_End()
{
- Abc_NtkFraigStoreClean();
-// Rwt_Man4ExplorePrint();
- {
- extern void Dar_LibStop();
- Dar_LibStop();
- }
+// Dar_LibDumpPriorities();
+
{
extern void Cnf_ClearMemory();
Cnf_ClearMemory();
}
+ {
+ extern void Dar_LibStop();
+ Dar_LibStop();
+ }
+
+ Abc_NtkFraigStoreClean();
+// Rwt_Man4ExplorePrint();
+
}
/**Function*************************************************************
@@ -230,15 +431,15 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fFactor;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set the defaults
fShort = 1;
fFactor = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "sfh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sfh" ) ) != EOF )
{
switch ( c )
{
@@ -257,7 +458,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( pNtk == NULL )
{
- fprintf( Abc_FrameReadErr(pAbc), "Empty network\n" );
+ fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" );
return 1;
}
Abc_NtkPrintStats( pOut, pNtk, fFactor );
@@ -265,7 +466,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
fprintf( pErr, "usage: print_stats [-fh]\n" );
- fprintf( pErr, "\t prints the network statistics and\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;
@@ -282,6 +483,98 @@ usage:
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;
@@ -289,13 +582,13 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Obj_t * pNode;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -312,18 +605,18 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintFanio( pOut, pNode );
@@ -358,13 +651,13 @@ int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -408,13 +701,13 @@ int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -453,6 +746,58 @@ usage:
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;
@@ -461,14 +806,14 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fUseRealNames;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseRealNames = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
{
switch ( c )
{
@@ -494,18 +839,18 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintFactor( pOut, pNode, fUseRealNames );
@@ -541,19 +886,24 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
Abc_Obj_t * pNode;
int c;
+ int fListNodes;
int fProfile;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fProfile = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ph" ) ) != EOF )
+ 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;
@@ -576,30 +926,31 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintLevel( pOut, pNode );
return 0;
}
// process all COs
- Abc_NtkPrintLevel( pOut, pNtk, fProfile );
+ Abc_NtkPrintLevel( pOut, pNtk, fProfile, fListNodes );
return 0;
usage:
- fprintf( pErr, "usage: print_level [-ph] <node>\n" );
+ 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");
@@ -623,20 +974,26 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
+ fStruct = 1;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
{
switch ( c )
{
+ case 's':
+ fStruct ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -652,9 +1009,17 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
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.\n" );
+ fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" );
return 1;
}
if ( !Abc_NtkIsStrash(pNtk) )
@@ -668,8 +1033,9 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: print_supp [-vh]\n" );
+ 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;
@@ -693,19 +1059,21 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fUseBdds;
int fNaive;
+ int fReorder;
int fVerbose;
- extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fVerbose );
+ extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseBdds = 0;
fNaive = 0;
+ fReorder = 1;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "bnvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF )
{
switch ( c )
{
@@ -715,6 +1083,9 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'n':
fNaive ^= 1;
break;
+ case 'r':
+ fReorder ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -731,7 +1102,82 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
}
if ( !Abc_NtkIsComb(pNtk) )
{
- fprintf( pErr, "This command works only for combinational networks.\n" );
+ 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) )
@@ -739,13 +1185,95 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" );
return 1;
}
- Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fVerbose );
+ Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose );
return 0;
usage:
- fprintf( pErr, "usage: print_symm [-nbvh]\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, "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");
@@ -763,24 +1291,30 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandPrintKMap( 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 );
+ int fUseRealNames;
+
+ extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ fUseRealNames = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
{
switch ( c )
{
+ case 'n':
+ fUseRealNames ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -794,35 +1328,106 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks.\n" );
+ fprintf( pErr, "Visualization of Karnaugh maps works for logic networks.\n" );
return 1;
}
-
- if ( argc != util_optind + 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;
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
- if ( pNode == NULL )
+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 )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ 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_NodeShowBdd( pNode );
+ 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: 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\n");
+ 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;
}
@@ -838,49 +1443,156 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandPrintSharing( 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 );
+ int fUseLibrary;
+
+ extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- nNodeSizeMax = 10;
- nConeSizeMax = ABC_INFINITY;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "NCh" ) ) != EOF )
+ 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 ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- nNodeSizeMax = atoi(argv[util_optind]);
- util_optind++;
- if ( nNodeSizeMax < 0 )
+ nCofLevel = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCofLevel < 0 )
goto usage;
break;
- case 'C':
- if ( util_optind >= argc )
- {
- fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
- goto usage;
- }
- nConeSizeMax = atoi(argv[util_optind]);
- util_optind++;
- if ( nConeSizeMax < 0 )
- goto usage;
+ case 'c':
+ fCofactor ^= 1;
break;
case 'h':
goto usage;
@@ -894,38 +1606,205 @@ int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
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;
- if ( !Abc_NtkIsStrash(pNtk) )
+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 )
{
- fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" );
+ 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 != util_optind + 1 )
+
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
-
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
- if ( pNode == NULL )
+ if ( argc == globalUtilOptind )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
- return 1;
+ 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;
+ }
}
- Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax );
+ 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_cut [-N num] [-C num] [-h] <node>\n" );
- fprintf( pErr, " visualizes the cut of a node using DOT and GSVIEW\n" );
+ 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, "\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");
+ 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;
}
@@ -940,23 +1819,50 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandShowAig( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
int c;
- extern void Abc_NtkShowAig( Abc_Ntk_t * pNtk );
+ int nNodeSizeMax;
+ int nConeSizeMax;
+ extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ 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:
@@ -972,20 +1878,35 @@ int Abc_CommandShowAig( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( pErr, "Visualizing AIG can only be done for AIGs (run \"strash\").\n" );
+ 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_NtkShowAig( pNtk );
+ Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax );
return 0;
usage:
- fprintf( pErr, "usage: show_aig [-h]\n" );
- fprintf( pErr, " visualizes the AIG with choices using DOT and GSVIEW\n" );
+ 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-h : print the command usage\n");
+ 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;
}
@@ -1005,18 +1926,46 @@ 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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ 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:
@@ -1038,11 +1987,11 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv )
// get the new network
if ( Abc_NtkIsStrash(pNtk) )
- pNtkRes = Abc_NtkCollapse( pNtk, 1 );
+ pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose );
else
{
- pNtk = Abc_NtkStrash( pNtk, 0, 0 );
- pNtkRes = Abc_NtkCollapse( pNtk, 1 );
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose );
Abc_NtkDelete( pNtk );
}
if ( pNtkRes == NULL )
@@ -1055,9 +2004,13 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: collapse [-h]\n" );
- fprintf( pErr, "\t collapses the network by constructing global BDDs\n" );
- fprintf( pErr, "\t-h : print the command usage\n");
+ 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;
}
@@ -1079,17 +2032,19 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
int fAllNodes;
+ int fRecord;
int fCleanup;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fAllNodes = 0;
fCleanup = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ach" ) ) != EOF )
+ fRecord = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "acrh" ) ) != EOF )
{
switch ( c )
{
@@ -1099,6 +2054,9 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'c':
fCleanup ^= 1;
break;
+ case 'r':
+ fRecord ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1113,7 +2071,7 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
- pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup );
+ pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Strashing has failed.\n" );
@@ -1124,10 +2082,11 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: strash [-ach]\n" );
+ 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;
}
@@ -1148,22 +2107,32 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp;
int c;
- int fDuplicate;
+ bool fDuplicate;
+ bool fSelective;
+ bool fUpdateLevel;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ fDuplicate = 0;
+ fSelective = 0;
+ fUpdateLevel = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ldsh" ) ) != EOF )
{
switch ( c )
{
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
case 'd':
fDuplicate ^= 1;
break;
+ case 's':
+ fSelective ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1176,21 +2145,20 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
-
// get the new network
if ( Abc_NtkIsStrash(pNtk) )
{
- pNtkRes = Abc_NtkBalance( pNtk, fDuplicate );
+ pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel );
}
else
{
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 );
+ 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 );
+ pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel );
Abc_NtkDelete( pNtkTemp );
}
@@ -1205,9 +2173,11 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: balance [-dh]\n" );
+ fprintf( pErr, "usage: balance [-ldsh]\n" );
fprintf( pErr, "\t transforms the current network into a well-balanced AIG\n" );
+ fprintf( pErr, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -1223,7 +2193,7 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
@@ -1231,8 +2201,10 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -1240,32 +2212,33 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
nThresh = 1;
nFaninMax = 20;
fCnf = 0;
- fMulti = 0;
+ fMulti = 1;
fSimple = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "TFmcsh" ) ) != EOF )
+ fFactor = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF )
{
switch ( c )
{
case 'T':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
goto usage;
}
- nThresh = atoi(argv[util_optind]);
- util_optind++;
+ nThresh = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nThresh < 0 )
goto usage;
break;
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFaninMax = atoi(argv[util_optind]);
- util_optind++;
+ nFaninMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFaninMax < 0 )
goto usage;
break;
@@ -1278,6 +2251,9 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
case 's':
fSimple ^= 1;
break;
+ case 'f':
+ fFactor ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1297,7 +2273,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
- pNtkRes = Abc_NtkRenode( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple );
+ pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Renoding has failed.\n" );
@@ -1308,15 +2284,16 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: renode [-T num] [-F num] [-cmsh]\n" );
+ 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 doing so prevents duplication of 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 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;
@@ -1333,19 +2310,191 @@ usage:
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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1367,7 +2516,7 @@ int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
// modify the current network
- Abc_NtkCleanup( pNtk, 0 );
+ Abc_NtkCleanup( pNtk, 1 );
return 0;
usage:
@@ -1394,13 +2543,13 @@ int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1416,9 +2565,9 @@ int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
- if ( !Abc_NtkIsSopLogic(pNtk) && !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Sweep cannot be performed on an AIG or a mapped network (unmap it first).\n" );
+ fprintf( pErr, "The classical (SIS-like) sweep can only be performed on a logic network.\n" );
return 1;
}
// modify the current network
@@ -1453,7 +2602,7 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
extern bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
extern void Abc_NtkFxuFreeInfo( Fxu_Data_t * p );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -1461,37 +2610,49 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
p = ALLOC( Fxu_Data_t, 1 );
memset( p, 0, sizeof(Fxu_Data_t) );
// set the defaults
- p->nPairsMax = 30000;
- p->nNodesExt = 10000;
- p->fOnlyS = 0;
- p->fOnlyD = 0;
- p->fUse0 = 0;
- p->fUseCompl = 1;
- p->fVerbose = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "LNsdzcvh")) != EOF )
+ 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 'L':
- if ( util_optind >= argc )
+ 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 \"-L\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
goto usage;
}
- p->nPairsMax = atoi(argv[util_optind]);
- util_optind++;
+ p->nPairsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( p->nPairsMax < 0 )
goto usage;
break;
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- p->nNodesExt = atoi(argv[util_optind]);
- util_optind++;
+ p->nNodesExt = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( p->nNodesExt < 0 )
goto usage;
break;
@@ -1516,7 +2677,7 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
default:
goto usage;
}
- }
+ }
if ( pNtk == NULL )
{
@@ -1546,10 +2707,11 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: fx [-N num] [-L num] [-sdzcvh]\n");
+ 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-L num : the maximum number of cube pairs to consider [default = %d]\n", p->nPairsMax );
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" );
@@ -1571,6 +2733,97 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandEliminate( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ FILE * pOut, * pErr;
+ int nMaxSize;
+ int fReverse;
+ int fVerbose;
+ int c;
+ extern int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ nMaxSize = 8;
+ fReverse = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "Nrvh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nMaxSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxSize <= 0 )
+ goto usage;
+ break;
+ case 'r':
+ fReverse ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( Abc_NtkNodeNum(pNtk) == 0 )
+ {
+ fprintf( pErr, "The network does not have internal nodes.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to a logic network (run \"renode\" or \"if\").\n" );
+ return 1;
+ }
+
+ // the nodes to be merged are linked into the special linked list
+ Abc_NtkEliminate( pNtk, nMaxSize, fReverse, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: eliminate [-N num] [-rvh]\n");
+ fprintf( pErr, "\t greedily eliminates nodes by collapsing them into fanouts\n");
+ fprintf( pErr, "\t-N num : the maximum support size after collapsing [default = %d]\n", nMaxSize );
+ fprintf( pErr, "\t-r : use the reverse topological order [default = %s]\n", fReverse? "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_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
@@ -1580,7 +2833,7 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -1590,8 +2843,8 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
fVerbose = 0;
fPrint = 0;
fShort = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "grvpsh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF )
{
switch ( c )
{
@@ -1630,7 +2883,7 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
// get the new network
if ( !Abc_NtkIsStrash(pNtk) )
{
- pNtkNew = Abc_NtkStrash( pNtk, 0, 0 );
+ pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 );
pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort );
Abc_NtkDelete( pNtkNew );
}
@@ -1661,7 +2914,7 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
{
if ( !Abc_NtkIsBddLogic( pNtk ) )
{
- fprintf( pErr, "This command is only applicable to logic BDD networks.\n" );
+ 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" );
@@ -1693,31 +2946,324 @@ usage:
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->nCands = 5;
+ pPars->nSimWords = 4;
+ pPars->nGrowthLevel = 0;
+ pPars->fArea = 0;
+ pPars->fVerbose = 0;
+ pPars->fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'W':
+ if ( globalUtilOptind >= argc )
+ {
+ 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 (there is another command for resynthesis after LUT mapping, \"lutpack\")\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-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-L <num> : the largest increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
+ 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 determines LUT size as the max fanin count of a node;\n" );
+ fprintf( pErr, "\t if the network is not LUT-mapped, packs it into 6-LUTs\n" );
+ fprintf( pErr, "\t (there is another command for resynthesis after LUT mapping, \"imfs\")\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();
- extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUseZeros, int fVerbose );
+ extern void Rwr_Precompute();
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fPrecompute = 0;
- fUseZeros = 0;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "xzvh" ) ) != EOF )
+ 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;
@@ -1727,6 +3273,12 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'v':
fVerbose ^= 1;
break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'p':
+ fPlaceEnable ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -1757,7 +3309,7 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// modify the current network
- if ( !Abc_NtkRewrite( pNtk, fUseZeros, fVerbose ) )
+ if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) )
{
fprintf( pErr, "Rewriting has failed.\n" );
return 1;
@@ -1765,13 +3317,16 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: rewrite [-zvh]\n" );
+ 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*************************************************************
@@ -1791,48 +3346,53 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
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 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_FrameReadNet(pAbc);
+ 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;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "NCzdvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF )
{
switch ( c )
{
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- nNodeSizeMax = atoi(argv[util_optind]);
- util_optind++;
+ nNodeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nNodeSizeMax < 0 )
goto usage;
break;
case 'C':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
- nConeSizeMax = atoi(argv[util_optind]);
- util_optind++;
+ nConeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nConeSizeMax < 0 )
goto usage;
break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
case 'z':
fUseZeros ^= 1;
break;
@@ -1872,7 +3432,7 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// modify the current network
- if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUseZeros, fUseDcs, fVerbose ) )
+ if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) )
{
fprintf( pErr, "Refactoring has failed.\n" );
return 1;
@@ -1880,10 +3440,11 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: refactor [-N num] [-C num] [-zdvh]\n" );
+ 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" );
@@ -1891,6 +3452,452 @@ usage:
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int 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*************************************************************
@@ -1909,13 +3916,13 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1932,14 +3939,14 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( !Abc_NtkIsNetlist( pNtk ) )
+ if ( !Abc_NtkIsStrash( pNtk ) )
{
- fprintf( pErr, "This command is only applicable to netlists.\n" );
+ fprintf( pErr, "This command is only applicable to strashed networks.\n" );
return 1;
}
// get the new network
- pNtkRes = Abc_NtkNetlistToLogic( pNtk );
+ pNtkRes = Abc_NtkToLogic( pNtk );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Converting to a logic network has failed.\n" );
@@ -1951,7 +3958,66 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
fprintf( pErr, "usage: logic [-h]\n" );
- fprintf( pErr, "\t transforms a netlist into a logic network\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;
}
@@ -1969,6 +4035,7 @@ usage:
***********************************************************************/
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;
@@ -1977,19 +4044,32 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fCheck;
int fComb;
+ int nPartSize;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fComb = 1;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ 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;
@@ -1998,13 +4078,13 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
return 1;
// compute the miter
- pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb );
+ pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize );
if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
@@ -2019,14 +4099,325 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: miter [-ch] <file1> <file2>\n" );
- fprintf( pErr, "\t computes the miter of the two circuits\n" );
- fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
+ 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");
- 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_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;
}
@@ -2049,27 +4440,27 @@ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv )
int nFrames;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fInitial = 0;
nFrames = 5;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Fih" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fih" ) ) != EOF )
{
switch ( c )
{
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
- if ( nFrames < 0 )
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames <= 0 )
goto usage;
break;
case 'i':
@@ -2091,7 +4482,7 @@ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv )
// get the new network
if ( !Abc_NtkIsStrash(pNtk) )
{
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 );
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial );
Abc_NtkDelete( pNtkTemp );
}
@@ -2131,38 +4522,40 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
+ int fDirect;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ 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;
}
-
- // get the new network
- if ( !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Converting to SOP is possible when node functions are BDDs.\n" );
+ fprintf( pErr, "Converting to SOP is possible only for logic networks.\n" );
return 1;
}
- if ( !Abc_NtkBddToSop( pNtk ) )
+ if ( !Abc_NtkToSop(pNtk, fDirect) )
{
fprintf( pErr, "Converting to SOP has failed.\n" );
return 1;
@@ -2170,8 +4563,9 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: sop [-h]\n" );
- fprintf( pErr, "\t converts node functions from BDD to SOP\n" );
+ 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;
}
@@ -2193,13 +4587,13 @@ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2209,20 +4603,22 @@ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
-
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
-
- // get the new network
- if ( !Abc_NtkIsSopLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Converting to BDD is possible when node functions are SOPs.\n" );
+ fprintf( pErr, "Converting to BDD is possible only for logic networks.\n" );
return 1;
}
- if ( !Abc_NtkSopToBdd( pNtk ) )
+ 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;
@@ -2231,7 +4627,7 @@ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
fprintf( pErr, "usage: bdd [-h]\n" );
- fprintf( pErr, "\t converts node functions from SOP to BDD\n" );
+ fprintf( pErr, "\t converts node functions to BDD\n" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -2247,19 +4643,19 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
- Abc_Ntk_t * pNtk, * pNtkRes;
+ Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2269,35 +4665,32 @@ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
-
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
-
- if ( !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsLogic(pNtk) )
{
- fprintf( pErr, "Only a BDD logic network can be converted to MUXes.\n" );
+ fprintf( pErr, "Converting to AIG is possible only for logic networks.\n" );
return 1;
}
-
- // get the new network
- pNtkRes = Abc_NtkBddToMuxes( pNtk );
- if ( pNtkRes == NULL )
+ if ( Abc_NtkIsAigLogic(pNtk) )
{
- fprintf( pErr, "Converting to MUXes has failed.\n" );
+ 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;
}
- // 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");
+ 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;
}
@@ -2312,21 +4705,22 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
+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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
@@ -2345,32 +4739,173 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
- if ( Abc_NtkLatchNum(pNtk) > 0 )
+
+ // get the new network
+ if ( !Abc_NtkIsBddLogic(pNtk) )
{
- fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
- return 0;
+ fprintf( pErr, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" );
+ return 1;
}
- if ( !Abc_NtkIsLogic(pNtk) )
+ 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 )
{
- fprintf( stdout, "This command can only be applied to logic network (run \"renode -c\").\n" );
- return 0;
+ switch ( c )
+ {
+ case 'r':
+ fReverse ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
}
- if ( Abc_NtkIsMappedLogic(pNtk) )
- Abc_NtkUnmap(pNtk);
- if ( Abc_NtkIsSopLogic(pNtk) )
- Abc_NtkSopToBdd(pNtk);
- if ( Abc_NtkMiterSat( pNtk, fVerbose ) )
- printf( "The miter is satisfiable.\n" );
+ 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
- printf( "The miter is unsatisfiable.\n" );
+ Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose );
return 0;
usage:
- fprintf( pErr, "usage: sat [-vh]\n" );
- fprintf( pErr, "\t solves the miter\n" );
+ 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;
}
@@ -2394,14 +4929,14 @@ int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv )
int fVerbose;
extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, bool fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
@@ -2427,7 +4962,7 @@ int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv )
}
if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( stdout, "This command works only for AIGs (run \"strash\").\n" );
+ fprintf( stdout, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" );
return 0;
}
if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) )
@@ -2456,38 +4991,42 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
- Abc_Obj_t * pNode;
+ Abc_Obj_t * pNode, * pNodeCo;
int c;
int fUseAllCis;
+ int fUseMffc;
int Output;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseAllCis = 0;
+ fUseMffc = 0;
Output = -1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Oah" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Omah" ) ) != EOF )
{
switch ( c )
{
case 'O':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" );
goto usage;
}
- Output = atoi(argv[util_optind]);
- util_optind++;
+ Output = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( Output < 0 )
goto usage;
break;
+ case 'm':
+ fUseMffc ^= 1;
case 'a':
fUseAllCis ^= 1;
break;
@@ -2510,27 +5049,31 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ pNodeCo = NULL;
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindCo( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find CO node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
- pNtkRes = Abc_NtkSplitOutput( pNtk, pNode, fUseAllCis );
+ if ( fUseMffc )
+ pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] );
+ else
+ pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis );
}
else
{
if ( Output == -1 )
{
- fprintf( pErr, "The output is not specified.\n" );
+ fprintf( pErr, "The node is not specified.\n" );
return 1;
}
if ( Output >= Abc_NtkCoNum(pNtk) )
@@ -2538,11 +5081,17 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) );
return 1;
}
- pNtkRes = Abc_NtkSplitOutput( pNtk, Abc_NtkCo(pNtk,Output), fUseAllCis );
+ pNodeCo = Abc_NtkCo( pNtk, Output );
+ if ( fUseMffc )
+ pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) );
+ else
+ pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis );
}
+ if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) )
+ printf( "The extracted cone represents the complement function of the CO.\n" );
if ( pNtkRes == NULL )
{
- fprintf( pErr, "Splitting one output has failed.\n" );
+ fprintf( pErr, "Writing the logic cone of one node has failed.\n" );
return 1;
}
// replace the current network
@@ -2550,12 +5099,13 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: one_output [-O num] [-ah] <name>\n" );
- fprintf( pErr, "\t replaces the current network by the logic cone of one output\n" );
+ fprintf( pErr, "usage: cone [-O num] [-amh] <name>\n" );
+ fprintf( pErr, "\t replaces the current network by one logic cone\n" );
fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" );
+ fprintf( pErr, "\t-m : toggle writing only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" );
fprintf( pErr, "\t-h : print the command usage\n");
- fprintf( pErr, "\t-O num : (optional) the 0-based number of the output\n");
- fprintf( pErr, "\tname : (optional) the name of the output\n");
+ fprintf( pErr, "\t-O num : (optional) the 0-based number of the CO to extract\n");
+ fprintf( pErr, "\tname : (optional) the name of the node to extract\n");
return 1;
}
@@ -2570,20 +5120,20 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
+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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2606,20 +5156,20 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
- pNtkRes = Abc_NtkSplitNode( pNtk, pNode );
+ pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode );
// pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL );
if ( pNtkRes == NULL )
{
@@ -2631,7 +5181,7 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: one_node [-h] <name>\n" );
+ fprintf( pErr, "usage: node [-h] <name>\n" );
fprintf( pErr, "\t replaces the current network by the network composed of one node\n" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "\tname : the node name\n");
@@ -2639,6 +5189,173 @@ usage:
}
+/**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*************************************************************
@@ -2657,13 +5374,13 @@ int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2700,73 +5417,301 @@ usage:
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_FrameReadNet(pAbc);
+ 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 = 250; // the max number of cuts kept at a node
- pParams->fTruth = 1; // compute truth tables
- pParams->fHash = 0; // hash cuts to detect unique
- pParams->fFilter = 0; // filter dominated cuts
- pParams->fSeq = 0; // compute sequential 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
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "KMtrfsdvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzmvoh" ) ) != EOF )
{
switch ( c )
{
case 'K':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nVarsMax = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nVarsMax < 0 )
goto usage;
break;
case 'M':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nKeepMax = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nKeepMax < 0 )
goto usage;
break;
case 't':
pParams->fTruth ^= 1;
break;
- case 'r':
- pParams->fHash ^= 1;
- break;
case 'f':
pParams->fFilter ^= 1;
break;
- case 's':
- pParams->fSeq ^= 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:
@@ -2784,22 +5729,45 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
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 );
- Cut_ManPrintStats( pCutMan );
+ 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] [-trfsdvh]\n" );
+ 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 (4 <= num <= 6) [default = %d]\n", 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-r : toggle reduction by hashing [default = %s]\n", pParams->fHash? "yes": "no" );
- fprintf( pErr, "\t-f : toggle filtering by dominance [default = %s]\n", pParams->fFilter? "yes": "no" );
- fprintf( pErr, "\t-s : toggle sequential cut computation [default = %s]\n", pParams->fSeq? "yes": "no" );
- fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" );
- fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
+ 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;
}
@@ -2815,22 +5783,540 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
+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_CommandInter( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes, * pNtk1, * pNtk2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int c, fDelete1, fDelete2;
+ int fVerbose;
+ extern Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, 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;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+ if ( nArgcNew == 0 )
+ {
+ printf( "Deriving new circuit structure for the current network.\n" );
+ Abc_ObjXorFaninC( Abc_NtkPo(pNtk2,0), 0 );
+ }
+ pNtkRes = Abc_NtkInter( pNtk1, pNtk2, fVerbose );
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 0;
+ }
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: inter [-vh] <fileOnSet> <fileOffSet>\n" );
+ fprintf( pErr, "\t derives interpolant of two networks (onset and offset)\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_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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ 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:
@@ -2842,8 +6328,143 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
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 fBmc;
+ int nFrames;
+ int nLevels;
+ int fVerbose;
+ int fVeryVerbose;
+// 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 );
+ extern Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk );
+// extern void Abc_NtkDarTestBlif( char * pFileName );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ printf( "This command is temporarily disabled.\n" );
+ return 0;
+
+ // set defaults
+ fVeryVerbose = 0;
+ fVerbose = 1;
+ fBmc = 1;
+ nFrames = 1;
+ nLevels = 200;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FNbvwh" ) ) != 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 '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 'b':
+ fBmc ^= 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_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_NtkMiterForCofactors( pNtk, 0, 0, -1 );
+// pNtkRes = Abc_NtkNewAig( pNtk );
+
+/*
+ pNtkRes = NULL;
if ( pNtkRes == NULL )
{
fprintf( pErr, "Command has failed.\n" );
@@ -2851,16 +6472,1937 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
- return 0;
+*/
+
+// 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 );
+*/
+// Abc_NtkDarHaigRecord( pNtk );
+// Abc_NtkDarClau( pNtk, nFrames, nLevels, fBmc, fVerbose, fVeryVerbose );
+/*
+ if ( globalUtilOptind != 1 )
+ {
+ fprintf( pErr, "Command has failed.\n" );
+ return 1;
+ }
+ Abc_NtkDarTestBlif( argv[globalUtilOptind] );
+*/
+ return 0;
usage:
- fprintf( pErr, "usage: test [-h]\n" );
+ fprintf( pErr, "usage: test [-vwh]\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-w : toggle printing very verbose 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_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_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*************************************************************
@@ -2881,61 +8423,65 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
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_FrameReadNet(pAbc);
+ 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 = 99; // 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 = 0; // 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
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "RDBrscpvah" ) ) != EOF )
+ 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 ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nPatsRand = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nPatsRand = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nPatsRand < 0 )
goto usage;
break;
case 'D':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nPatsDyna = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nPatsDyna = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nPatsDyna < 0 )
goto usage;
break;
- case 'B':
- if ( util_optind >= argc )
+ case 'C':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nBTLimit = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nBTLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nBTLimit < 0 )
goto usage;
break;
@@ -2955,9 +8501,15 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
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:
@@ -2980,13 +8532,28 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
pParams->fVerboseP = pParams->fTryProve;
// get the new network
- if ( Abc_NtkIsStrash(pNtk) )
- pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes );
+ 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
{
- pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes );
- pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes );
- Abc_NtkDelete( pNtk );
+ 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 )
{
@@ -3003,17 +8570,20 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
sprintf( Buffer, "%d", pParams->nBTLimit );
- fprintf( pErr, "usage: fraig [-R num] [-D num] [-B num] [-rscpvah]\n" );
+ 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 (there are also newer fraiging commands, \"ifraig\" and \"dfraig\")\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-B num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer );
+ 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 final miter [default = %s]\n", pParams->fTryProve? "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;
}
@@ -3036,14 +8606,14 @@ int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fDuplicate;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -3100,14 +8670,14 @@ int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fDuplicate;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -3161,14 +8731,14 @@ int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fDuplicate;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -3225,14 +8795,14 @@ int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fDuplicate;
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -3273,26 +8843,37 @@ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fUseInv = 1;
+ fExdc = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ivh" ) ) != EOF )
+ 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:
@@ -3316,7 +8897,7 @@ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
// modify the current network
- if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fVerbose ) )
+ if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) )
{
fprintf( pErr, "Sweeping has failed.\n" );
return 1;
@@ -3324,14 +8905,535 @@ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: fraig_sweep [-vh]\n" );
+ fprintf( pErr, "usage: fraig_sweep [-evwh]\n" );
fprintf( pErr, "\t performs technology-dependent sweep\n" );
-// fprintf( pErr, "\t-i : toggle using inverter for complemented nodes [default = %s]\n", fUseInv? "yes": "no" );
+ 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*************************************************************
@@ -3356,8 +9458,9 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -3367,19 +9470,19 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
fSweep = 1;
fSwitching = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Daspvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF )
{
switch ( c )
{
case 'D':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
goto usage;
}
- DelayTarget = (float)atof(argv[util_optind]);
- util_optind++;
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( DelayTarget <= 0.0 )
goto usage;
break;
@@ -3410,13 +9513,13 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( !Abc_NtkIsStrash(pNtk) )
{
- pNtk = Abc_NtkStrash( pNtk, 0, 0 );
+ 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 );
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtk == NULL )
{
@@ -3446,7 +9549,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
}
if ( fSweep )
- Abc_NtkFraigSweep( pNtkRes, 0, 0 );
+ Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 );
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
@@ -3457,14 +9560,14 @@ usage:
sprintf( Buffer, "not used" );
else
sprintf( Buffer, "%.3f", DelayTarget );
- fprintf( pErr, "usage: map [-D num] [-aspvh]\n" );
- fprintf( pErr, "\t performs standard cell mapping of the current network\n" );
- fprintf( pErr, "\t-D num : 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 activity [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");
+ 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;
}
@@ -3485,15 +9588,14 @@ int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
- extern int Abc_NtkUnmap( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3516,7 +9618,7 @@ int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
- if ( !Abc_NtkUnmap( pNtk ) )
+ if ( !Abc_NtkMapToSop( pNtk ) )
{
fprintf( pErr, "Unmapping has failed.\n" );
return 1;
@@ -3546,15 +9648,14 @@ int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
- extern int Abc_NtkUnmap( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3611,13 +9712,13 @@ int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3636,7 +9737,7 @@ int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( pErr, "Works only for the AIG representation (run \"strash\").\n" );
+ fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" );
return 1;
}
@@ -3671,26 +9772,139 @@ usage:
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;
- extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fVerbose );
+ int nLutSize;
+ float DelayTarget;
- pNtk = Abc_FrameReadNet(pAbc);
+ 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;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "apvh" ) ) != EOF )
+ fRecovery = 1;
+ fSwitching = 0;
+ fLatchPaths = 0;
+ fVerbose = 0;
+ DelayTarget =-1;
+ nLutSize =-1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "aplvhDK" ) ) != EOF )
{
switch ( c )
{
@@ -3700,11 +9914,36 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
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;
}
@@ -3716,16 +9955,26 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
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 );
+ 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 );
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtk == NULL )
{
@@ -3734,7 +9983,7 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
}
fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" );
// get the new network
- pNtkRes = Abc_NtkFpga( pNtk, fRecovery, fSwitching, fVerbose );
+ pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose );
if ( pNtkRes == NULL )
{
Abc_NtkDelete( pNtk );
@@ -3746,7 +9995,7 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
else
{
// get the new network
- pNtkRes = Abc_NtkFpga( pNtk, fRecovery, fSwitching, fVerbose );
+ pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose );
if ( pNtkRes == NULL )
{
fprintf( pErr, "FPGA mapping has failed.\n" );
@@ -3758,16 +10007,160 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: fpga [-apvh]\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-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
- fprintf( pErr, "\t-h : prints the command usage\n");
+ 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*************************************************************
@@ -3780,23 +10173,321 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
{
+ char Buffer[100];
+ char LutSize[100];
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
+ If_Par_t Pars, * pPars = &Pars;
int c;
- extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
+ 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->fEdge = 0;
+ pPars->fCutMin = 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, "KCFADpaflemrstvh" ) ) != 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 'r':
+ pPars->fExpRed ^= 1;
+ break;
+ case 'f':
+ pPars->fFancy ^= 1;
+ break;
+ case 'l':
+ pPars->fLatchPaths ^= 1;
+ break;
+ case 'e':
+ pPars->fEdge ^= 1;
+ break;
+ case 'm':
+ pPars->fCutMin ^= 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;
+ }
+
+ // enable truth table computation if choices are selected
+ if ( Abc_NtkGetChoiceNum( pNtk ) )
+ {
+ printf( "Performing FPGA mapping with choices.\n" );
+ pPars->fTruth = 1;
+ }
+ // enable truth table computation if cut minimization is selected
+ if ( pPars->fCutMin )
+ pPars->fTruth = 1;
+
+ // complain if truth tables are requested but the cut size is too large
+ if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE )
+ {
+ fprintf( pErr, "Truth tables cannot be computed for LUT larger than %d inputs.\n", IF_MAX_FUNC_LUTSIZE );
+ return 1;
+ }
+
+ // disable cut-expansion if edge-based heuristics are selected
+// if ( pPars->fEdge )
+// pPars->fExpRed = 0;
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ // strash and balance the network
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ 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] [-parlemsvh]\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-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" );
+ fprintf( pErr, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" );
+ fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" );
+// fprintf( pErr, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" );
+ 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;
+}
+
+
- pNtk = Abc_FrameReadNet(pAbc);
+/**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
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ 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:
@@ -3810,17 +10501,107 @@ int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- printf( "This command is not yet implemented.\n" );
+ 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 )
+ {
+ srand( time(NULL) );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if ( rand() & 1 )
+ Abc_LatchSetInit1( pObj );
+ else
+ Abc_LatchSetInit0( pObj );
+ }
+ else if ( fDontCare )
+ {
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_LatchSetInitDc( pObj );
+ }
+ else
+ printf( "The initial states remain unchanged.\n" );
return 0;
- if ( !Abc_NtkIsStrash(pNtk) )
+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 )
{
- fprintf( pErr, "Works only for AIG (run \"strash\").\n" );
+ 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_NtkAigToSeq( pNtk );
+ pNtkRes = Abc_NtkRestrashZero( pNtk, 0 );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Converting to sequential AIG has failed.\n" );
@@ -3831,8 +10612,8 @@ int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: seq [-h]\n" );
- fprintf( pErr, "\t converts AIG into sequential AIG (while sweeping latches)\n" );
+ 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;
}
@@ -3848,33 +10629,98 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandUndc( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
- int fForward;
- int fBackward;
- 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;
+ }
+ }
- pNtk = Abc_FrameReadNet(pAbc);
+ 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
- fForward = 0;
- fBackward = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "fbh" ) ) != EOF )
+ nLatches = 5;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF )
{
switch ( c )
{
- case 'f':
- fForward ^= 1;
- break;
- case 'b':
- fBackward ^= 1;
+ 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;
@@ -3889,35 +10735,95 @@ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- printf( "This command is not yet implemented.\n" );
+ 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*************************************************************
- if ( !Abc_NtkIsSeq(pNtk) )
+ 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 )
{
- fprintf( pErr, "Works only for sequential AIG.\n" );
+ 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
- if ( fForward )
- Abc_NtkSeqRetimeForward( pNtk );
- else if ( fBackward )
- Abc_NtkSeqRetimeBackward( pNtk );
- else
- Abc_NtkSeqRetimeDelay( pNtk );
+// 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: retime [-fbh]\n" );
- fprintf( pErr, "\t retimes sequential AIG (default is Pan's algorithm)\n" );
- fprintf( pErr, "\t-f : toggle forward retiming [default = %s]\n", fForward? "yes": "no" );
- fprintf( pErr, "\t-b : toggle backward retiming [default = %s]\n", fBackward? "yes": "no" );
+ 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 []
@@ -3929,69 +10835,67 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
- Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
- int fDelete1, fDelete2;
- char ** pArgvNew;
- int nArgcNew;
+ Abc_Ntk_t * pNtk, * pNtkRes;
int c;
- int fSat;
- int fVerbose;
+ int fShare;
- extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
- extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fVerbose );
-
-
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fSat = 0;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "svh" ) ) != EOF )
+ fShare = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF )
{
switch ( c )
{
case 's':
- fSat ^= 1;
- break;
- case 'v':
- fVerbose ^= 1;
+ fShare ^= 1;
break;
+ case 'h':
+ goto usage;
default:
goto usage;
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
- if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ 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);
- // perform equivalence checking
- if ( fSat )
- Abc_NtkCecSat( pNtk1, pNtk2 );
- else
- Abc_NtkCecFraig( pNtk1, pNtk2, fVerbose );
-
- if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
- if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ // 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: cec [-svh] <file1> <file2>\n" );
- fprintf( pErr, "\t performs combinational equivalence checking\n" );
- fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
- fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "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");
- 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;
}
@@ -4006,84 +10910,142 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandRetime( 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 nFrames;
-
- extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames );
- extern void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames );
-
+ 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_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- nFrames = 3;
- fSat = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Fsh" ) ) != EOF )
+ 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 'F':
- if ( util_optind >= argc )
+ case 'M':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
- if ( nFrames < 0 )
+ Mode = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Mode < 0 )
goto usage;
break;
+ case 'f':
+ fForward ^= 1;
+ break;
+ case 'b':
+ fBackward ^= 1;
+ break;
case 's':
- fSat ^= 1;
+ fOneStep ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
break;
+ case 'h':
+ goto usage;
default:
goto usage;
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
- if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
return 1;
+ }
- // perform equivalence checking
- if ( fSat )
- Abc_NtkSecSat( pNtk1, pNtk2, nFrames );
- else
- Abc_NtkSecFraig( pNtk1, pNtk2, nFrames );
+ if ( fForward && fBackward )
+ {
+ fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" );
+ return 1;
+ }
- if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
- if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
- return 0;
+ if ( !Abc_NtkLatchNum(pNtk) )
+ {
+ fprintf( pErr, "The network has no latches. Retiming is not performed.\n" );
+ return 0;
+ }
-usage:
- fprintf( pErr, "usage: sec [-sh] [-F num] <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-h : print the command usage\n");
- fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames );
- 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;
-}
+ 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*************************************************************
@@ -4096,35 +11058,43 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandDRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
- int c;
- int fLatchSweep;
- int fAutoSweep;
+ int nStepsMax;
+ int fFastAlgo;
int fVerbose;
- extern Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose );
- extern Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk );
+ int c;
+ extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose );
+ extern Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fLatchSweep = 0;
- fAutoSweep = 0;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lavh" ) ) != EOF )
+ nStepsMax = 100000;
+ fFastAlgo = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Savh" ) ) != EOF )
{
switch ( c )
{
- case 'l':
- fLatchSweep ^= 1;
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-S\" should be followed by a positive integer.\n" );
+ goto usage;
+ }
+ nStepsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nStepsMax < 0 )
+ goto usage;
break;
case 'a':
- fAutoSweep ^= 1;
+ fFastAlgo ^= 1;
break;
case 'v':
fVerbose ^= 1;
@@ -4135,27 +11105,33 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
}
}
+
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
- if ( !Abc_NtkIsStrash(pNtk) )
+
+ if ( !Abc_NtkLatchNum(pNtk) )
{
- fprintf( pErr, "Only works for structrally hashed networks.\n" );
- return 1;
+ fprintf( pErr, "The network has no latches. Retiming is not performed.\n" );
+ return 0;
}
- if ( !Abc_NtkLatchNum(pNtk) )
+
+ if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( pErr, "Only works for sequential networks.\n" );
- return 1;
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
}
- // modify the current network
- pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchSweep, fVerbose );
-// pNtkRes = Abc_NtkDar( pNtk );
+
+ // perform the retiming
+ if ( fFastAlgo )
+ pNtkRes = Abc_NtkDarRetime( pNtk, nStepsMax, fVerbose );
+ else
+ pNtkRes = Abc_NtkDarRetimeF( pNtk, nStepsMax, fVerbose );
if ( pNtkRes == NULL )
{
- fprintf( pErr, "Sequential cleanup has failed.\n" );
+ fprintf( pErr, "Retiming has failed.\n" );
return 1;
}
// replace the current network
@@ -4163,18 +11139,14 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
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-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, "usage: dretime [-S num] [-avh]\n" );
+ fprintf( pErr, "\t retimes the current network forward\n" );
+ fprintf( pErr, "\t-S num : the max number of retiming steps to perform [default = %d]\n", nStepsMax );
+ fprintf( pErr, "\t-a : enables a fast algorithm [default = %s]\n", fFastAlgo? "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;
}
-
/**Function*************************************************************
Synopsis []
@@ -4186,51 +11158,68 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
- int c;
- int nFramesP;
- int nConfMax;
+ int c, nMaxIters;
+ int fForward;
+ int fBackward;
int fVerbose;
- extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose );
+ int fComputeInit;
+ int maxDelay;
+
+ extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInit,
+ int fForward, int fBackward, int nMaxIters,
+ int maxDelay);
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- nFramesP = 0;
- nConfMax = 10000;
- fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "PCvh" ) ) != EOF )
+ fForward = 0;
+ fBackward = 0;
+ fComputeInit = 1;
+ fVerbose = 0;
+ nMaxIters = 999;
+ maxDelay = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "MDfbivh" ) ) != EOF )
{
switch ( c )
{
- case 'P':
- if ( util_optind >= argc )
+ case 'M':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" );
goto usage;
}
- nFramesP = atoi(argv[util_optind]);
- util_optind++;
- if ( nFramesP < 0 )
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nMaxIters < 0 )
goto usage;
break;
- case 'C':
- if ( util_optind >= argc )
+ case 'D':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-D\" should be followed by a positive integer.\n" );
goto usage;
}
- nConfMax = atoi(argv[util_optind]);
- util_optind++;
- if ( nConfMax < 0 )
+ maxDelay = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( maxDelay < 0 )
goto usage;
break;
+ case 'f':
+ fForward ^= 1;
+ break;
+ case 'i':
+ fComputeInit ^= 1;
+ break;
+ case 'b':
+ fBackward ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -4247,34 +11236,295 @@ int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( Abc_NtkIsComb(pNtk) )
+ if ( fForward && fBackward )
{
- fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" );
+ fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" );
return 1;
}
- if ( !Abc_NtkIsStrash(pNtk) )
+ if ( !Abc_NtkLatchNum(pNtk) )
{
- printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ fprintf( pErr, "The network has no latches. Retiming is not performed.\n" );
return 0;
}
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "Retiming with choice nodes is not implemented.\n" );
+ return 0;
+ }
+
+ // perform the retiming
+ pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit, fForward, fBackward, nMaxIters, maxDelay );
+
+ if (pNtkRes != pNtk)
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: fretime [-M num] [-D num] [-fbvih]\n" );
+ fprintf( pErr, "\t retimes the current network using flow-based algorithm\n" );
+ fprintf( pErr, "\t-M num : the maximum number of iterations [default = %d]\n", nMaxIters );
+ fprintf( pErr, "\t-D num : the maximum delay [default = none]\n" );
+ fprintf( pErr, "\t-i : enables init state computation [default = %s]\n", fComputeInit? "yes": "no" );
+ fprintf( pErr, "\t-f : enables forward-only retiming [default = %s]\n", fForward? "yes": "no" );
+ fprintf( pErr, "\t-b : enables backward-only retiming [default = %s]\n", fBackward? "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;
+}
+
+/**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 = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose );
+// pNtkRes = Seq_NtkFpgaMapRetime( pNtkNew, nMaxIters, fVerbose );
+ pNtkRes = NULL;
if ( pNtkRes == NULL )
{
- fprintf( pErr, "Sequential sweeping has failed.\n" );
+// 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: 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, "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;
@@ -4307,7 +11557,7 @@ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
int fVerbose;
extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFrames, int nMaxImps, int nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -4321,52 +11571,52 @@ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
fLatchCorr = 0;
fWriteImps = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "PFILirlevh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "PFILirlevh" ) ) != EOF )
{
switch ( c )
{
case 'P':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
goto usage;
}
- nFramesP = atoi(argv[util_optind]);
- util_optind++;
+ nFramesP = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFramesP < 0 )
goto usage;
break;
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFramesK = atoi(argv[util_optind]);
- util_optind++;
+ nFramesK = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFramesK <= 0 )
goto usage;
break;
case 'I':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
goto usage;
}
- nMaxImps = atoi(argv[util_optind]);
- util_optind++;
+ nMaxImps = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nMaxImps <= 0 )
goto usage;
break;
case 'L':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
goto usage;
}
- nMaxLevs = atoi(argv[util_optind]);
- util_optind++;
+ nMaxLevs = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nMaxLevs <= 0 )
goto usage;
break;
@@ -4422,13 +11672,13 @@ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: ssweep [-P num] [-F num] [-lrevh]\n" );
+ 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 num : max number of implications to consider [default = %d]\n", nMaxImps );
fprintf( pErr, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", nMaxLevs );
-// fprintf( pErr, "\t-i : toggle using implications [default = %s]\n", fUseImps? "yes": "no" );
+ 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" );
@@ -4448,6 +11698,928 @@ usage:
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-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_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int nWords;
+ int fVerbose;
+ extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 32;
+ nWords = 8;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FWvh" ) ) != 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 'W':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nWords = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nWords < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ 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;
+ }
+
+ FREE( pNtk->pSeqModel );
+ Abc_NtkDarSeqSim( pNtk, nFrames, nWords, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: sim [-F num] [-W num] [-vh]\n" );
+ fprintf( pErr, "\t performs random simulation of the sequentail miter\n" );
+ fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-W num : the number of words to simulate [default = %d]\n", nWords );
+ fprintf( pErr, "\t-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 (there is also an unbounded SEC commands, \"dsec\" and \"dprove\")\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;
@@ -4463,7 +12635,7 @@ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
extern int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose );
- pNtk = Abc_FrameReadNet(pAbc);
+ pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
@@ -4472,19 +12644,19 @@ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
fRetimeFirst = 1;
fVerbose = 0;
fVeryVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Krwvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF )
{
switch ( c )
{
case 'K':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFrames < 0 )
goto usage;
break;
@@ -4502,8 +12674,8 @@ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
return 1;
@@ -4535,6 +12707,1092 @@ usage:
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, "Frwvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ 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 [-F num] [-rwvh]\n" );
+ fprintf( pErr, "\t performs SEC on the sequential miter\n" );
+ fprintf( pErr, "\t-F num : the limit on the depth of induction [default = %d]\n", 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 (there is also a newer SAT solving command \"dsat\")\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 (there are also newer CEC commands, \"iprove\" and \"dprove\")\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_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nFrames;
+ int nBTLimit;
+ int fRewrite;
+ int fVerbose;
+
+// extern void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose );
+ extern int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nFrames, int nBTLimit, int fRewrite, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 5;
+ nBTLimit = 1000000;
+ fRewrite = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FCrvh" ) ) != 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 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nBTLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nBTLimit < 0 )
+ goto usage;
+ break;
+ case 'r':
+ fRewrite ^= 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( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+ Abc_NtkDarBmc( pNtk, nFrames, nBTLimit, fRewrite, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: bmc [-F num] [-C num] [-rvh]\n" );
+ fprintf( pErr, "\t perform bounded model checking\n" );
+ fprintf( pErr, "\t-F num : number of time frames [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit );
+ fprintf( pErr, "\t-r : toggle initialization of the first frame [default = %s]\n", fRewrite? "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_CommandIndcut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int nFrames;
+ int nPref;
+ int nClauses;
+ int nLutSize;
+ int nLevels;
+ int nCutsMax;
+ int nBatches;
+ int fStepUp;
+ int fBmc;
+ int fRegs;
+ int fTarget;
+ int fVerbose;
+ int fVeryVerbose;
+ int c;
+ extern int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRegs, int fTarget, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 1;
+ nPref = 0;
+ nClauses = 5000;
+ nLutSize = 4;
+ nLevels = 8;
+ nCutsMax = 16;
+ nBatches = 1;
+ fStepUp = 0;
+ fBmc = 1;
+ fRegs = 1;
+ fTarget = 1;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FPCMLNBsbrtvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ 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 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nPref = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nPref < 0 )
+ goto usage;
+ break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nClauses = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nClauses < 0 )
+ goto usage;
+ break;
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ 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 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutsMax < 0 )
+ goto usage;
+ break;
+ case 'B':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nBatches = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nBatches < 0 )
+ goto usage;
+ break;
+ case 's':
+ fStepUp ^= 1;
+ break;
+ case 'b':
+ fBmc ^= 1;
+ break;
+ case 'r':
+ fRegs ^= 1;
+ break;
+ case 't':
+ fTarget ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+ if ( nLutSize > 12 )
+ {
+ fprintf( stdout, "The cut size should be not exceed 12.\n" );
+ return 0;
+ }
+ Abc_NtkDarClau( pNtk, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRegs, fTarget, fVerbose, fVeryVerbose );
+ return 0;
+usage:
+ fprintf( pErr, "usage: indcut [-FPCMLNB num] [-sbrtvh]\n" );
+ fprintf( pErr, "\t K-step induction strengthened with cut properties\n" );
+ fprintf( pErr, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-P num : number of time frames in the prefix (0=no prefix) [default = %d]\n", nPref );
+ fprintf( pErr, "\t-C num : the max number of clauses to use for strengthening [default = %d]\n", nClauses );
+ fprintf( pErr, "\t-M num : the cut size (2 <= M <= 12) [default = %d]\n", nLutSize );
+ fprintf( pErr, "\t-L num : the max number of levels for cut computation [default = %d]\n", nLevels );
+ fprintf( pErr, "\t-N num : the max number of cuts to compute at a node [default = %d]\n", nCutsMax );
+ fprintf( pErr, "\t-B num : the max number of invariant batches to try [default = %d]\n", nBatches );
+ fprintf( pErr, "\t-s : toggle increment cut size in each batch [default = %s]\n", fStepUp? "yes": "no" );
+ fprintf( pErr, "\t-b : toggle enabling BMC check [default = %s]\n", fBmc? "yes": "no" );
+ fprintf( pErr, "\t-r : toggle enabling register clauses [default = %s]\n", fRegs? "yes": "no" );
+ fprintf( pErr, "\t-t : toggle proving target / computing don't-cares [default = %s]\n", fTarget? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+// fprintf( pErr, "\t-w : toggle printing very verbose 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_CommandEnlarge( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int nFrames;
+ int fVerbose;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nFrames = 5;
+ 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_NtkIsComb(pNtk) )
+ {
+ fprintf( pErr, "Only works for sequential networks.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( stdout, "Currently only works for structurally hashed circuits.\n" );
+ return 0;
+ }
+
+ // modify the current network
+ pNtkRes = Abc_NtkDarEnlarge( pNtk, nFrames, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Target enlargement has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+usage:
+ fprintf( pErr, "usage: enlarge [-F num] [-vh]\n" );
+ fprintf( pErr, "\t performs structural K-step target enlargement\n" );
+ fprintf( pErr, "\t-F num : the number of timeframes for enlargement [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_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
index 6ee1fb90..d5d2aa16 100644
--- a/src/base/abci/abcAttach.c
+++ b/src/base/abci/abcAttach.c
@@ -40,7 +40,7 @@ static char ** s_pPerms = NULL;
static int s_nPerms;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -66,7 +66,7 @@ int Abc_NtkAttach( Abc_Ntk_t * pNtk )
assert( Abc_NtkIsSopLogic(pNtk) );
// check that the library is available
- pGenlib = Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame());
+ pGenlib = Abc_FrameReadLibGen();
if ( pGenlib == NULL )
{
printf( "The current library is not available.\n" );
@@ -142,7 +142,7 @@ int Abc_NtkAttach( Abc_Ntk_t * pNtk )
Abc_NtkForEachNode( pNtk, pNode, i )
pNode->pData = pNode->pCopy, pNode->pCopy = NULL;
pNtk->ntkFunc = ABC_FUNC_MAP;
- Extra_MmFlexStop( pNtk->pManFunc, 0 );
+ Extra_MmFlexStop( pNtk->pManFunc );
pNtk->pManFunc = pGenlib;
printf( "Library gates are successfully attached to the nodes.\n" );
@@ -187,7 +187,7 @@ int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTrut
Abc_ObjForEachFanin( pNode, pFanin, i )
pTempInts[i] = pFanin->Id;
for ( i = 0; i < nFanins; i++ )
- pNode->vFanins.pArray[Perm[i]].iFan = pTempInts[i];
+ pNode->vFanins.pArray[Perm[i]] = pTempInts[i];
// set the gate
pNode->pCopy = (Abc_Obj_t *)pGate;
return 1;
@@ -387,13 +387,13 @@ void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned
nMints = (1 << nVars);
for ( iMint = 0; iMint < nMints; iMint++ )
{
- if ( (uTruthNode[iMint/32] & (1 << (iMint%32))) == 0 )
+ 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/32] |= (1 << (iMintPerm%32));
+ uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31));
}
}
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
index 40701e41..f9b3384e 100644
--- a/src/base/abci/abcBalance.c
+++ b/src/base/abci/abcBalance.c
@@ -24,13 +24,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate );
-static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, bool fDuplicate );
-static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int fDuplicate );
-static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -44,14 +47,32 @@ static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSupe
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate )
+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_TYPE_STRASH, ABC_FUNC_AIG );
- Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate );
+ 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 ) )
{
@@ -73,7 +94,7 @@ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate )
SeeAlso []
***********************************************************************/
-void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate )
+void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel )
{
int fCheck = 1;
ProgressBar * pProgress;
@@ -81,12 +102,10 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
Abc_Obj_t * pNode, * pDriver;
int i;
- // copy the constant node
- Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkAig->pManFunc);
// 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( Abc_AigGetLevelNum(pNtk) + 1 );
+ vStorage = Vec_VecStart( 10 );
// perform balancing of POs
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pNode, i )
@@ -94,7 +113,7 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
Extra_ProgressBarUpdate( pProgress, i, NULL );
// strash the driver node
pDriver = Abc_ObjFanin0(pNode);
- Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, fDuplicate );
+ Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel );
}
Extra_ProgressBarStop( pProgress );
Vec_VecFree( vStorage );
@@ -102,6 +121,97 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
/**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 []
@@ -111,36 +221,44 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, bool fDuplicate )
+Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel )
{
Abc_Aig_t * pMan = pNtkNew->pManFunc;
Abc_Obj_t * pNodeNew, * pNode1, * pNode2;
Vec_Ptr_t * vSuper;
- int i;
+ int i, LeftBound;
assert( !Abc_ObjIsComplement(pNodeOld) );
// return if the result if known
if ( pNodeOld->pCopy )
return pNodeOld->pCopy;
assert( Abc_ObjIsNode(pNodeOld) );
// get the implication supergate
- vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, fDuplicate );
+// 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(pMan));
+ 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, fDuplicate );
+ 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) );
@@ -149,6 +267,13 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_
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;
}
@@ -165,17 +290,25 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int fDuplicate )
+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) );
- vNodes = Vec_VecEntry( vStorage, pNode->Level );
+ // 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 );
- RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate );
- assert( vNodes->nSize > 0 );
+ // 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;
@@ -195,7 +328,7 @@ Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int fD
SeeAlso []
***********************************************************************/
-int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate )
+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
@@ -213,7 +346,7 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst,
return 0;
}
// if the new node is complemented or a PI, another gate begins
- if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && (Abc_ObjFanoutNum(pNode) > 1)) )
+ if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && !fSelective && (Abc_ObjFanoutNum(pNode) > 1)) )
{
Vec_PtrPush( vSuper, pNode );
Abc_ObjRegular(pNode)->fMarkB = 1;
@@ -222,8 +355,8 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst,
assert( !Abc_ObjIsComplement(pNode) );
assert( Abc_ObjIsNode(pNode) );
// go through the branches
- RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate );
- RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate );
+ 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
@@ -231,6 +364,248 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst,
}
+/**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/abcCollapse.c b/src/base/abci/abcClpBdd.c
index 40370eff..a6b3a770 100644
--- a/src/base/abci/abcCollapse.c
+++ b/src/base/abci/abcClpBdd.c
@@ -19,6 +19,7 @@
***********************************************************************/
#include "abc.h"
+//#include "reo.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -28,7 +29,7 @@ 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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -42,33 +43,41 @@ static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd,
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose )
+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_NtkGlobalBdds(pNtk, 0) == NULL )
+ if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL )
return NULL;
if ( fVerbose )
- printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) );
+ {
+ 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 );
+ Abc_NtkFreeGlobalBdds( pNtk, 1 );
if ( pNtkNew == NULL )
{
- Cudd_Quit( pNtk->pManGlob );
- pNtk->pManGlob = NULL;
+// Cudd_Quit( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
return NULL;
}
- Extra_StopManager( pNtk->pManGlob );
- pNtk->pManGlob = NULL;
+// Extra_StopManager( pNtk->pManGlob );
+// pNtk->pManGlob = NULL;
// make the network minimum base
Abc_NtkMinimumBase( pNtkNew );
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
@@ -79,6 +88,9 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose )
return pNtkNew;
}
+
+//int runtime1, runtime2;
+
/**Function*************************************************************
Synopsis [Derives the network with the given global BDD.]
@@ -92,13 +104,21 @@ Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose )
***********************************************************************/
Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk )
{
+// extern void Extra_ShuffleTest( reo_man * p, DdManager * dd, DdNode * Func );
+// reo_man * pReo;
+
ProgressBar * pProgress;
Abc_Ntk_t * pNtkNew;
- Abc_Obj_t * pNode, * pNodeNew;
- DdManager * dd = pNtk->pManGlob;
+ Abc_Obj_t * pNode, * pDriver, * pNodeNew;
+// DdManager * dd = pNtk->pManGlob;
+ DdManager * dd = Abc_NtkGlobalBddMan( pNtk );
int i;
+
+// pReo = Extra_ReorderInit( Abc_NtkCiNum(pNtk), 1000 );
+// runtime1 = runtime2 = 0;
+
// start the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD );
+ 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
@@ -106,10 +126,25 @@ Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk )
Abc_NtkForEachCo( pNtk, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) );
+ pDriver = Abc_ObjFanin0(pNode);
+ if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) )
+ {
+ Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy );
+ continue;
+ }
+// pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) );
+ pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Abc_ObjGlobalBdd(pNode) );
Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+
+// Extra_ShuffleTest( pReo, dd, Abc_ObjGlobalBdd(pNode) );
+
}
Extra_ProgressBarStop( pProgress );
+
+// Extra_ReorderQuit( pReo );
+//PRT( "Reo ", runtime1 );
+//PRT( "Cudd", runtime2 );
+
return pNtkNew;
}
diff --git a/src/base/abci/abcClpSop.c b/src/base/abci/abcClpSop.c
new file mode 100644
index 00000000..de92243f
--- /dev/null
+++ b/src/base/abci/abcClpSop.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+ FileName [abcCollapse.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Collapsing the network into two-levels.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Collapses the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCollapseSop( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ pNtkNew = NULL;
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c
index f487bd1b..d399ce5f 100644
--- a/src/base/abci/abcCut.c
+++ b/src/base/abci/abcCut.c
@@ -25,8 +25,16 @@
/// 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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -42,18 +50,30 @@
***********************************************************************/
Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
{
+ ProgressBar * pProgress;
Cut_Man_t * p;
- Abc_Obj_t * pObj, * pDriver, * pNode;
+ Abc_Obj_t * pObj, * pNode;
Vec_Ptr_t * vNodes;
Vec_Int_t * vChoices;
int i;
int clk = clock();
- assert( Abc_NtkIsStrash(pNtk) );
+ 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
@@ -61,8 +81,9 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
if ( Abc_ObjFanoutNum(pObj) > 0 )
Cut_NodeSetTriv( p, pObj->Id );
// compute cuts for internal nodes
- vNodes = Abc_AigDfs( pNtk, 0, 1 );
+ 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
@@ -73,12 +94,19 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
continue;
}
// skip constant node, it has no cuts
- if ( Abc_NodeIsConst(pObj) )
- continue;
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
// compute the cuts to the internal node
- Abc_NodeGetCuts( p, pObj );
+ 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_NodeIsAigChoice(pObj) )
+ if ( Abc_AigNodeIsChoice(pObj) )
{
Vec_IntClear( vChoices );
for ( pNode = pObj; pNode; pNode = pNode->pData )
@@ -86,31 +114,203 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
Cut_NodeUnionCuts( p, vChoices );
}
}
- if ( !pParams->fSeq )
+ 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 )
{
- Vec_PtrFree( vNodes );
- Vec_IntFree( vChoices );
-PRT( "Total", clock() - clk );
- return p;
+ // 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) );
+ }
}
- assert( 0 );
+ Vec_PtrFree( vNodes );
+//PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts_( p, pNtk, 0 );
+}
+
- // compute sequential cuts
- Abc_NtkIncrementTravId( pNtk );
- Abc_NtkForEachLatch( pNtk, pObj, i )
+/**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 )
{
- pDriver = Abc_ObjFanin0(pObj);
- if ( !Abc_ObjIsNode(pDriver) )
- continue;
- if ( Abc_NodeIsTravIdCurrent(pDriver) )
- continue;
- Abc_NodeSetTravIdCurrent(pDriver);
- Cut_NodeSetComputedAsNew( p, pDriver->Id );
+//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 );
}
- // compute as long as new cuts appear
+ // 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*************************************************************
@@ -124,14 +324,14 @@ PRT( "Total", clock() - clk );
SeeAlso []
***********************************************************************/
-void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj )
+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) );
- Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj) );
- return Abc_NodeGetCuts( p, pObj );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree );
+ return Abc_NodeGetCuts( p, pObj, fDag, fTree );
}
/**Function*************************************************************
@@ -145,10 +345,73 @@ void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj )
SeeAlso []
***********************************************************************/
-void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj )
+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) );
+ 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*************************************************************
@@ -164,7 +427,7 @@ void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj )
***********************************************************************/
void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj )
{
- return Cut_NodeReadCuts( p, pObj->Id );
+ return Cut_NodeReadCutsNew( p, pObj->Id );
}
/**Function*************************************************************
@@ -183,6 +446,173 @@ 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
index 39f58a4e..1563bdfe 100644
--- a/src/base/abci/abcDar.c
+++ b/src/base/abci/abcDar.c
@@ -22,16 +22,13 @@
#include "aig.h"
#include "dar.h"
#include "cnf.h"
-//#include "fra.h"
-//#include "fraig.h"
+#include "fra.h"
+#include "fraig.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \
- for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
-
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -56,6 +53,25 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
// make sure the latches follow PIs/POs
if ( fRegisters )
{
+ assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( i < Abc_NtkPiNum(pNtk) )
+ {
+ assert( Abc_ObjIsPi(pObj) );
+ if ( !Abc_ObjIsPi(pObj) )
+ printf( "Abc_NtkToDar(): Temporary bug: The PI ordering is wrong!\n" );
+ }
+ else
+ assert( Abc_ObjIsBo(pObj) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ if ( i < Abc_NtkPoNum(pNtk) )
+ {
+ assert( Abc_ObjIsPo(pObj) );
+ if ( !Abc_ObjIsPo(pObj) )
+ printf( "Abc_NtkToDar(): Temporary bug: The PO ordering is wrong!\n" );
+ }
+ else
+ assert( Abc_ObjIsBi(pObj) );
// print warning about initial values
nDontCares = 0;
Abc_NtkForEachLatch( pNtk, pObj, i )
@@ -74,7 +90,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
}
// create the manager
pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 );
- pMan->pName = util_strsav( pNtk->pName );
+ pMan->pName = Extra_UtilStrsav( pNtk->pName );
// save the number of registers
if ( fRegisters )
{
@@ -83,7 +99,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
pMan->vFlopNums = NULL;
}
// transfer the pointers to the basic nodes
- Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
+ 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
@@ -95,8 +111,6 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
// pMan->fAddStrash = 1;
Abc_NtkForEachNode( pNtk, pObj, i )
{
- if ( Abc_ObjFaninNum(pObj) == 0 )
- continue;
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 );
}
@@ -107,8 +121,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters )
// complement the 1-valued registers
if ( fRegisters )
Aig_ManForEachLiSeq( pMan, pObjNew, i )
-// if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) )
- if ( Abc_LatchIsInit1(Abc_NtkCo(pNtk,i)) )
+ if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) )
pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0);
// remove dangling nodes
if ( nNodes = Aig_ManCleanup( pMan ) )
@@ -138,14 +151,14 @@ 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;
+ Abc_Obj_t * pObjNew;
Aig_Obj_t * pObj;
int i;
// assert( Aig_ManRegNum(pMan) == Abc_NtkLatchNum(pNtkOld) );
// perform strashing
- pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
// transfer the pointers to the basic nodes
- Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc);
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
Aig_ManForEachPi( pMan, pObj, i )
pObj->pData = Abc_NtkCi(pNtkNew, i);
// rebuild the AIG
@@ -163,7 +176,6 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
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 )
@@ -172,7 +184,6 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
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;
@@ -180,30 +191,6 @@ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
/**Function*************************************************************
- Synopsis [Adds dummy names.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkAddDummyLatchNames( Abc_Ntk_t * pNtk )
-{
- char Buffer[100];
- Abc_Obj_t * pObj;
- int nDigits, i;
- nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtk) );
- Abc_NtkForEachLatch( pNtk, pObj, i )
- {
- sprintf( Buffer, "L%0*d", nDigits, i );
- Abc_NtkLogicStoreName( pObj, Buffer );
- }
-}
-
-/**Function*************************************************************
-
Synopsis [Converts the network from the AIG manager into ABC.]
Description [This procedure should be called after seq sweeping,
@@ -217,38 +204,52 @@ void Abc_NtkAddDummyLatchNames( Abc_Ntk_t * pNtk )
Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
{
Vec_Ptr_t * vNodes;
- Abc_Ntk_t * pNtkNew;
- Abc_Obj_t * pObjOld, * pObjNew;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObjNew, * pLatch;
Aig_Obj_t * pObj, * pObjLo, * pObjLi;
- int i;
- // start the network
- pNtkNew = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG );
- // duplicate the name and the spec
- pNtkNew->pName = util_strsav(pNtkOld->pName);
- pNtkNew->pSpec = util_strsav(pNtkOld->pSpec);
- // create PIs/POs/latches
- Abc_NtkForEachPi( pNtkOld, pObjOld, i )
- {
- pObjNew = Abc_NtkDupObj( pNtkNew, pObjOld );
- Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObjOld) );
- }
- Abc_NtkForEachPo( pNtkOld, pObjOld, i )
+ int i, iNodeId;
+// assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) );
+ // perform strashing
+ pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
+ // consider the case of target enlargement
+ if ( Abc_NtkCiNum(pNtkNew) < Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) )
{
- pObjNew = Abc_NtkDupObj( pNtkNew, pObjOld );
- Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObjOld) );
+ for ( i = Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) - Abc_NtkCiNum(pNtkNew); i > 0; i-- )
+ {
+ pObjNew = Abc_NtkCreatePi( pNtkNew );
+ Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL );
+ }
+ Abc_NtkOrderCisCos( pNtkNew );
}
+ assert( Abc_NtkCiNum(pNtkNew) == Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan) );
+ assert( Abc_NtkCoNum(pNtkNew) == Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) );
+ // transfer the pointers to the basic nodes
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
+ Aig_ManForEachPiSeq( pMan, pObj, i )
+ pObj->pData = Abc_NtkCi(pNtkNew, i);
+ // create as many latches as there are registers in the manager
Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i )
{
pObjNew = Abc_NtkCreateLatch( pNtkNew );
- Vec_PtrPush( pNtkNew->vCis, pObjNew );
- Vec_PtrPush( pNtkNew->vCos, pObjNew );
+ pObjLi->pData = Abc_NtkCreateBi( pNtkNew );
+ pObjLo->pData = Abc_NtkCreateBo( pNtkNew );
+ Abc_ObjAddFanin( pObjNew, pObjLi->pData );
+ Abc_ObjAddFanin( pObjLo->pData, pObjNew );
Abc_LatchSetInit0( pObjNew );
}
- Abc_NtkAddDummyLatchNames( pNtkNew );
- // transfer the pointers to the basic nodes
- Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc);
- Aig_ManForEachPi( pMan, pObj, i )
- pObj->pData = Abc_NtkCi(pNtkNew, i);
+ 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 )
@@ -260,9 +261,23 @@ Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
// connect the PO nodes
Aig_ManForEachPo( pMan, pObj, i )
{
- pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
+ if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts )
+ break;
+ iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(Abc_NtkCo(pNtkNew, i)), ABC_OBJ_PI, ABC_OBJ_BO );
+ if ( iNodeId >= 0 )
+ pObjNew = Abc_NtkObj( pNtkNew, iNodeId );
+ else
+ pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj);
Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew );
}
+ // if 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;
@@ -288,9 +303,9 @@ Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
assert( pMan->pEquivs != NULL );
assert( Aig_ManBufNum(pMan) == 0 );
// perform strashing
- pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG );
// transfer the pointers to the basic nodes
- Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew->pManFunc);
+ Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
Aig_ManForEachPi( pMan, pObj, i )
pObj->pData = Abc_NtkCi(pNtkNew, i);
@@ -321,6 +336,154 @@ Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan )
/**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 []
@@ -357,6 +520,7 @@ Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk )
return pNtkAig;
}
+
/**Function*************************************************************
Synopsis [Gives the current ABC network to AIG manager for processing.]
@@ -368,59 +532,483 @@ Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose )
+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;
- pMan = Abc_NtkToDar( pNtk, 1 );
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 0 );
if ( pMan == NULL )
return NULL;
- Aig_ManSeqCleanup( pMan );
- if ( fLatchSweep )
+ 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 );
{
- if ( pMan->nRegs )
- pMan = Aig_ManReduceLaches( pMan, fVerbose );
- if ( pMan->nRegs )
- pMan = Aig_ManConstReduce( pMan, fVerbose );
+ Vec_Vec_t * vParts;
+ vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL );
+ Vec_VecFree( vParts );
}
- pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+*/
+ 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 [Computes latch correspondence.]
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
Description []
SideEffects []
SeeAlso []
-
+
***********************************************************************/
-Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose )
+Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars )
{
- extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter );
Aig_Man_t * pMan, * pTemp;
Abc_Ntk_t * pNtkAig;
- pMan = Abc_NtkToDar( pNtk, 1 );
+ int clk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ pMan = Abc_NtkToDar( pNtk, 0 );
if ( pMan == NULL )
return NULL;
- pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, 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 );
- if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) )
- pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+//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
{
- Abc_Obj_t * pObj;
- int i;
- pNtkAig = Abc_NtkFromDar( pNtk, pMan );
- Abc_NtkForEachLatch( pNtkAig, pObj, i )
- Abc_LatchSetInit0( pObj );
+ 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 );
- return pNtkAig;
+
+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*************************************************************
@@ -436,8 +1024,7 @@ Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int f
***********************************************************************/
Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, int nMaxImps, int nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose )
{
- extern Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, int nFramesP, int nFramesK, int nMaxImps, int nMaxLevs, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose, int * pnIter );
-// Fraig_Params_t Params;
+ Fraig_Params_t Params;
Abc_Ntk_t * pNtkAig, * pNtkFraig;
Aig_Man_t * pMan, * pTemp;
int clk = clock();
@@ -445,8 +1032,8 @@ Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, in
// 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;
+ Fraig_ParamsSetDefault( &Params );
+ Params.nBTLimit = 100000;
// pNtkFraig = Abc_NtkFraig( pNtk, &Params, 0, 0 );
pNtkFraig = Abc_NtkDup( pNtk );
if ( fVerbose )
@@ -478,6 +1065,113 @@ PRT( "Initial fraiging time", clock() - clk );
/**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
+ {
+ Abc_Obj_t * pObj;
+ int i;
+ pNtkAig = Abc_NtkFromDar( pNtk, pMan );
+ Abc_NtkForEachLatch( pNtkAig, pObj, i )
+ Abc_LatchSetInit0( pObj );
+ }
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nFrames, int nBTLimit, int fRewrite, int fVerbose )
+{
+ Aig_Man_t * pMan;
+ int clk = clock();
+ // 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
+ Fra_BmcPerformSimple( pMan, nFrames, nBTLimit, fRewrite, fVerbose );
+ pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+ if ( pNtk->pSeqModel )
+ {
+ Fra_Cex_t * pCex = pNtk->pSeqModel;
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump the trace). ", pCex->iPo, pCex->iFrame );
+ }
+ else
+ printf( "No output was asserted after BMC with %d frames. ", nFrames );
+PRT( "Time", clock() - clk );
+ Aig_ManStop( pMan );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarProve( Abc_Ntk_t * pNtk, 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 );
+ pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL;
+ if ( pNtk->pSeqModel )
+ {
+ Fra_Cex_t * pCex = pNtk->pSeqModel;
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump the trace).\n", pCex->iPo, pCex->iFrame );
+ }
+ Aig_ManStop( pMan );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
Synopsis [Gives the current ABC network to AIG manager for processing.]
Description []
@@ -489,14 +1183,13 @@ PRT( "Initial fraiging time", clock() - clk );
***********************************************************************/
int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose )
{
- extern int Fra_FraigSec( Aig_Man_t * p, int nFramesMax, 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 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
@@ -507,12 +1200,10 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetim
{
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;
}
@@ -567,7 +1258,314 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetim
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 );
+ if ( pMan->vFlopNums )
+ Vec_IntFree( pMan->vFlopNums );
+ pMan->vFlopNums = NULL;
+
+ 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;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+// Aig_ManReduceLachesCount( pMan );
+ if ( pMan->vFlopNums )
+ Vec_IntFree( pMan->vFlopNums );
+ pMan->vFlopNums = NULL;
+
+ pMan = Aig_ManRetimeFrontier( pTemp = pMan, nStepsMax );
+ Aig_ManStop( pTemp );
+
+// pMan = Aig_ManReduceLaches( pMan, 1 );
+// pMan = Aig_ManConstReduce( pMan, 1 );
+
+ 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 []
+
+***********************************************************************/
+void Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk )
+{
+ Aig_Man_t * pMan;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return;
+// Aig_ManReduceLachesCount( pMan );
+ if ( pMan->vFlopNums )
+ Vec_IntFree( pMan->vFlopNums );
+ pMan->vFlopNums = NULL;
+ Aig_ManHaigRecord( pMan );
+ Aig_ManStop( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs random simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose )
+{
+ Aig_Man_t * pMan;
+ Fra_Sml_t * pSml;
+ Fra_Cex_t * pCex;
+ int RetValue, clk = clock();
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords );
+ if ( pSml->fNonConstOut )
+ {
+ pCex = Fra_SmlGetCounterExample( pSml );
+ if ( pCex )
+ printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ",
+ nFrames, nWords, pCex->iPo, pCex->iFrame );
+ pNtk->pSeqModel = pCex;
+ RetValue = 1;
+ }
+ else
+ {
+ RetValue = 0;
+ printf( "Simulation of %d frames with %d words did not assert the outputs. ",
+ nFrames, nWords );
+ }
+ PRT( "Time", clock() - clk );
+ Fra_SmlStop( pSml );
+ Aig_ManStop( pMan );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose )
+{
+ extern int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose );
+ extern int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose );
+ Aig_Man_t * pMan;
+ if ( fTarget && Abc_NtkPoNum(pNtk) != 1 )
+ {
+ printf( "The number of outputs should be 1.\n" );
+ return 1;
+ }
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return 1;
+// Aig_ManReduceLachesCount( pMan );
+ if ( pMan->vFlopNums )
+ Vec_IntFree( pMan->vFlopNums );
+ pMan->vFlopNums = NULL;
+
+// Fra_Clau( pMan, nStepsMax, fVerbose, fVeryVerbose );
+ Fra_Claus( pMan, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRefs, fTarget, fVerbose, fVeryVerbose );
+ Aig_ManStop( pMan );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs targe enlargement.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan, * pTemp;
+ pMan = Abc_NtkToDar( pNtk, 1 );
+ if ( pMan == NULL )
+ return NULL;
+ pMan = Aig_ManFrames( pTemp = pMan, nFrames, 0, 1, 1, 1, NULL );
+ Aig_ManStop( pTemp );
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interplates two networks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fVerbose )
+{
+ extern Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose );
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pManOn, * pManOff, * pManAig;
+ if ( Abc_NtkCoNum(pNtkOn) != 1 || Abc_NtkCoNum(pNtkOff) != 1 )
+ {
+ printf( "Currently works only for single output networks.\n" );
+ return NULL;
+ }
+ if ( Abc_NtkCiNum(pNtkOn) != Abc_NtkCiNum(pNtkOff) )
+ {
+ printf( "The number of PIs should be the same.\n" );
+ return NULL;
+ }
+ // create internal AIGs
+ pManOn = Abc_NtkToDar( pNtkOn, 0 );
+ if ( pManOn == NULL )
+ return NULL;
+ pManOff = Abc_NtkToDar( pNtkOff, 0 );
+ if ( pManOff == NULL )
+ return NULL;
+ // derive the interpolant
+ pManAig = Aig_ManInter( pManOn, pManOff, fVerbose );
+ if ( pManAig == NULL )
+ {
+ printf( "Interpolant computation failed.\n" );
+ return NULL;
+ }
+ Aig_ManStop( pManOn );
+ Aig_ManStop( pManOff );
+ // create logic network
+ pNtkAig = Abc_NtkFromDar( pNtkOn, pManAig );
+ Aig_ManStop( pManAig );
+ return pNtkAig;
+}
+
+
+#include "ntl.h"
+
+/**Function*************************************************************
+
+ Synopsis [Performs targe enlargement.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkDarTestBlif( char * pFileName )
+{
+ char Buffer[1000];
+ Ntl_Man_t * p;
+ p = Ioa_ReadBlif( pFileName, 1 );
+ if ( p == NULL )
+ {
+ printf( "Abc_NtkDarTestBlif(): Reading BLIF has failed.\n" );
+ return;
+ }
+ Ntl_ManPrintStats( p );
+// if ( !Ntl_ManInsertTest( p ) )
+ if ( !Ntl_ManInsertTestIf( p ) )
+ {
+ printf( "Abc_NtkDarTestBlif(): Tranformation of the netlist has failed.\n" );
+ return;
+ }
+// sprintf( Buffer, "%s_.blif", p->pName );
+ sprintf( Buffer, "test_.blif", p->pName );
+ Ioa_WriteBlif( p, Buffer );
+ Ntl_ManFree( p );
+}
////////////////////////////////////////////////////////////////////////
/// 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
index 67665ad6..c00a7d7c 100644
--- a/src/base/abci/abcDsd.c
+++ b/src/base/abci/abcDsd.c
@@ -27,15 +27,15 @@
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 );
+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 );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -55,28 +55,22 @@ static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int n
***********************************************************************/
Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort )
{
+ DdManager * dd;
Abc_Ntk_t * pNtkNew;
-
assert( Abc_NtkIsStrash(pNtk) );
-
- // perform FPGA mapping
- if ( Abc_NtkGlobalBdds(pNtk, 0) == NULL )
+ dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
+ if ( dd == NULL )
return NULL;
if ( fVerbose )
- printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) );
-
+ printf( "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 )
- {
- Cudd_Quit( pNtk->pManGlob );
- pNtk->pManGlob = NULL;
return NULL;
- }
- Extra_StopManager( pNtk->pManGlob );
- pNtk->pManGlob = NULL;
-
- // make sure that everything is okay
+ // 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" );
@@ -99,26 +93,25 @@ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool
***********************************************************************/
Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort )
{
- DdManager * dd = pNtk->pManGlob;
+ char ** ppNamesCi, ** ppNamesCo;
+ Vec_Ptr_t * vFuncsGlob;
Dsd_Manager_t * pManDsd;
Abc_Ntk_t * pNtkNew;
- DdNode * bFunc;
- char ** ppNamesCi, ** ppNamesCo;
+ DdManager * dd;
Abc_Obj_t * pObj;
int i;
// complement the global functions
+ vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pObj, i )
- {
- bFunc = Vec_PtrEntry(pNtk->vFuncsGlob, i);
- Vec_PtrWriteEntry(pNtk->vFuncsGlob, i, Cudd_NotCond(bFunc, Abc_ObjFaninC0(pObj)) );
- }
+ Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) );
// perform the decomposition
- assert( Vec_PtrSize(pNtk->vFuncsGlob) == Abc_NtkCoNum(pNtk) );
+ dd = Abc_NtkGlobalBddMan(pNtk);
pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose );
- Dsd_Decompose( pManDsd, (DdNode **)pNtk->vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) );
- Abc_NtkFreeGlobalBdds( pNtk );
+ Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) );
+ Vec_PtrFree( vFuncsGlob );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
if ( pManDsd == NULL )
{
Cudd_Quit( dd );
@@ -126,7 +119,7 @@ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bo
}
// start the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD );
+ 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)
@@ -135,7 +128,6 @@ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bo
Abc_NtkFinalize( pNtk, pNtkNew );
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
-
if ( fPrint )
{
ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 );
@@ -165,24 +157,21 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t *
{
Dsd_Node_t ** ppNodesDsd;
Dsd_Node_t * pNodeDsd;
- Abc_Obj_t * pNode, * pNodeNew, * pDriver, * pConst1;
+ 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 );
}
- // set the constant node
- pConst1 = Abc_AigConst1(pNtk->pManFunc);
- if ( Abc_ObjFanoutNum(pConst1) > 0 )
- pConst1->pCopy = Abc_NodeCreateConst1(pNtkNew);
// 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 );
+ Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew, NULL );
free( ppNodesDsd );
// set the pointers to the CO drivers
@@ -191,7 +180,7 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t *
pDriver = Abc_ObjFanin0( pNode );
if ( !Abc_ObjIsNode(pDriver) )
continue;
- if ( !Abc_NodeIsAigAnd(pDriver) )
+ if ( !Abc_AigNodeIsAnd(pDriver) )
continue;
pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i );
pNodeNew = (Abc_Obj_t *)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) );
@@ -211,7 +200,7 @@ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t *
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew )
+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;
@@ -268,8 +257,22 @@ Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNode
}
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;
@@ -307,6 +310,7 @@ int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive )
DdManager * dd = pNtk->pManFunc;
Vec_Ptr_t * vNodes;
int i;
+ int pCounters[11] = {0};
assert( Abc_NtkIsBddLogic(pNtk) );
@@ -319,9 +323,14 @@ int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive )
// collect nodes for decomposition
vNodes = Abc_NtkCollectNodesForDsd( pNtk );
for ( i = 0; i < vNodes->nSize; i++ )
- Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive );
+ 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 );
@@ -371,7 +380,7 @@ Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive )
+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;
@@ -398,7 +407,7 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd );
for ( i = 0; i < nNodesDsd; i++ )
{
- pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk );
+ pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters );
if ( Abc_NodeIsForDsd(pRoot) && fRecursive )
Vec_PtrPush( vNodes, pRoot );
}
@@ -419,14 +428,14 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
pNodeC = Abc_ObjFanin( pNode, iVar );
// get the negative cofactor
- pNode1 = Abc_NodeClone( pNode );
+ 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_NodeClone( pNode );
+ 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) )
@@ -446,7 +455,7 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
/**Function*************************************************************
- Synopsis [Performs decomposition of one node.]
+ Synopsis [Checks if the node should be decomposed by DSD.]
Description []
@@ -458,12 +467,14 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
bool Abc_NodeIsForDsd( Abc_Obj_t * pNode )
{
DdManager * dd = pNode->pNtk->pManFunc;
- DdNode * bFunc, * bFunc0, * bFunc1;
+// 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) );
@@ -475,6 +486,9 @@ bool Abc_NodeIsForDsd( Abc_Obj_t * pNode )
else
return 1;
}
+*/
+ if ( Abc_ObjFaninNum(pNode) > 2 )
+ return 1;
return 0;
}
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
index 55ae23ff..3bc9fbed 100644
--- a/src/base/abci/abcFpga.c
+++ b/src/base/abci/abcFpga.c
@@ -25,12 +25,12 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fVerbose );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -44,7 +44,7 @@ static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNo
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fVerbose )
+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;
@@ -68,11 +68,14 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fV
}
// perform FPGA mapping
- pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fVerbose );
+ 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 );
@@ -88,6 +91,9 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fV
// 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 ) )
{
@@ -109,13 +115,14 @@ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fV
SeeAlso []
***********************************************************************/
-Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fVerbose )
+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) );
@@ -126,10 +133,17 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching,
return NULL;
Fpga_ManSetAreaRecovery( pMan, fRecovery );
Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) );
- Fpga_ManSetInputArrivals( pMan, Abc_NtkGetCiArrivalFloats(pNtk) );
+ 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];
@@ -144,12 +158,6 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching,
Vec_PtrForEachEntry( vNodes, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- // consider the case of a constant
- if ( Abc_NodeIsConst(pNode) )
- {
- Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan);
- continue;
- }
// add the node to the mapper
pNodeFpga = Fpga_NodeAnd( pMan,
Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
@@ -160,7 +168,7 @@ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching,
if ( pSwitching )
Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] );
// set up the choice node
- if ( Abc_NodeIsAigChoice( pNode ) )
+ 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 );
@@ -194,15 +202,15 @@ Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk )
Abc_Obj_t * pNode, * pNodeNew;
int i, nDupGates;
// create the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD );
+ 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 ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk->pManFunc) ) > 0 )
- Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NodeCreateConst1(pNtkNew) );
+// 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 )
@@ -215,6 +223,10 @@ Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk )
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) )
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
index a11e6eef..be8a25f1 100644
--- a/src/base/abci/abcFraig.c
+++ b/src/base/abci/abcFraig.c
@@ -26,16 +26,19 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
-static Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
-static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig );
-
-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_Aig_t * pMan, Abc_Obj_t * pNode );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -49,19 +52,30 @@ static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode );
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes )
+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;
+ 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 );
+ 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
- pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
+ 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 ) )
{
@@ -83,13 +97,13 @@ Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes )
SeeAlso []
***********************************************************************/
-Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes )
+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;
- Fraig_Node_t * pNodeFraig;
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pConst1, * pReset;
+ Abc_Obj_t * pNode;
int i;
assert( Abc_NtkIsStrash(pNtk) );
@@ -97,36 +111,35 @@ Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fA
// create the FRAIG manager
pMan = Fraig_ManCreate( pParams );
- // create PIs and remember them in the old nodes
+ // 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);
- pConst1 = Abc_AigConst1( pNtk->pManFunc );
- pReset = Abc_AigReset( pNtk->pManFunc );
-
+
// perform strashing
vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 );
- if ( !pParams->fInternal )
+ if ( !fInternal )
pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
Vec_PtrForEachEntry( vNodes, pNode, i )
{
- if ( !pParams->fInternal )
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- if ( pNode == pConst1 )
- pNodeFraig = Fraig_ManReadConst1(pMan);
- else if ( pNode == pReset )
+ if ( Abc_ObjFaninNum(pNode) == 0 )
continue;
- else
- pNodeFraig = Fraig_NodeAnd( pMan,
+ 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) ) );
- assert( pNode->pCopy == NULL );
- pNode->pCopy = (Abc_Obj_t *)pNodeFraig;
}
- if ( !pParams->fInternal )
+ 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) ) );
@@ -135,7 +148,123 @@ Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fA
/**Function*************************************************************
- Synopsis [Transforms FRAIG into what looks like a strashed network.]
+ 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 []
@@ -146,26 +275,27 @@ Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fA
***********************************************************************/
Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
{
-// ProgressBar * pProgress;
+ ProgressBar * pProgress;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pNode, * pNodeNew;
int i;
// create the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ 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->pManFunc) );
+ Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew) );
// process the nodes in topological order
-// pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pNode, i )
{
-// Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
pNodeNew = Abc_NodeFromFraig_rec( pNtkNew, Fraig_ManReadOutputs(pMan)[i] );
Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
}
-// Extra_ProgressBarStop( pProgress );
+ Extra_ProgressBarStop( pProgress );
+ Abc_NtkReassignIds( pNtkNew );
return pNtkNew;
}
@@ -232,6 +362,109 @@ Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFrai
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) );
+}
@@ -263,9 +496,10 @@ Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk )
}
// perform strashing
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ 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 ) );
@@ -322,7 +556,6 @@ int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk )
void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
ProgressBar * pProgress;
- Abc_Aig_t * pMan = pNtkNew->pManFunc;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pNode, * pNodeNew, * pObj;
int i;
@@ -336,7 +569,7 @@ void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
// get the node
assert( Abc_ObjIsNode(pNode) );
// strash the node
- pNodeNew = Abc_NodeFraigTrust( pMan, pNode );
+ pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode );
// get the old object
if ( Abc_NtkIsNetlist(pNtk) )
pObj = Abc_ObjFanout0( pNode ); // the fanout net
@@ -362,10 +595,9 @@ void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
+Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode )
{
Abc_Obj_t * pSum, * pFanin;
- Abc_Obj_t * pConst1 = Abc_AigConst1(pMan);
void ** ppTail;
int i, nFanins, fCompl;
@@ -375,11 +607,11 @@ Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
assert( nFanins == Abc_SopGetVarNum(pNode->pData) );
// check if it is a constant
if ( nFanins == 0 )
- return Abc_ObjNotCond( pConst1, Abc_SopIsConst0(pNode->pData) );
+ 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( pMan,
+ 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) );
@@ -416,49 +648,32 @@ Abc_Obj_t * Abc_NodeFraigTrust( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-int Abc_NtkFraigStore( Abc_Ntk_t * pNtk )
+int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd )
{
- extern int Abc_NtkAppendNew( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
-
- Abc_Ntk_t * pStore;
- int nAndsOld;
-
- if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
+ 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( "The netlist need to be converted into a logic network before adding it to storage.\n" );
+ printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" );
return 0;
}
-
// get the network currently stored
- pStore = Abc_FrameReadNtkStore();
- if ( pStore == NULL )
+ vStore = Abc_FrameReadStore();
+ if ( Vec_PtrSize(vStore) > 0 )
{
- // start the stored network
- pStore = Abc_NtkStrash( pNtk, 0, 0 );
- if ( pStore == NULL )
+ // 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( "Abc_NtkFraigStore: Initial strashing has failed.\n" );
- return 0;
+ 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();
}
- // save the parameters
- Abc_FrameSetNtkStore( pStore );
- Abc_FrameSetNtkStoreSize( 1 );
- nAndsOld = 0;
}
- else
- {
- // add the new network to storage
- nAndsOld = Abc_NtkNodeNum( pStore );
-// if ( !Abc_NtkAppend( pStore, pNtk ) )
- if ( !Abc_NtkAppendNew( pStore, pNtk ) )
- {
- printf( "The current network cannot be appended to the stored network.\n" );
- return 0;
- }
- // set the number of networks stored
- Abc_FrameSetNtkStoreSize( Abc_FrameReadNtkStoreSize() + 1 );
- }
- printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pStore) - nAndsOld );
+ Vec_PtrPush( vStore, pNtk );
+// printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) );
return 1;
}
@@ -475,56 +690,54 @@ int Abc_NtkFraigStore( Abc_Ntk_t * pNtk )
***********************************************************************/
Abc_Ntk_t * Abc_NtkFraigRestore()
{
- extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Abc_Ntk_t * pNtk, void * pParams );
-
+ extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams );
Fraig_Params_t Params;
- Abc_Ntk_t * pStore, * pFraig;
+ Vec_Ptr_t * vStore;
+ Abc_Ntk_t * pNtk, * pFraig;
int nWords1, nWords2, nWordsMin;
int clk = clock();
// get the stored network
- pStore = Abc_FrameReadNtkStore();
- Abc_FrameSetNtkStore( NULL );
- if ( pStore == NULL )
+ vStore = Abc_FrameReadStore();
+ if ( Vec_PtrSize(vStore) == 0 )
{
printf( "There are no network currently in storage.\n" );
return NULL;
}
- printf( "Currently stored %d networks with %d nodes will be fraiged.\n",
- Abc_FrameReadNtkStoreSize(), Abc_NtkNodeNum(pStore) );
+// 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(pStore) + Abc_NtkCiNum(pStore));
+ 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 = 99; // the max number of backtracks to perform
- Params.nBTLimit = 1000000; // 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
- Params.fInternal = 1; // the flag indicates the internal run
-
-// Fraig_ManReportChoices( p );
- // transform it into FRAIG
-// pFraig = Abc_NtkFraig( pStore, &Params, 1 );
- pFraig = Abc_NtkFraigPartitioned( pStore, &Params );
-
-PRT( "Total fraiging time", clock() - clk );
- if ( pFraig == NULL )
- return NULL;
- Abc_NtkDelete( pStore );
+ 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;
}
@@ -541,12 +754,13 @@ PRT( "Total fraiging time", clock() - clk );
***********************************************************************/
void Abc_NtkFraigStoreClean()
{
- Abc_Ntk_t * pStore;
- // get the stored network
- pStore = Abc_FrameReadNtkStore();
- if ( pStore )
- Abc_NtkDelete( pStore );
- Abc_FrameSetNtkStore( NULL );
+ 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*************************************************************
@@ -567,7 +781,7 @@ void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig )
int i, k;
// check that the PO functions are correct
nPoFinal = Abc_NtkPoNum(pFraig);
- nStored = Abc_FrameReadNtkStoreSize(Abc_FrameGetGlobalFrame());
+ nStored = Abc_FrameReadStoreSize();
assert( nPoFinal % nStored == 0 );
nPoOrig = nPoFinal / nStored;
for ( i = 0; i < nPoOrig; i++ )
diff --git a/src/base/abci/abcFxu.c b/src/base/abci/abcFxu.c
index 3a70862f..45515dd1 100644
--- a/src/base/abci/abcFxu.c
+++ b/src/base/abci/abcFxu.c
@@ -30,7 +30,7 @@ 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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -53,16 +53,19 @@ static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p );
bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p )
{
assert( Abc_NtkIsLogic(pNtk) );
- // convert nodes to SOPs
- if ( Abc_NtkIsMappedLogic(pNtk) )
- Abc_NtkUnmap(pNtk);
- else if ( Abc_NtkIsBddLogic(pNtk) )
- Abc_NtkBddToSop(pNtk);
- else
+ // 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) )
{
@@ -108,7 +111,7 @@ bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk )
{
Abc_ObjForEachFanin( pNode, pFanin1, i )
{
- if ( Abc_ObjFaninC(pNode, i) )
+ if ( i < 2 && Abc_ObjFaninC(pNode, i) )
return 0;
Abc_ObjForEachFanin( pNode, pFanin2, k )
{
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
index a4731095..d3513bbe 100644
--- a/src/base/abci/abcHaig.c
+++ b/src/base/abci/abcHaig.c
@@ -19,7 +19,6 @@
***********************************************************************/
#include "abc.h"
-#include "hop.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -31,6 +30,127 @@
/**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 []
@@ -347,10 +467,10 @@ Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p )
assert( p->nCreated == Vec_PtrSize(p->vObjs) );
// start the new network
- pNtkAig = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ 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->pManFunc );
+ Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig );
Hop_ManForEachPi( p, pObj, i )
pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i );
@@ -516,6 +636,59 @@ int Abc_NtkHaigResetReprs( Hop_Man_t * p )
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*************************************************************
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
index ec5352cb..d4d50923 100644
--- a/src/base/abci/abcMap.c
+++ b/src/base/abci/abcMap.c
@@ -40,7 +40,7 @@ static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Sup
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -56,28 +56,28 @@ static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Sup
***********************************************************************/
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 fShowSwitching = 0;
int clk;
assert( Abc_NtkIsStrash(pNtk) );
// check that the library is available
- if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == NULL )
+ if ( Abc_FrameReadLibGen() == NULL )
{
printf( "The current library is not available.\n" );
return 0;
}
// derive the supergate library
- if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL && Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) )
+ if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
{
printf( "A simple supergate library is derived from gate library \"%s\".\n",
- Mio_LibraryReadName(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) );
- Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
+ Mio_LibraryReadName(Abc_FrameReadLibGen()) );
+ Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() );
}
// print a warning about choice nodes
@@ -113,6 +113,9 @@ clk = clock();
return NULL;
Map_ManFree( pMan );
+ if ( pNtk->pExdc )
+ pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
@@ -156,6 +159,7 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f
// 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];
@@ -170,12 +174,6 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f
Vec_PtrForEachEntry( vNodes, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- // consider the case of a constant
- if ( Abc_NodeIsConst(pNode) )
- {
- Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan);
- continue;
- }
// add the node to the mapper
pNodeMap = Map_NodeAnd( pMan,
Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
@@ -186,7 +184,7 @@ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, f
if ( pSwitching )
Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] );
// set up the choice node
- if ( Abc_NodeIsAigChoice( pNode ) )
+ 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 );
@@ -220,17 +218,12 @@ Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
Map_Node_t * pNodeMap;
Abc_Obj_t * pNode, * pNodeNew;
int i, nDupGates;
-
// create the new network
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_MAP );
+ 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 );
- // set the constant node
- if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk->pManFunc) ) > 0 )
- Map_NodeSetData( Map_ManReadConst1(pMan), 1, (char *)Abc_NodeCreateConst1(pNtkNew) );
-
// assign the mapping of the required phase to the POs
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pNode, i )
@@ -264,6 +257,10 @@ Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int
{
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 )
@@ -372,7 +369,7 @@ Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap
* (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_NodeCreateConst0(pNtkNew);
+ return Abc_NtkCreateNodeConst0(pNtkNew);
}
}
@@ -391,38 +388,6 @@ Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap
}
-/**Function*************************************************************
-
- Synopsis [Unmaps the network.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NtkUnmap( Abc_Ntk_t * pNtk )
-{
- Abc_Obj_t * pNode;
- char * pSop;
- int i;
-
- assert( Abc_NtkIsMappedLogic(pNtk) );
- // update the functionality manager
- assert( pNtk->pManFunc == Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
- pNtk->pManFunc = Extra_MmFlexStart();
- pNtk->ntkFunc = ABC_FUNC_SOP;
- // update the nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- pSop = Mio_GateReadSop(pNode->pData);
- assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) );
- pNode->pData = Abc_SopRegister( pNtk->pManFunc, pSop );
- }
- return 1;
-}
-
@@ -446,18 +411,18 @@ Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk )
assert( Abc_NtkIsStrash(pNtk) );
// check that the library is available
- if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == NULL )
+ if ( Abc_FrameReadLibGen() == NULL )
{
printf( "The current library is not available.\n" );
return 0;
}
// derive the supergate library
- if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL && Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) )
+ if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() )
{
printf( "A simple supergate library is derived from gate library \"%s\".\n",
- Mio_LibraryReadName(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) );
- Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
+ Mio_LibraryReadName(Abc_FrameReadLibGen()) );
+ Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() );
}
// print a warning about choice nodes
@@ -504,6 +469,7 @@ Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk )
***********************************************************************/
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;
@@ -519,8 +485,12 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
// duplicate the network
pNtkNew2 = Abc_NtkDup( pNtk );
- pNtkNew = Abc_NtkRenode( pNtkNew2, 0, 20, 0, 0, 1 );
- Abc_NtkBddToSop( pNtkNew );
+ 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 )
@@ -534,14 +504,14 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
// set the pointers from the mapper to the new nodes
Abc_NtkForEachCi( pNtk, pNode, i )
{
- Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NodeCreateInv(pNtkNew,pNode->pCopy) );
+ 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_NodeCreateInv(pNtkNew,pNode->pCopy) );
+// 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 );
}
@@ -550,8 +520,8 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
Abc_NtkForEachNode( pNtk, pNode, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- if ( Abc_NodeIsConst(pNode) )
- continue;
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
Abc_NodeSuperChoice( pNtkNew, pNode );
}
Extra_ProgressBarStop( pProgress );
@@ -661,7 +631,7 @@ Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * p
* (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_NodeCreateConst0(pNtkNew);
+ return Abc_NtkCreateNodeConst0(pNtkNew);
}
}
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
index 1e728d92..257d930f 100644
--- a/src/base/abci/abcMiter.c
+++ b/src/base/abci/abcMiter.c
@@ -24,16 +24,19 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
-static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb );
+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_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode );
-static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb );
-static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame, Vec_Ptr_t * vNodes );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -47,18 +50,20 @@ static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int i
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+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, fComb ) )
+ 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));
- fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0));
+ 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 );
+ pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize );
if ( fRemove1 ) Abc_NtkDelete( pNtk1 );
if ( fRemove2 ) Abc_NtkDelete( pNtk2 );
return pTemp;
@@ -75,24 +80,24 @@ Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
+Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize )
{
- char Buffer[100];
+ char Buffer[1000];
Abc_Ntk_t * pNtkMiter;
assert( Abc_NtkIsStrash(pNtk1) );
assert( Abc_NtkIsStrash(pNtk2) );
// start the new network
- pNtkMiter = Abc_NtkAlloc( ABC_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
- pNtkMiter->pName = util_strsav(Buffer);
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
// perform strashing
- Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb );
+ Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize );
Abc_NtkMiterAddOne( pNtk1, pNtkMiter );
Abc_NtkMiterAddOne( pNtk2, pNtkMiter );
- Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb );
+ Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize );
Abc_AigCleanup(pNtkMiter->pManFunc);
// make sure that everything is okay
@@ -116,13 +121,16 @@ Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
SeeAlso []
***********************************************************************/
-void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb )
+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
@@ -134,12 +142,15 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk
pObj = Abc_NtkCi(pNtk2, i);
pObj->pCopy = pObjNew;
// add name
- Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObj) );
+ 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 only PO
- pObjNew = Abc_NtkCreatePo( pNtkMiter );
- // add the PO name
- Abc_NtkLogicStoreName( pObjNew, "miter" );
}
else
{
@@ -152,28 +163,31 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk
pObj = Abc_NtkPi(pNtk2, i);
pObj->pCopy = pObjNew;
// add name
- Abc_NtkLogicStoreName( pObjNew, Abc_ObjName(pObj) );
+ 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 only PO
- pObjNew = Abc_NtkCreatePo( pNtkMiter );
- // add the PO name
- Abc_NtkLogicStoreName( pObjNew, "miter" );
// create the latches
Abc_NtkForEachLatch( pNtk1, pObj, i )
{
- pObjNew = Abc_NtkDupObj( pNtkMiter, pObj );
- Vec_PtrPush( pNtkMiter->vCis, pObjNew );
- Vec_PtrPush( pNtkMiter->vCos, pObjNew );
- // add name
- Abc_NtkLogicStoreNamePlus( pObjNew, Abc_ObjName(pObj), "_1" );
+ 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_NtkDupObj( pNtkMiter, pObj );
- Vec_PtrPush( pNtkMiter->vCis, pObjNew );
- Vec_PtrPush( pNtkMiter->vCos, pObjNew );
+ pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 );
// add name
- Abc_NtkLogicStoreNamePlus( pObjNew, Abc_ObjName(pObj), "_2" );
+ 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" );
}
}
}
@@ -191,26 +205,11 @@ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtk
***********************************************************************/
void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter )
{
- ProgressBar * pProgress;
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pConst1, * pConst1New;
+ Abc_Obj_t * pNode;
int i;
- // get the constant nodes
- pConst1 = Abc_AigConst1( pNtk->pManFunc );
- pConst1New = Abc_AigConst1( pNtkMiter->pManFunc );
- // perform strashing
- vNodes = Abc_NtkDfs( pNtk, 0 );
- pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
- Vec_PtrForEachEntry( vNodes, pNode, i )
- {
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- if ( pNode == pConst1 )
- pNode->pCopy = pConst1New;
- else
- pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
- }
- Vec_PtrFree( vNodes );
- Extra_ProgressBarStop( pProgress );
+ assert( Abc_NtkIsDfsOrdered(pNtk) );
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
}
/**Function*************************************************************
@@ -227,22 +226,15 @@ void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter )
void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot )
{
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pNodeNew, * pConst1, * pConst1New;
+ Abc_Obj_t * pNode;
int i;
- // get the constant nodes
- pConst1 = Abc_AigConst1( pNtk->pManFunc );
- pConst1New = Abc_AigConst1( pNtkMiter->pManFunc );
+ // map the constant nodes
+ Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter);
// perform strashing
vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 );
- for ( i = 0; i < vNodes->nSize; i++ )
- {
- pNode = vNodes->pArray[i];
- if ( pNode == pConst1 )
- pNodeNew = pConst1New;
- else
- pNodeNew = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
- pNode->pCopy = pNodeNew;
- }
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ if ( Abc_AigNodeIsAnd(pNode) )
+ pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
Vec_PtrFree( vNodes );
}
@@ -258,7 +250,7 @@ void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * p
SeeAlso []
***********************************************************************/
-void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb )
+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;
@@ -286,19 +278,184 @@ void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNt
}
// connect new latches
Abc_NtkForEachLatch( pNtk1, pNode, i )
- Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+ Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) );
Abc_NtkForEachLatch( pNtk2, pNode, i )
- Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) );
+ Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) );
}
// add the miter
- pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairs );
+ 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 );
- Vec_PtrFree( vPairs );
+
+ // 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.]
@@ -312,7 +469,7 @@ void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNt
***********************************************************************/
Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 )
{
- char Buffer[100];
+ char Buffer[1000];
Abc_Ntk_t * pNtkMiter;
Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter;
@@ -320,21 +477,22 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
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_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) );
- pNtkMiter->pName = util_strsav(Buffer);
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
// get the root output
pRoot = Abc_NtkCo( pNtk, Out );
// perform strashing
- Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1 );
+ Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 );
// set the first cofactor
- Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter->pManFunc) );
+ Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
if ( In2 >= 0 )
- Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1( pNtkMiter->pManFunc );
+ Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter);
// add the first cofactor
Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
@@ -342,9 +500,9 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
// set the second cofactor
- Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1( pNtkMiter->pManFunc );
+ Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter);
if ( In2 >= 0 )
- Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter->pManFunc) );
+ Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) );
// add the second cofactor
Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
@@ -366,6 +524,98 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
}
+/**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;
+}
+
@@ -373,8 +623,8 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
Synopsis [Checks the status of the miter.]
- Description [Return 1 if the miter is sat for at least one output.
- Return 0 if the miter is unsat for all its outputs. Returns -1 if the
+ 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 []
@@ -389,23 +639,31 @@ int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter )
assert( Abc_NtkIsStrash(pMiter) );
Abc_NtkForEachPo( pMiter, pNodePo, i )
{
- pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) );
- if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) )
+ pChild = Abc_ObjChild0( pNodePo );
+ // check if the output is constant 1
+ if ( Abc_AigNodeIsConst(pChild) )
{
- assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter->pManFunc) );
+ 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 1;
+// 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 0, meaning all outputs are constant zero
- return 0;
+ // return 1, meaning all outputs are constant zero
+ return 1;
}
/**Function*************************************************************
@@ -426,7 +684,7 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter )
if ( Abc_NtkPoNum(pMiter) == 1 )
{
pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) );
- if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) )
+ if ( Abc_AigNodeIsConst(pChild) )
{
if ( Abc_ObjIsComplement(pChild) )
printf( "Unsatisfiable.\n" );
@@ -442,7 +700,7 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter )
{
pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) );
printf( "Output #%2d : ", i );
- if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) )
+ if ( Abc_AigNodeIsConst(pChild) )
{
if ( Abc_ObjIsComplement(pChild) )
printf( "Unsatisfiable.\n" );
@@ -469,23 +727,158 @@ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter )
***********************************************************************/
Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
{
- char Buffer[100];
+ char Buffer[1000];
ProgressBar * pProgress;
Abc_Ntk_t * pNtkFrames;
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pLatch, * pLatchNew;
+ 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_TYPE_STRASH, ABC_FUNC_AIG );
+ pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
- pNtkFrames->pName = util_strsav(Buffer);
+ 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
{
@@ -495,14 +888,17 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI
{
pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames);
- Abc_NtkLogicStoreName( pLatch->pCopy, Abc_ObjName(pLatch) );
+ Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL );
Counter++;
}
- else
- pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames->pManFunc), Abc_LatchIsInit0(pLatch) );
+ 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 variables.\n", Counter );
+ printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter );
}
// create the timeframes
@@ -511,7 +907,7 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
for ( i = 0; i < nFrames; i++ )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- Abc_NtkAddFrame( pNtkFrames, pNtk, i, vNodes );
+ Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg );
}
Extra_ProgressBarStop( pProgress );
Vec_PtrFree( vNodes );
@@ -521,13 +917,20 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
{
Abc_NtkForEachLatch( pNtk, pLatch, i )
{
- pLatchNew = Abc_NtkLatch(pNtkFrames, i);
- Abc_ObjAddFanin( pLatchNew, Abc_ObjFanin0(pLatch)->pCopy );
- Vec_PtrPush( pNtkFrames->vCis, pLatchNew );
- Vec_PtrPush( pNtkFrames->vCos, pLatchNew );
- Abc_NtkLogicStoreName( pLatchNew, Abc_ObjName(pLatch) );
+ 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 ) )
{
@@ -536,6 +939,8 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
return NULL;
}
return pNtkFrames;
+*/
+ return NULL;
}
/**Function*************************************************************
@@ -552,22 +957,24 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
SeeAlso []
***********************************************************************/
-void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes )
+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->pManFunc );
- pConst1New = Abc_AigConst1( pNtkFrames->pManFunc );
+ 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_NtkLogicStoreNamePlus( pNodeNew, Abc_ObjName(pNode), Buffer );
+ Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer );
+ if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
}
// add the internal nodes
Vec_PtrForEachEntry( vNodes, pNode, i )
@@ -577,20 +984,161 @@ void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_
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_NtkLogicStoreNamePlus( pNodeNew, Abc_ObjName(pNode), Buffer );
+ Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer );
+ if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg);
}
// transfer the implementation of the latch drivers to the latches
- Abc_NtkForEachLatch( pNtk, pLatch, i )
- pLatch->pCopy = Abc_ObjChild0Copy(pLatch);
+
+ // 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
index 6362a925..f127811e 100644
--- a/src/base/abci/abcNtbdd.c
+++ b/src/base/abci/abcNtbdd.c
@@ -25,12 +25,12 @@
////////////////////////////////////////////////////////////////////////
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, Abc_Obj_t * pConst1 );
+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 );
+static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -78,13 +78,13 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo
return NULL;
// start the network
- pNtk = Abc_NtkAlloc( ABC_TYPE_LOGIC, ABC_FUNC_BDD );
- pNtk->pName = util_strsav(pNamePo);
+ 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_NtkLogicStoreName( Abc_NtkCreatePi(pNtk), pName );
+ 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);
@@ -93,7 +93,7 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo
// create the only PO
pNodePo = Abc_NtkCreatePo( pNtk );
Abc_ObjAddFanin( pNodePo, pNode );
- Abc_NtkLogicStoreName( pNodePo, pNamePo );
+ Abc_ObjAssignName( pNodePo, pNamePo, NULL );
// make the network minimum base
Abc_NtkMinimumBase( pNtk );
if ( vNamesPiFake )
@@ -121,7 +121,7 @@ Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
assert( Abc_NtkIsBddLogic(pNtk) );
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_SOP );
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
Abc_NtkBddToMuxesPerform( pNtk, pNtkNew );
Abc_NtkFinalize( pNtk, pNtkNew );
// make sure everything is okay
@@ -148,12 +148,9 @@ Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk )
void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
ProgressBar * pProgress;
- DdManager * dd = pNtk->pManFunc;
- Abc_Obj_t * pNode, * pNodeNew, * pConst1;
+ Abc_Obj_t * pNode, * pNodeNew;
Vec_Ptr_t * vNodes;
int i;
- // create the constant one node
- pConst1 = Abc_NodeCreateConst1( pNtkNew );
// perform conversion in the topological order
vNodes = Abc_NtkDfs( pNtk, 0 );
pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
@@ -162,7 +159,7 @@ void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
Extra_ProgressBarUpdate( pProgress, i, NULL );
// convert one node
assert( Abc_ObjIsNode(pNode) );
- pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew, pConst1 );
+ pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew );
// mark the old node with the new one
assert( pNode->pCopy == NULL );
pNode->pCopy = pNodeNew;
@@ -182,7 +179,7 @@ void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pConst1 )
+Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
{
DdManager * dd = pNodeOld->pNtk->pManFunc;
DdNode * bFunc = pNodeOld->pData;
@@ -192,14 +189,13 @@ Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, Abc_O
// create the table mapping BDD nodes into the ABC nodes
tBdd2Node = st_init_table( st_ptrcmp, st_ptrhash );
// add the constant and the elementary vars
- st_insert( tBdd2Node, (char *)b1, (char *)pConst1 );
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_NodeCreateInv( pNtkNew, pNodeNew );
+ pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew );
return pNodeNew;
}
@@ -218,17 +214,19 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t *
{
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_NodeCreateInv( pNtkNew, pNodeNew0 );
+ 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_NodeCreateMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 );
+ pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 );
st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew );
return pNodeNew;
}
@@ -245,88 +243,96 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t *
SeeAlso []
***********************************************************************/
-DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly )
+DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose )
{
- int fReorder = 1;
ProgressBar * pProgress;
- Vec_Ptr_t * vFuncsGlob;
- Abc_Obj_t * pNode;
- DdNode * bFunc;
+ Abc_Obj_t * pObj, * pFanin;
+ Vec_Att_t * pAttMan;
DdManager * dd;
- int i;
+ DdNode * bFunc;
+ int i, k, Counter;
+
+ // remove dangling nodes
+ Abc_AigCleanup( pNtk->pManFunc );
// start the manager
- assert( pNtk->pManGlob == NULL );
+ 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 );
- // set the elementary variables
- Abc_NtkCleanCopy( pNtk );
- Abc_NtkForEachCi( pNtk, pNode, i )
- pNode->pCopy = (Abc_Obj_t *)dd->vars[i];
// assign the constant node BDD
- pNode = Abc_AigConst1( pNtk->pManFunc );
- pNode->pCopy = (Abc_Obj_t *)dd->one; Cudd_Ref( dd->one );
-
- // collect the global functions of the COs
- vFuncsGlob = Vec_PtrAlloc( 100 );
- if ( fLatchOnly )
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
{
- // construct the BDDs
- pProgress = Extra_ProgressBarStart( stdout, Abc_NtkLatchNum(pNtk) );
- Abc_NtkForEachLatch( pNtk, pNode, i )
+ bFunc = dd->one;
+ Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc );
+ }
+ // set the elementary variables
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
{
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode) );
- if ( bFunc == NULL )
- {
- printf( "Constructing global BDDs timed out.\n" );
- Extra_ProgressBarStop( pProgress );
- Cudd_Quit( dd );
- return NULL;
- }
- bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); Cudd_Ref( bFunc );
- Vec_PtrPush( vFuncsGlob, bFunc );
+ bFunc = dd->vars[i];
+// bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i];
+ Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc );
}
- Extra_ProgressBarStop( pProgress );
- }
- else
+
+ // collect the global functions of the COs
+ Counter = 0;
+ // construct the BDDs
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
{
- // construct the BDDs
- pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
- Abc_NtkForEachCo( pNtk, pNode, i )
+ bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose );
+ if ( bFunc == NULL )
{
- Extra_ProgressBarUpdate( pProgress, i, NULL );
- bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode) );
- if ( bFunc == NULL )
- {
- printf( "Constructing global BDDs timed out.\n" );
- Extra_ProgressBarStop( pProgress );
- Cudd_Quit( dd );
- return NULL;
- }
- bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pNode) ); Cudd_Ref( bFunc );
- Vec_PtrPush( vFuncsGlob, bFunc );
+ if ( fVerbose )
+ printf( "Constructing global BDDs is aborted.\n" );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
+ Cudd_Quit( dd );
+ return NULL;
}
- Extra_ProgressBarStop( pProgress );
+ bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc );
+ Abc_ObjSetGlobalBdd( pObj, bFunc );
}
+ Extra_ProgressBarStop( pProgress );
+/*
// derefence the intermediate BDDs
- Abc_NtkForEachNode( pNtk, pNode, i )
- if ( pNode->pCopy )
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ if ( pObj->pCopy )
{
- Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
- pNode->pCopy = NULL;
+ 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 );
}
- pNtk->pManGlob = dd;
- pNtk->vFuncsGlob = vFuncsGlob;
+// Cudd_PrintInfo( dd, stdout );
return dd;
}
@@ -341,39 +347,107 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fLatchOnly )
SeeAlso []
***********************************************************************/
-DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode )
+DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose )
{
- DdNode * bFunc, * bFunc0, * bFunc1;
+ DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC;
+ int fDetectMuxes = 1;
assert( !Abc_ObjIsComplement(pNode) );
- if ( Cudd_ReadKeys(dd) > 500000 )
+ 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 ( pNode->pCopy )
- return (DdNode *)pNode->pCopy;
- // compute the result for both branches
- bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0) );
- if ( bFunc0 == NULL )
- return NULL;
- Cudd_Ref( bFunc0 );
- bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1) );
- 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 );
- // set the result
- assert( pNode->pCopy == NULL );
- pNode->pCopy = (Abc_Obj_t *)bFunc;
+ 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 [Dereferences global BDDs of the network.]
+ Synopsis [Frees the global BDDs of the network.]
Description []
@@ -382,16 +456,123 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk )
+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;
- assert( pNtk->pManGlob );
- assert( pNtk->vFuncsGlob );
- Vec_PtrForEachEntry( pNtk->vFuncsGlob, bFunc, i )
- Cudd_RecursiveDeref( pNtk->pManGlob, bFunc );
- Vec_PtrFree( pNtk->vFuncsGlob );
- pNtk->vFuncsGlob = NULL;
+ 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 );
}
////////////////////////////////////////////////////////////////////////
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
index 506010c7..85c4e918 100644
--- a/src/base/abci/abcPart.c
+++ b/src/base/abci/abcPart.c
@@ -19,77 +19,87 @@
***********************************************************************/
#include "abc.h"
-#include "hop.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 [Returns the number of common entries.]
+ Synopsis [Start the memory manager.]
- Description [Assumes that the vectors are sorted in the increasing order.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize )
{
- int i, k, Counter = 0;
- for ( i = k = 0; i < Vec_IntSize(vArr1) && k < Vec_IntSize(vArr2); )
- {
- if ( Vec_IntEntry(vArr1,i) == Vec_IntEntry(vArr2,k) )
- Counter++, i++, k++;
- else if ( Vec_IntEntry(vArr1,i) < Vec_IntEntry(vArr2,k) )
- i++;
- else
- k++;
- }
- return Counter;
+ 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 [Returns the result of merging the two vectors.]
+ Synopsis [Stops the memory manager.]
- Description [Assumes that the vectors are sorted in the increasing order.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 )
+void Supp_ManStop( Supp_Man_t * p )
{
- Vec_Int_t * vArr;
- int i, k;
- vArr = Vec_IntAlloc( Vec_IntSize(vArr1) );
- for ( i = k = 0; i < Vec_IntSize(vArr1) && k < Vec_IntSize(vArr2); )
- {
- if ( Vec_IntEntry(vArr1,i) == Vec_IntEntry(vArr2,k) )
- Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) ), i++, k++;
- else if ( Vec_IntEntry(vArr1,i) < Vec_IntEntry(vArr2,k) )
- Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) ), i++;
- else
- Vec_IntPush( vArr, Vec_IntEntry(vArr2,k) ), k++;
- }
- for ( ; i < Vec_IntSize(vArr1); i++ )
- Vec_IntPush( vArr, Vec_IntEntry(vArr1,i) );
- for ( ; k < Vec_IntSize(vArr2); k++ )
- Vec_IntPush( vArr, Vec_IntEntry(vArr2,k) );
- return vArr;
+ void * pMemory;
+ int i;
+ Vec_PtrForEachEntry( p->vMemory, pMemory, i )
+ free( pMemory );
+ Vec_PtrFree( p->vMemory );
+ Vec_PtrFree( p->vFree );
+ free( p );
}
/**Function*************************************************************
- Synopsis [Comparison procedure for two arrays.]
+ Synopsis [Fetches the memory entry of the given size.]
Description []
@@ -98,18 +108,35 @@ static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2
SeeAlso []
***********************************************************************/
-static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+char * Supp_ManFetch( Supp_Man_t * p, int nSize )
{
- if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
- return -1;
- if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
- return 1;
- return 0;
+ 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 [Comparison procedure for two integers.]
+ Synopsis [Recycles the memory entry of the given size.]
Description []
@@ -118,18 +145,18 @@ static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
SeeAlso []
***********************************************************************/
-static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
+void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize )
{
- if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) )
- return -1;
- if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) )
- return 1;
- return 0;
+ 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 [Sorting the entries by their integer value.]
+ Synopsis [Fetches the memory entry of the given size.]
Description []
@@ -138,19 +165,19 @@ static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 )
SeeAlso []
***********************************************************************/
-static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse )
+static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs )
{
- if ( fReverse )
- qsort( (void *)p->pArray, p->nSize, sizeof(void *),
- (int (*)(const void *, const void *)) Vec_VecSortCompare2 );
- else
- qsort( (void *)p->pArray, p->nSize, sizeof(void *),
- (int (*)(const void *, const void *)) Vec_VecSortCompare1 );
+ 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 [Performs DFS for one node.]
+ Synopsis [Recycles the memory entry of the given size.]
Description []
@@ -159,31 +186,16 @@ static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse )
SeeAlso []
***********************************************************************/
-void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry )
{
- Abc_Obj_t * pFanin;
- int i;
- assert( !Abc_ObjIsNet(pNode) );
- // if this node is already visited, skip
- if ( Abc_NodeIsTravIdCurrent( pNode ) )
- return;
- // mark the node as visited
- Abc_NodeSetTravIdCurrent( pNode );
- // collect the CI
- if ( Abc_ObjIsCi(pNode) || Abc_ObjFaninNum(pNode) == 0 )
- {
- Vec_PtrPush( vNodes, pNode );
- return;
- }
- assert( Abc_ObjIsNode( pNode ) );
- // visit the transitive fanin of the node
- Abc_ObjForEachFanin( pNode, pFanin, i )
- Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes );
+ 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 [Returns the set of CI nodes in the support of the given nodes.]
+ Synopsis [Merges two entries.]
Description []
@@ -192,26 +204,37 @@ void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes )
+Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs )
{
- Vec_Ptr_t * vNodes;
- int i;
- // set the traversal ID
- Abc_NtkIncrementTravId( pNtk );
- // start the array of nodes
- vNodes = Vec_PtrAlloc( 100 );
- // go through the PO nodes and call for each of them
- for ( i = 0; i < nNodes; i++ )
- if ( Abc_ObjIsCo(ppNodes[i]) )
- Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes );
- else
- Abc_NtkNodeSupport_rec( ppNodes[i], vNodes );
- return vNodes;
+ 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 [Extra_UtilStrsav()]
+ Synopsis [Tranfers the entry.]
Description []
@@ -220,16 +243,19 @@ Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNod
SeeAlso []
***********************************************************************/
-char * Extra_UtilStrsav( char * s )
+Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p )
{
- if ( s == NULL )
- return s;
- return strcpy(ALLOC(char, strlen(s)+1), s);
+ 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 [Creates the network composed of several logic cones.]
+ Synopsis [Computes supports of the POs in the multi-output AIG.]
Description []
@@ -238,198 +264,257 @@ char * Extra_UtilStrsav( char * s )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis )
+Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk )
{
- Abc_Ntk_t * pNtkNew;
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
- char Buffer[1000];
+ Abc_Obj_t * pObj, * pNext;
int i, k;
-
- assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
-
- // start the network
- pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
- // set the name
- sprintf( Buffer, "%s_part", pNtk->pName );
- pNtkNew->pName = Extra_UtilStrsav(Buffer);
-
- // establish connection between the constant nodes
- if ( Abc_NtkIsStrash(pNtk) )
- Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkNew->pManFunc);
-
- // collect the nodes in the TFI of the output (mark the TFI)
- vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) );
-
- // create the PIs
- Abc_NtkForEachCi( pNtk, pObj, i )
- {
- if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS
- {
- pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
-// Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
- Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) );
- }
- }
-
- // copy the nodes
- Vec_PtrForEachEntry( vNodes, pObj, i )
- {
- // if it is an AIG, add to the hash table
- if ( Abc_NtkIsStrash(pNtk) )
- {
- pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
- }
- else
- {
- Abc_NtkDupObj( pNtkNew, pObj );
- Abc_ObjForEachFanin( pObj, pFanin, k )
- Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
- }
- }
- Vec_PtrFree( vNodes );
-
- // add the PO corresponding to the nodes
- Vec_PtrForEachEntry( vRoots, pObj, i )
+ 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 )
{
- // create the PO node
- pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
- // connect the internal nodes to the new CO
- if ( Abc_ObjIsCo(pObj) )
- Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) );
- else
- Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy );
- // assign the name
-// Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL );
- Abc_NtkLogicStoreName( pNodeCoNew, Abc_ObjName(pObj) );
+ // 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 );
+ }
}
-
- if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" );
- return pNtkNew;
+ return vNodes;
}
/**Function*************************************************************
- Synopsis [Appends the second network to the first.]
+ Synopsis [Computes supports of the POs.]
- 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.]
+ Description [Returns the ptr-vector of int-vectors.]
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NtkAppendNew( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+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;
-// char * pName;
- int i, nNewCis;
- // the first network should be an AIG
- assert( Abc_NtkIsStrash(pNtk1) );
- assert( Abc_NtkIsStrash(pNtk2) );
- // 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 );
- Abc_AigConst1(pNtk2->pManFunc)->pCopy = Abc_AigConst1(pNtk1->pManFunc);
- Abc_NtkForEachCi( pNtk2, pObj, i )
+ 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 )
{
-// pName = Abc_ObjName(pObj);
-// pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj));
- pObj->pCopy = Abc_NtkCi( pNtk1, i );
- if ( pObj->pCopy == NULL )
+ if ( Abc_ObjIsNode(pObj) )
{
- pObj->pCopy = Abc_NtkDupObj( pNtk1, pObj );
- nNewCis++;
+ 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 ( nNewCis )
- printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis );
- // add pNtk2 to pNtk1 while strashing
- Abc_NtkForEachNode( pNtk2, pObj, i )
- {
- if ( Abc_ObjFaninNum(pObj) == 0 )
+ 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;
- pObj->pCopy = Abc_AigAnd( pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
- }
- // add the COs of the second network
- {
- Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew;
- int fCompl;//, iNodeId;
- // OR the choices
- Abc_NtkForEachCo( pNtk2, pObj, i )
+ }
+ if ( Abc_ObjIsCi(pObj) )
{
-// iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
-// assert( iNodeId >= 0 );
-// pObjOld = Abc_NtkObj( pNtk1, iNodeId );
- pObjOld = Abc_NtkCo( pNtk1, i );
-
- // 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) );
+ 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 );
}
- // make sure that everything is okay
- if ( !Abc_NtkCheck( pNtk1 ) )
- {
- printf( "Abc_NtkAppend: The network check has failed.\n" );
- return 0;
- }
- return 1;
+ 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 [Prepare supports.]
+ Synopsis [Computes supports of the POs using naive method.]
- Description []
+ Description [Returns the ptr-vector of int-vectors.]
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Abc_NtkPartitionCollectSupps( Abc_Ntk_t * pNtk )
+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, pTemp->Id );
+ 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 []
@@ -439,8 +524,9 @@ Vec_Ptr_t * Abc_NtkPartitionCollectSupps( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, int nPartSizeLimit, Vec_Int_t * vOne )
+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;
@@ -448,12 +534,12 @@ int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vParts
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;
- vPart = Vec_PtrEntry( vPartsAll, i );
- if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) > nPartSizeLimit )
- continue;
if ( nCommon == Vec_IntSize(vOne) )
return i;
Attract = 1.0 * nCommon / Vec_IntSize(vOne);
@@ -471,6 +557,49 @@ int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vParts
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*************************************************************
@@ -498,7 +627,7 @@ void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t *
if ( i == Vec_PtrSize(vPartsAll) - 1 )
break;
}
- assert( Counter == Abc_NtkCoNum(pNtk) );
+// assert( Counter == Abc_NtkCoNum(pNtk) );
printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) );
}
@@ -513,20 +642,20 @@ void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t *
SeeAlso []
***********************************************************************/
-void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nPartSizeLimit )
+void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit )
{
Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp;
int i, iPart;
- if ( nPartSizeLimit == 0 )
- nPartSizeLimit = 200;
+ 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) < nPartSizeLimit )
+ if ( Vec_IntSize(vOne) < nSuppSizeLimit )
{
if ( vPartSupp == NULL )
{
@@ -542,7 +671,7 @@ void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll,
Vec_IntFree( vTemp );
Vec_IntFree( Vec_PtrEntry(vPartsAll, i) );
}
- if ( Vec_IntSize(vPartSupp) < nPartSizeLimit )
+ if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit )
continue;
}
else
@@ -578,37 +707,49 @@ void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll,
Synopsis [Perform the smart partitioning.]
- Description []
+ Description [Returns the ptr-vector of int-vectors.]
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Vec_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose )
+Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose )
{
- Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll, * vPartPtr;
+ 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;
+ int i, iPart, iOut, clk, clk2, timeFind = 0;
// compute the supports for all outputs
clk = clock();
- vSupps = Abc_NtkPartitionCollectSupps( pNtk );
+// 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
- iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, nPartSizeLimit, vOne );
+clk2 = clock();
+ iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nSuppSizeLimit, vOne );
+timeFind += clock() - clk2;
if ( iPart == -1 )
{
// create new partition
@@ -619,6 +760,8 @@ clk = clock();
// add this partition and its support
Vec_PtrPush( vPartsAll, vPart );
Vec_PtrPush( vPartSuppsAll, vPartSupp );
+
+ Vec_PtrPush( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) );
}
else
{
@@ -631,11 +774,22 @@ clk = clock();
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();
@@ -653,18 +807,20 @@ clk = clock();
// compact small partitions
// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll );
- Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nPartSizeLimit );
- if ( fVerbose )
- 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 )
{
@@ -674,34 +830,54 @@ PRT( "Comps", clock() - clk );
Vec_IntFree( vPart );
Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr );
}
- return (Vec_Vec_t *)vPartsAll;
+*/
+ return vPartsAll;
}
/**Function*************************************************************
Synopsis [Perform the naive partitioning.]
- Description []
+ Description [Returns the ptr-vector of int-vectors.]
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Vec_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize )
+Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize )
{
- Vec_Vec_t * vParts;
+ Vec_Ptr_t * vParts;
Abc_Obj_t * pObj;
int nParts, i;
nParts = (Abc_NtkCoNum(pNtk) / nPartSize) + ((Abc_NtkCoNum(pNtk) % nPartSize) > 0);
- vParts = Vec_VecStart( nParts );
+ vParts = (Vec_Ptr_t *)Vec_VecStart( nParts );
Abc_NtkForEachCo( pNtk, pObj, i )
- Vec_VecPush( vParts, i / nPartSize, pObj );
+ 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 []
@@ -744,7 +920,6 @@ static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t
return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) );
}
-
/**Function*************************************************************
Synopsis []
@@ -781,24 +956,18 @@ Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk )
pMan->vObjs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) + 1 );
Vec_PtrPush( pMan->vObjs, Hop_ManConst1(pMan) );
// map constant node and PIs
- Abc_AigConst1(pNtk->pManFunc)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan);
+ 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 )
- Abc_NtkForEachNode( pNtk, pObj, i )
+ Abc_AigForEachAnd( pNtk, pObj, i )
{
- if ( Abc_ObjFaninNum(pObj) == 0 )
- continue;
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 )
- Abc_NtkForEachNode( pNtk, pObj, i )
+ Abc_AigForEachAnd( pNtk, pObj, i )
{
- if ( Abc_ObjFaninNum(pObj) == 0 )
- continue;
if ( pObj->pCopy )
((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext;
}
@@ -813,58 +982,6 @@ Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk )
/**Function*************************************************************
- Synopsis [Maps terminals of the old networks into those of the new network.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NtkPartMapTerminals( Vec_Ptr_t * vParts, Abc_Ntk_t * pNtkOld )
-{
- Abc_Ntk_t * pNtkNew;
- stmm_table * tTablePi, * tTablePo;
- Abc_Obj_t * pObj, * pTemp;
- int i, k;
-
- // map names into old nodes
- tTablePi = stmm_init_table( strcmp, stmm_strhash );
- tTablePo = stmm_init_table( strcmp, stmm_strhash );
- Abc_NtkForEachPi( pNtkOld, pObj, i )
- stmm_insert( tTablePi, Abc_ObjName(pObj), (char *)pObj );
- Abc_NtkForEachPo( pNtkOld, pObj, i )
- stmm_insert( tTablePo, Abc_ObjName(pObj), (char *)pObj );
-
- // map new nodes into old nodes
- Vec_PtrForEachEntry( vParts, pNtkNew, k )
- {
- Abc_NtkForEachPi( pNtkNew, pObj, i )
- {
- if ( !stmm_lookup(tTablePi, Abc_ObjName(pObj), (char **)&pTemp) )
- {
- printf( "Cannot find PI node %s in the original network.\n", Abc_ObjName(pObj) );
- return;
- }
- pObj->pCopy = pTemp;
- }
- Abc_NtkForEachPo( pNtkNew, pObj, i )
- {
- if ( !stmm_lookup(tTablePo, Abc_ObjName(pObj), (char **)&pTemp) )
- {
- printf( "Cannot find PO node %s in the original network.\n", Abc_ObjName(pObj) );
- return;
- }
- pObj->pCopy = pTemp;
- }
- }
- stmm_free_table( tTablePi );
- stmm_free_table( tTablePo );
-}
-
-/**Function*************************************************************
-
Synopsis [Stitches together several networks with choice nodes.]
Description []
@@ -879,36 +996,23 @@ 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;
- Abc_Ntk_t * pNtkNew, * pNtkTemp;
Vec_Ptr_t * vNodes;
+ Abc_Ntk_t * pNtkNew, * pNtkTemp;
Abc_Obj_t * pObj, * pFanin;
- int i, k;
+ int i, k, iNodeId;
// start a new network similar to the original one
assert( Abc_NtkIsStrash(pNtk) );
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
-
+ 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 );
- }
-
- // perform mapping of terminals
- Abc_NtkPartMapTerminals( vParts, pNtkNew );
-
-
- // 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->pManFunc)->pCopy = Abc_AigConst1(pNtkNew->pManFunc);
-/*
+ 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 );
@@ -919,16 +1023,14 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
}
pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId );
}
-*/
+
// add the internal nodes while saving representatives
vNodes = Abc_AigDfs( pNtkTemp, 1, 0 );
Vec_PtrForEachEntry( vNodes, pObj, k )
{
- if ( Abc_ObjFaninNum(pObj) == 0 )
- continue;
pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
assert( !Abc_ObjIsComplement(pObj->pCopy) );
- if ( Abc_NodeIsAigChoice(pObj) )
+ if ( Abc_AigNodeIsChoice(pObj) )
for ( pFanin = pObj->pData; pFanin; pFanin = pFanin->pData )
pFanin->pCopy->pCopy = pObj->pCopy;
}
@@ -937,7 +1039,6 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
// 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 )
{
@@ -945,11 +1046,23 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
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 );
@@ -977,49 +1090,112 @@ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkFraigPartitioned( Abc_Ntk_t * pNtk, void * pParams )
+Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams )
{
extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
extern void * Abc_FrameGetGlobalFrame();
- Vec_Vec_t * vParts;
- Vec_Ptr_t * vFraigs, * vOne;
- Abc_Ntk_t * pNtkAig, * pNtkFraig;
- int i;
+ 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, 0, 0 );
+ vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 );
Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );
// fraig each partition
- vFraigs = Vec_PtrAlloc( Vec_VecSize(vParts) );
- Vec_VecForEachLevel( vParts, vOne, i )
+ vOnePtr = Vec_PtrAlloc( 1000 );
+ vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+ Vec_PtrForEachEntry( vParts, vOne, i )
{
- pNtkAig = Abc_NtkCreateConeArray( pNtk, vOne, 0 );
- pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0 );
+ // 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( "Finished part %d (out of %d)\r", i+1, Vec_VecSize(vParts) );
}
- Vec_VecFree( vParts );
- printf( " \r" );
+ 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_NtkPrintStats( stdout, pNtkAig, 0 );
+ 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_PtrFree( vFraigs );
+ Vec_VecFree( (Vec_Vec_t *)vParts );
- return pNtkFraig;
+ 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 );
}
////////////////////////////////////////////////////////////////////////
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
index 41b9288e..4003a6d6 100644
--- a/src/base/abci/abcPrint.c
+++ b/src/base/abci/abcPrint.c
@@ -20,13 +20,24 @@
#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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -44,57 +55,171 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
{
int Num;
- fprintf( pFile, "%-13s:", pNtk->pName );
- fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) );
+// if ( Abc_NtkIsStrash(pNtk) )
+// Abc_AigCountNext( pNtk->pManFunc );
- if ( !Abc_NtkIsSeq(pNtk) )
- fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) );
+ fprintf( pFile, "%-13s:", pNtk->pName );
+ if ( Abc_NtkAssertNum(pNtk) )
+ fprintf( pFile, " i/o/a = %5d/%5d/%5d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkAssertNum(pNtk) );
else
- fprintf( pFile, " lat = %4d", Abc_NtkSeqLatchNum(pNtk) );
-
+ fprintf( pFile, " i/o = %5d/%5d", 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, " 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 if ( Abc_NtkIsSeq(pNtk) )
- fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
else
+ {
fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
+ fprintf( pFile, " edge = %6d", Abc_NtkGetTotalFanins(pNtk) );
+ }
- if ( Abc_NtkHasSop(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) );
+ 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_NtkHasAig(pNtk) )
+ else if ( !Abc_NtkHasBlackbox(pNtk) )
{
assert( 0 );
}
if ( Abc_NtkIsStrash(pNtk) )
- fprintf( pFile, " lev = %3d", Abc_AigGetLevelNum(pNtk) );
- else if ( !Abc_NtkIsSeq(pNtk) )
- fprintf( pFile, " lev = %3d", Abc_NtkGetLevelNum(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*************************************************************
@@ -116,6 +241,7 @@ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk )
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) );
@@ -125,7 +251,8 @@ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk )
fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) );
Abc_NtkForEachLatch( pNtk, pObj, i )
- fprintf( pFile, " %s", Abc_ObjName(pObj) );
+ fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj),
+ Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) );
fprintf( pFile, "\n" );
}
@@ -144,34 +271,38 @@ void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pLatch, * pFanin;
int i, Counter0, Counter1, Counter2;
- int Init0, Init1, Init2;
+ int InitNums[4], Init;
+ assert( !Abc_NtkIsNetlist(pNtk) );
if ( Abc_NtkLatchNum(pNtk) == 0 )
{
fprintf( pFile, "The network is combinational.\n" );
return;
}
- assert( !Abc_NtkIsNetlist(pNtk) );
-
- Init0 = Init1 = Init2 = 0;
+ for ( i = 0; i < 4; i++ )
+ InitNums[i] = 0;
Counter0 = Counter1 = Counter2 = 0;
-
Abc_NtkForEachLatch( pNtk, pLatch, i )
{
- if ( Abc_LatchIsInit0(pLatch) )
- Init0++;
- else if ( Abc_LatchIsInit1(pLatch) )
- Init1++;
- else if ( Abc_LatchIsInitDc(pLatch) )
- Init2++;
+ 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 );
- pFanin = Abc_ObjFanin0(pLatch);
- if ( !Abc_ObjIsNode(pFanin) || !Abc_NodeIsConst(pFanin) )
- continue;
-
// the latch input is a constant node
Counter0++;
if ( Abc_LatchIsInitDc(pLatch) )
@@ -187,18 +318,15 @@ void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk )
}
else
{
- if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(pLatch) )
+ if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) )
Counter2++;
}
}
-// fprintf( pFile, "%-15s: ", pNtk->pName );
-// fprintf( pFile, "L = %5d: 0 = %4d. 1 = %3d. DC = %4d. ", Abc_NtkLatchNum(pNtk), Init0, Init1, Init2 );
-// fprintf( pFile, "Con = %3d. DC = %3d. Mat = %3d. ", Counter0, Counter1, Counter2 );
-// fprintf( pFile, "SFeed = %2d.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
fprintf( pFile, "%-15s: ", pNtk->pName );
- fprintf( pFile, "Lat = %5d: 0 = %4d. 1 = %3d. DC = %4d. \n", Abc_NtkLatchNum(pNtk), Init0, Init1, Init2 );
- fprintf( pFile, "Con = %3d. DC = %3d. Mat = %3d. ", Counter0, Counter1, Counter2 );
- fprintf( pFile, "SFeed = %2d.\n", Abc_NtkCountSelfFeedLatches(pNtk) );
+ 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*************************************************************
@@ -230,6 +358,7 @@ void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * 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;
@@ -301,6 +430,26 @@ void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode )
/**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 []
@@ -371,10 +520,26 @@ void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames )
SeeAlso []
***********************************************************************/
-void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile )
+void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes )
{
Abc_Obj_t * pNode;
- int i, Length;
+ 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) )
@@ -416,7 +581,7 @@ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile )
int nOutsSum, nOutsTotal;
if ( !Abc_NtkIsStrash(pNtk) )
- Abc_NtkGetLevelNum(pNtk);
+ Abc_NtkLevel(pNtk);
LevelMax = 0;
Abc_NtkForEachCo( pNtk, pNode, i )
@@ -498,6 +663,289 @@ void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode )
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
index 60a02aed..e77f055a 100644
--- a/src/base/abci/abcReconv.c
+++ b/src/base/abci/abcReconv.c
@@ -44,7 +44,7 @@ static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLe
static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -321,7 +321,9 @@ int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int
{
CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit );
//printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur );
- if ( CostBest > 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;
@@ -489,18 +491,20 @@ void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
SeeAlso []
***********************************************************************/
-DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited )
+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( &pNode, 1, vLeaves, vVisited, 0 );
+ 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 );
@@ -585,7 +589,7 @@ Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNode
p->vConeLeaves = Vec_PtrAlloc( 100 );
p->vVisited = Vec_PtrAlloc( 100 );
p->vLevels = Vec_VecAlloc( 100 );
- p->vNodesTfo = Vec_PtrAlloc( 100 );
+ p->vNodesTfo = Vec_PtrAlloc( 100 );
p->nNodeSizeMax = nNodeSizeMax;
p->nConeSizeMax = nConeSizeMax;
p->nNodeFanStop = nNodeFanStop;
@@ -641,6 +645,22 @@ Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p )
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;
@@ -692,7 +712,7 @@ Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Pt
// mark MFFC
if ( pRoot )
- Abc_NodeMffcLabel( pRoot );
+ Abc_NodeMffcLabelAig( pRoot );
// go through the levels up
Vec_PtrClear( p->vNodesTfo );
diff --git a/src/base/abci/abcRefactor.c b/src/base/abci/abcRefactor.c
index 92d497fc..b925f1b9 100644
--- a/src/base/abci/abcRefactor.c
+++ b/src/base/abci/abcRefactor.c
@@ -43,6 +43,8 @@ struct Abc_ManRef_t_
int nNodesConsidered;
int nNodesRefactored;
int nNodesGained;
+ int nNodesBeg;
+ int nNodesEnd;
// runtime statistics
int timeCut;
int timeBdd;
@@ -58,10 +60,10 @@ struct Abc_ManRef_t_
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 fUseZeros, bool fUseDcs, bool fVerbose );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -80,8 +82,9 @@ static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec
SeeAlso []
***********************************************************************/
-int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseZeros, bool fUseDcs, bool fVerbose )
+int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose )
{
+ extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
ProgressBar * pProgress;
Abc_ManRef_t * pManRef;
Abc_ManCut_t * pManCut;
@@ -98,16 +101,22 @@ int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool
pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 );
pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose );
pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCut );
- Abc_NtkStartReverseLevels( pNtk );
+ // 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) )
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ // skip persistant nodes
+ if ( Abc_NodeIsPersistant(pNode) )
continue;
// skip the nodes with many fanouts
if ( Abc_ObjFanoutNum(pNode) > 1000 )
@@ -121,18 +130,23 @@ clk = clock();
pManRef->timeCut += clock() - clk;
// evaluate this cut
clk = clock();
- pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUseZeros, fUseDcs, fVerbose );
+ 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, pManRef->nLastGain );
+ 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 )
@@ -140,7 +154,14 @@ pManRef->timeTotal = clock() - clkStart;
// delete the managers
Abc_NtkManCutStop( pManCut );
Abc_NtkManRefStop( pManRef );
- Abc_NtkStopReverseLevels( pNtk );
+ // 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 ) )
{
@@ -161,14 +182,18 @@ pManRef->timeTotal = clock() - clkStart;
SeeAlso []
***********************************************************************/
-Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUseZeros, bool fUseDcs, bool fVerbose )
+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 )
{
+ extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
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++;
@@ -214,7 +239,7 @@ p->timeDcs += clock() - clk;
// get the SOP of the cut
clk = clock();
- pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, p->vCube, -1 );
+ pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, 0, p->vCube, -1 );
p->timeSop += clock() - clk;
// get the factored form
@@ -229,7 +254,7 @@ p->timeFact += clock() - clk;
pFanin->vFanouts.nSize++;
// label MFFC with current traversal ID
Abc_NtkIncrementTravId( pNode->pNtk );
- nNodesSaved = Abc_NodeMffcLabel( pNode );
+ nNodesSaved = Abc_NodeMffcLabelAig( pNode );
// unmark the fanin boundary and set the fanins as leaves in the form
Vec_PtrForEachEntry( vFanins, pFanin, i )
{
@@ -239,7 +264,7 @@ p->timeFact += clock() - clk;
// detect how many new nodes will be added (while taking into account reused nodes)
clk = clock();
- nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Abc_NodeReadRequiredLevel(pNode) );
+ nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required );
p->timeEval += clock() - clk;
// quit if there is no improvement
if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !fUseZeros )
@@ -336,7 +361,7 @@ 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( "Calculated gain = %8d.\n", p->nNodesGained );
+ 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 );
diff --git a/src/base/abci/abcRenode.c b/src/base/abci/abcRenode.c
index 165777f8..8e8e8719 100644
--- a/src/base/abci/abcRenode.c
+++ b/src/base/abci/abcRenode.c
@@ -6,7 +6,7 @@
PackageName [Network and node package.]
- Synopsis [Procedures which transform an AIG into the network of SOP logic nodes.]
+ Synopsis []
Author [Alan Mishchenko]
@@ -19,479 +19,172 @@
***********************************************************************/
#include "abc.h"
+#include "reo.h"
+#include "if.h"
+#include "kit.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NtkRenodeInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
-static Abc_Obj_t * Abc_NtkRenode_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld );
+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 DdNode * Abc_NtkRenodeDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins );
+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 void Abc_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax );
-static void Abc_NtkRenodeSetBoundsCnf( Abc_Ntk_t * pNtk );
-static void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh );
-static void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk );
-static void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone );
+static int nDsdCounter = 0;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Transforms the AIG into nodes.]
+ Synopsis [Performs renoding as technology mapping.]
- Description [Threhold is the max number of nodes duplicated at a node.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple )
+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;
- 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_NtkRenodeSetBoundsCnf( pNtk );
- else if ( fMulti )
- Abc_NtkRenodeSetBoundsMulti( pNtk, nThresh );
- else if ( fSimple )
- Abc_NtkRenodeSetBoundsSimple( pNtk );
- else
- Abc_NtkRenodeSetBounds( pNtk, nThresh, nFaninMax );
-
- // perform renoding for this boundary
- pNtkNew = Abc_NtkStartFrom( pNtk, ABC_TYPE_LOGIC, ABC_FUNC_BDD );
- Abc_NtkRenodeInt( 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 )
+ 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 )
{
-// 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 );
+ pPars->fArea = 1;
+ pPars->pFuncCost = Abc_NtkRenodeEvalCnf;
}
-//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) );
+ else if ( fUseMv )
+ pPars->pFuncCost = Abc_NtkRenodeEvalMv;
+ else
+ pPars->pFuncCost = Abc_NtkRenodeEvalAig;
- // make sure everything is okay
- if ( !Abc_NtkCheck( pNtkNew ) )
+ // start the manager
+ if ( fUseBdds )
{
- printf( "Abc_NtkRenode: The network check has failed.\n" );
- Abc_NtkDelete( pNtkNew );
- return NULL;
+ 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;
}
- 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_NtkRenodeInt( 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->pManFunc);
- if ( Abc_ObjFanoutNum(pConst1) > 0 )
+ else
{
- pNodeNew = Abc_NtkCreateNode( pNtkNew );
- pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData );
- pConst1->pCopy = pNodeNew;
+ assert( s_vMemory == NULL );
+ s_vMemory = Vec_IntAlloc( 1 << 16 );
+ s_vMemory2 = Vec_IntAlloc( 1 << 16 );
}
- // 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_NtkRenode_rec( pNtkNew, Abc_ObjFanin0(pNode) );
- }
- Extra_ProgressBarStop( pProgress );
+ // perform mapping/renoding
+ pNtkNew = Abc_NtkIf( pNtk, pPars );
- // clean the boundaries and data field in the old network
- Abc_NtkForEachObj( pNtk, pNode, i )
+ // start the manager
+ if ( fUseBdds )
{
- pNode->fMarkA = 0;
- pNode->pData = NULL;
+ Extra_StopManager( s_pDd );
+ Extra_ReorderQuit( s_pReo );
+ s_pReo = NULL;
+ s_pDd = NULL;
}
-}
-
-/**Function*************************************************************
-
- Synopsis [Find the best multi-input node rooted at the given node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Abc_Obj_t * Abc_NtkRenode_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_NodeIsConst(pNodeOld) );
- assert( pNodeOld->fMarkA );
-
- // collect the renoding cone
- vCone = Vec_PtrAlloc( 10 );
- Abc_NtkRenodeCone( pNodeOld, vCone );
-
- // create a new node
- pNodeNew = Abc_NtkCreateNode( pNtkNew );
- for ( i = 0; i < vCone->nSize; i++ )
- Abc_ObjAddFanin( pNodeNew, Abc_NtkRenode_rec(pNtkNew, vCone->pArray[i]) );
-
- // derive the function of this node
- pNodeNew->pData = Abc_NtkRenodeDeriveBdd( 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_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld )
-{
- Abc_Obj_t * pFaninOld;
- DdNode * bFunc;
- int i;
- assert( !Abc_NodeIsConst(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_NtkRenodeDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc );
- // dereference the intermediate nodes
- for ( i = 0; i < vFaninsOld->nSize; i++ )
+ else
{
- pFaninOld = vFaninsOld->pArray[i];
- Cudd_RecursiveDeref( dd, pFaninOld->pData );
- pFaninOld->fMarkC = 0;
+ Vec_IntFree( s_vMemory );
+ Vec_IntFree( s_vMemory2 );
+ s_vMemory = NULL;
+ s_vMemory2 = NULL;
}
- Cudd_Deref( bFunc );
- return bFunc;
-}
-/**Function*************************************************************
+// printf( "Decomposed %d functions.\n", nDsdCounter );
- Synopsis [Derives the local BDD of the node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-DdNode * Abc_NtkRenodeDeriveBdd_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_NtkRenodeDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 );
- bFunc1 = Abc_NtkRenodeDeriveBdd_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;
+ return pNtkNew;
}
-
-
/**Function*************************************************************
- Synopsis [Limits the cones to be no more than the given size.]
+ Synopsis [Computes the cost based on the factored form.]
- Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NtkRenodeLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst )
+int Abc_NtkRenodeEvalAig( If_Cut_t * pCut )
{
- 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_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 );
- Abc_NtkRenodeLimit_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_NtkRenodeLimit_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_NtkRenodeLimit_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_NtkRenodeLimit_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_NtkRenodeLimit_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_NtkRenodeLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax )
+ Kit_Graph_t * pGraph;
+ int i, nNodes;
+/*
+extern void Kit_DsdTest( unsigned * pTruth, int nVars );
+if ( If_CutLeaveNum(pCut) == 8 )
{
- vCone->nSize = 0;
- return Abc_NtkRenodeLimit_rec( pNode, vCone, nFaninMax, 1, 1 );
+ nDsdCounter++;
+ Kit_DsdTest( If_CutTruth(pCut), If_CutLeaveNum(pCut) );
}
-
-/**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_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax )
-{
- Vec_Ptr_t * vCone = pNtk->vPtrTemp;
- 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 ntil it meets the fanin limit
- while ( Abc_NtkRenodeLimit(pNode, vCone, nFaninMax) );
- assert( vCone->nSize <= nFaninMax );
- }
-/*
- // 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_NtkRenodeCone( 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_NtkRenodeSetBoundsCnf( 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 )
+ pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory );
+ if ( pGraph == NULL )
{
- // 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;
- }
+ 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;
+}
- // 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.]
+ Synopsis [Computes the cost based on the BDD size after reordering.]
Description []
@@ -500,44 +193,27 @@ void Abc_NtkRenodeSetBoundsCnf( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
+int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut )
{
- 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;
+ 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 [Sets a simple boundary.]
+ Synopsis [Computes the cost based on ISOP.]
Description []
@@ -546,21 +222,21 @@ void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
SeeAlso []
***********************************************************************/
-void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk )
+int Abc_NtkRenodeEvalSop( If_Cut_t * pCut )
{
- 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;
+ 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 [Collects the fanins of a large node.]
+ Synopsis [Computes the cost based on two ISOPs.]
Description []
@@ -569,21 +245,32 @@ void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NtkRenodeCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
{
- assert( !Abc_ObjIsComplement(pNode) );
- if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) )
- {
- Vec_PtrPushUnique( vCone, pNode );
- return;
- }
- Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,0), vCone );
- Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,1), vCone );
+ 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 [Collects the fanins of a large node.]
+ Synopsis [Computes the cost of MV-SOP of the cut function.]
Description []
@@ -592,13 +279,29 @@ void Abc_NtkRenodeCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
SeeAlso []
***********************************************************************/
-void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
+int Abc_NtkRenodeEvalMv( If_Cut_t * pCut )
{
- assert( !Abc_ObjIsComplement(pNode) );
- assert( Abc_ObjIsNode(pNode) );
- vCone->nSize = 0;
- Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,0), vCone );
- Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,1), vCone );
+ 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;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcReorder.c b/src/base/abci/abcReorder.c
new file mode 100644
index 00000000..182780cd
--- /dev/null
+++ b/src/base/abci/abcReorder.c
@@ -0,0 +1,102 @@
+/**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;
+ Abc_NtkRemoveDupFanins( pNtk );
+ Abc_NtkMinimumBase( pNtk );
+ p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( Abc_ObjFaninNum(pNode) < 3 )
+ continue;
+ if ( fVerbose )
+ fprintf( stdout, "%10s: ", Abc_ObjName(pNode) );
+ if ( fVerbose )
+ fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize(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..aa9a2998
--- /dev/null
+++ b/src/base/abci/abcRestruct.c
@@ -0,0 +1,1497 @@
+/**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 )
+{
+ extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
+ ProgressBar * pProgress;
+ Abc_ManRst_t * pManRst;
+ Cut_Man_t * pManCut;
+ Cut_Cut_t * pCutList;
+ Dec_Graph_t * pGraph;
+ Abc_Obj_t * pNode;
+ 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..a2b23c0c
--- /dev/null
+++ b/src/base/abci/abcResub.c
@@ -0,0 +1,1952 @@
+/**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 )
+{
+ extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
+ 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
index ea221296..3b50107b 100644
--- a/src/base/abci/abcRewrite.c
+++ b/src/base/abci/abcRewrite.c
@@ -32,11 +32,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -50,31 +55,54 @@ static void Abc_NodePrintCuts( Abc_Obj_t * pNode );
SeeAlso []
***********************************************************************/
-int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUseZeros, int fVerbose )
+int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable )
{
- int fDrop = 0;
+ extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
ProgressBar * pProgress;
Cut_Man_t * pManCut;
Rwr_Man_t * pManRwr;
Abc_Obj_t * pNode;
- int i, nNodes, nGain;
+ 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;
- Abc_NtkStartReverseLevels( pNtk );
+ // 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, fDrop );
+ 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 )
@@ -83,34 +111,71 @@ Rwr_ManAddTimeCuts( pManRwr, clock() - clk );
// stop if all nodes have been tried once
if ( i >= nNodes )
break;
- // skip the constant node
- if ( Abc_NodeIsConst(pNode) )
+ // 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, fUseZeros );
- if ( nGain > 0 || nGain == 0 && fUseZeros )
- {
- Dec_Graph_t * pGraph = Rwr_ManReadDecs(pManRwr);
- int fCompl = Rwr_ManReadCompl(pManRwr);
- // complement the FF if needed
- if ( fCompl ) Dec_GraphComplement( pGraph );
- Dec_GraphUpdateNetwork( pNode, pGraph, nGain );
- if ( fCompl ) Dec_GraphComplement( pGraph );
- }
+ 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;
- Abc_NtkStopReverseLevels( pNtk );
+
+ // 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 ) )
{
@@ -132,7 +197,7 @@ Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart );
SeeAlso []
***********************************************************************/
-Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop )
+Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk )
{
static Cut_Params_t Params, * pParams = &Params;
Cut_Man_t * pManCut;
@@ -143,10 +208,9 @@ Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop )
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->fHash = 1; // hash cuts to detect unique
- pParams->fFilter = 0; // filter dominated cuts
+ pParams->fFilter = 1; // filter dominated cuts
pParams->fSeq = 0; // compute sequential cuts
- pParams->fDrop = fDrop; // drop cuts on the fly
+ pParams->fDrop = 0; // drop cuts on the fly
pParams->fVerbose = 0; // the verbosiness flag
pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
pManCut = Cut_ManStart( pParams );
@@ -172,19 +236,178 @@ Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk, int fDrop )
***********************************************************************/
void Abc_NodePrintCuts( Abc_Obj_t * pNode )
{
+ Vec_Ptr_t * vCuts;
Cut_Cut_t * pCut;
- unsigned uTruth;
+ int k;
+
printf( "\nNode %s\n", Abc_ObjName(pNode) );
- for ( pCut = (Cut_Cut_t *)pNode->pCopy; pCut; pCut = pCut->pNext )
+ vCuts = (Vec_Ptr_t *)pNode->pCopy;
+ Vec_PtrForEachEntry( vCuts, pCut, k )
{
- uTruth = pCut->uTruth;
- Extra_PrintBinary( stdout, &uTruth, 16 );
+ Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 );
printf( " " );
- Cut_CutPrint( pCut );
+ 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
index 4fb059e5..58614584 100644
--- a/src/base/abci/abcSat.c
+++ b/src/base/abci/abcSat.c
@@ -6,7 +6,7 @@
PackageName [Network and node package.]
- Synopsis [Procedures to solve the miter using the internal SAT solver.]
+ Synopsis [Procedures to solve the miter using the internal SAT sat_solver.]
Author [Alan Mishchenko]
@@ -19,79 +19,123 @@
***********************************************************************/
#include "abc.h"
+#include "satSolver.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars );
-static void Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars );
+static sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes );
+extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );
+static nMuxes;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Attempts to solve the miter using an internal SAT solver.]
+ Synopsis [Attempts to solve the miter using an internal SAT sat_solver.]
- Description [Returns 1 if the miter is SAT.]
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
SideEffects []
SeeAlso []
***********************************************************************/
-bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose )
+int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects )
{
- solver * pSat;
+ sat_solver * pSat;
lbool status;
- int clk;
+ int RetValue, clk;
+
+ if ( pNumConfs )
+ *pNumConfs = 0;
+ if ( pNumInspects )
+ *pNumInspects = 0;
- assert( Abc_NtkIsBddLogic(pNtk) );
assert( Abc_NtkLatchNum(pNtk) == 0 );
- if ( Abc_NtkPoNum(pNtk) > 1 )
- fprintf( stdout, "Warning: The miter has more than 1 output. SAT will try to prove all of them.\n" );
+// if ( Abc_NtkPoNum(pNtk) > 1 )
+// fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) );
- // load clauses into the solver
+ // load clauses into the sat_solver
clk = clock();
- pSat = Abc_NtkMiterSatCreate( pNtk );
-// printf( "Created SAT problem with %d variable and %d clauses. ",
-// solver_nvars(pSat), solver_nclauses(pSat) );
+ 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 = solver_simplify(pSat);
-// printf( "Simplified the problem to %d variables and %d clauses. ",
-// solver_nvars(pSat), solver_nclauses(pSat) );
+ 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 == l_False )
+ if ( status == 0 )
{
- solver_delete( pSat );
- printf( "The problem is UNSAT after simplification.\n" );
- return 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 = solver_solve( pSat, NULL, NULL );
-// if ( fVerbose )
-// {
- printf( "The problem is %5s. ", (status == l_True)? "SAT" : "UNSAT" );
- PRT( "SAT solver time", clock() - clk );
-// }
- // free the solver
- solver_delete( pSat );
- return status == l_True;
+ 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 [Sets up the SAT solver.]
+ Synopsis [Returns the array of CI IDs.]
Description []
@@ -100,43 +144,505 @@ bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose )
SeeAlso []
***********************************************************************/
-solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk )
+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 )
{
- solver * pSat;
- Extra_MmFlex_t * pMmFlex;
Abc_Obj_t * pNode;
- Vec_Str_t * vCube;
- Vec_Int_t * vVars;
- char * pSop0, * pSop1;
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*************************************************************
- assert( Abc_NtkIsBddLogic(pNtk) );
+ Synopsis [Adds trivial clause.]
- // start the data structures
- pSat = solver_new();
- pMmFlex = Extra_MmFlexStart();
- vCube = Vec_StrAlloc( 100 );
- vVars = Vec_IntAlloc( 100 );
+ Description []
+
+ SideEffects []
- // add clauses for each internal nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
+ 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++ )
{
- // derive SOPs for both phases of the node
- Abc_NodeBddToCnf( pNode, pMmFlex, vCube, &pSop0, &pSop1 );
- // add the clauses to the solver
- Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars );
+ // 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 clauses for each PO
- Abc_NtkForEachPo( pNtk, pNode, i )
- Abc_NodeAddClausesTop( pSat, pNode, vVars );
+ // 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_StrFree( vCube );
Vec_IntFree( vVars );
- Extra_MmFlexStop( pMmFlex, 0 );
+ 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.]
@@ -148,14 +654,33 @@ solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+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++ )
@@ -171,10 +696,15 @@ void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t *
if ( pCube[i] == '0' )
Vec_IntPush( vVars, toLit(pFanin->Id) );
else if ( pCube[i] == '1' )
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, 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;
}
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
}
// add clauses for the positive phase
@@ -191,11 +721,17 @@ void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t *
if ( pCube[i] == '0' )
Vec_IntPush( vVars, toLit(pFanin->Id) );
else if ( pCube[i] == '1' )
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
}
Vec_IntPush( vVars, toLit(pNode->Id) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ 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*************************************************************
@@ -209,9 +745,10 @@ void Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t *
SeeAlso []
***********************************************************************/
-void Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
+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) )
@@ -219,31 +756,126 @@ void Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars
vVars->nSize = 0;
Vec_IntPush( vVars, toLit(pFanin->Id) );
Vec_IntPush( vVars, toLit(pNode->Id) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ 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, neg(toLit(pFanin->Id)) );
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ 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, neg(toLit(pFanin->Id)) );
+ Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) );
Vec_IntPush( vVars, toLit(pNode->Id) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ 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, neg(toLit(pNode->Id)) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ 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) );
- solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
+ 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
index de87a1e9..c77f8dea 100644
--- a/src/base/abci/abcStrash.c
+++ b/src/base/abci/abcStrash.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [aigStrash.c]
+ FileName [abcStrash.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: aigStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
@@ -26,52 +26,170 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-// static functions
-static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fAllNodes );
-static Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
-static Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
-
-extern char * Mio_GateReadSop( void * pGate );
+static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Creates the strashed AIG network.]
+ Synopsis [Reapplies structural hashing to the AIG.]
- Description [Converts the logic network or the AIG into a
- structurally hashed 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_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup )
+Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup )
{
+ extern int timeRetime;
Abc_Ntk_t * pNtkAig;
- int nNodes;
+ 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.]
- assert( !Abc_NtkIsNetlist(pNtk) );
- if ( Abc_NtkIsBddLogic(pNtk) )
- Abc_NtkBddToSop(pNtk);
+ 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 initial AIG are removed by strashing.\n" );
+ 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
- pNtkAig = Abc_NtkStartFrom( pNtk, ABC_TYPE_STRASH, ABC_FUNC_AIG );
- Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes );
+// 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( "The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
- if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) )
- printf( "Cleanup has removed %d nodes.\n", nNodes );
+// 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_NtkStrash( pNtk->pExdc, 0, 1 );
+ pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
// make sure everything is okay
if ( !Abc_NtkCheck( pNtkAig ) )
{
@@ -87,34 +205,85 @@ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup )
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 add
- the COs of the second. Does not change the second network. Returns 0
- if the appending failed, 1 otherise.]
+ 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 Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos )
{
Abc_Obj_t * pObj;
- int i;
+ 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_NtkIsBddLogic(pNtk2) )
- Abc_NtkBddToSop(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 ) )
- return 0;
+ 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 )
- pObj->pCopy = Abc_NtkCi(pNtk1, 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
- Abc_NtkStrashPerform( pNtk2, pNtk1, 1 );
+ 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 ) )
{
@@ -124,7 +293,6 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
return 1;
}
-
/**Function*************************************************************
Synopsis [Prepares the network for strashing.]
@@ -136,38 +304,31 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
SeeAlso []
***********************************************************************/
-void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, bool fAllNodes )
+void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord )
{
ProgressBar * pProgress;
- Abc_Aig_t * pMan = pNtkNew->pManFunc;
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pNode, * pNodeNew, * pObj;
- int i;
-
- // perform strashing
- vNodes = Abc_NtkDfs( pNtk, fAllNodes );
+ 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, pNode, i )
+ Vec_PtrForEachEntry( vNodes, pNodeOld, i )
{
Extra_ProgressBarUpdate( pProgress, i, NULL );
- // get the node
- assert( Abc_ObjIsNode(pNode) );
- // strash the node
- pNodeNew = Abc_NodeStrash( pMan, pNode );
- // get the old object
- pObj = Abc_ObjFanout0Ntk( pNode );
- // make sure the node is not yet strashed
- assert( pObj->pCopy == NULL );
- // mark the old object with the new AIG node
- pObj->pCopy = pNodeNew;
+ pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord );
}
- Vec_PtrFree( vNodes );
Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
}
/**Function*************************************************************
- Synopsis [Strashes one logic node.]
+ Synopsis [Transfers the AIG from one manager into another.]
Description []
@@ -176,40 +337,76 @@ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, bool fAllNodes
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
+void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj )
{
- int fUseFactor = 1;
- char * pSop;
+ 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*************************************************************
- assert( Abc_ObjIsNode(pNode) );
+ Synopsis [Strashes one logic node.]
- // consider the case when the graph is an AIG
- if ( Abc_NtkIsStrash(pNode->pNtk) )
+ 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() )
{
- if ( Abc_NodeIsConst(pNode) )
- return Abc_AigConst1(pMan);
- return Abc_AigAnd( pMan, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
+ 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) );
+}
+
+
+
- // 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 Abc_ObjNotCond( Abc_AigConst1(pMan), Abc_SopIsConst0(pSop) );
- // decide when to use factoring
- if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 )
- return Abc_NodeStrashFactor( pMan, pNode, pSop );
- return Abc_NodeStrashSop( pMan, pNode, pSop );
-}
/**Function*************************************************************
- Synopsis [Strashes one logic node using its SOP.]
+ Synopsis [Copies the topmost levels of the network.]
Description []
@@ -218,41 +415,21 @@ Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop )
+Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut )
{
- Abc_Obj_t * pFanin, * pAnd, * pSum;
- Abc_Obj_t * pConst1 = Abc_AigConst1(pMan);
- 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 = Abc_ObjNot(pConst1);
- Abc_SopForEachCube( pSop, nFanins, pCube )
- {
- // create the AND of literals
- pAnd = pConst1;
- Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net
- {
- if ( pCube[i] == '1' )
- pAnd = Abc_AigAnd( pMan, pAnd, pFanin->pCopy );
- else if ( pCube[i] == '0' )
- pAnd = Abc_AigAnd( pMan, pAnd, Abc_ObjNot(pFanin->pCopy) );
- }
- // add to the sum of cubes
- pSum = Abc_AigOr( pMan, pSum, pAnd );
- }
- // decide whether to complement the result
- if ( Abc_SopIsComplement(pSop) )
- pSum = Abc_ObjNot(pSum);
- return pSum;
+ 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 [Strashes one logic node using its SOP.]
+ Synopsis [Copies the topmost levels of the network.]
Description []
@@ -261,23 +438,39 @@ Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, char * pSop )
+Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels )
{
- Dec_Graph_t * pFForm;
- Dec_Node_t * pNode;
- Abc_Obj_t * pAnd;
- int i;
- // 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_GraphToNetwork( pMan, pFForm );
- Dec_GraphFree( pFForm );
- return pAnd;
+ 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
index 7000ecad..1ae8745b 100644
--- a/src/base/abci/abcSweep.c
+++ b/src/base/abci/abcSweep.c
@@ -25,20 +25,20 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
-
-static stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv, bool fVerbose );
+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 fVerbose, int fUseInv );
-static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fVerbose, int fUseInv );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -54,22 +54,57 @@ static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pF
SeeAlso []
***********************************************************************/
-bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose )
+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 );
+ 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 );
+ 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( pMan, pNtk, fUseInv, fVerbose );
+ tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose );
// transform the network into the equivalent one
Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose );
@@ -80,7 +115,11 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose )
Abc_NtkDelete( pNtkAig );
// cleanup the dangling nodes
- Abc_NtkCleanup( pNtk, fVerbose );
+ if ( Abc_NtkHasMapping(pNtk) )
+ Abc_NtkCleanup( pNtk, fVerbose );
+ else
+ Abc_NtkSweep( pNtk, fVerbose );
+
// check
if ( !Abc_NtkCheck( pNtk ) )
{
@@ -92,6 +131,47 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose )
/**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 []
@@ -101,7 +181,7 @@ bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose )
SeeAlso []
***********************************************************************/
-stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv, bool fVerbose )
+stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose )
{
Abc_Obj_t * pList, * pNode, * pNodeAig;
Fraig_Node_t * gNode;
@@ -115,16 +195,16 @@ stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv,
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 constant input nodes
- if ( Abc_ObjFaninNum(pNode) == 0 )
- continue;
- // skip the nodes that fanout into POs
- if ( Abc_NodeHasUniqueCoFanout(pNode) )
+ // 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) );
@@ -151,22 +231,22 @@ stmm_table * Abc_NtkFraigEquiv( Fraig_Man_t * p, Abc_Ntk_t * pNtk, int fUseInv,
// count nodes in the non-trival classes
for ( pNode = pList; pNode; pNode = pNode->pNext )
Counter++;
-/*
- if ( fVerbose )
+
+ if ( fVeryVerbose )
{
printf( "Class %2d : {", c );
for ( pNode = pList; pNode; pNode = pNode->pNext )
{
pNode->pCopy = NULL;
printf( " %s", Abc_ObjName(pNode) );
- if ( pNode->fPhase ) printf( "(*)" );
+ printf( "(%c)", pNode->fPhase? '-' : '+' );
+ printf( "(%d)", pNode->Level );
}
printf( " }\n" );
c++;
}
-*/
}
- if ( fVerbose )
+ 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) );
@@ -194,8 +274,6 @@ void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv,
Abc_Obj_t * pList;
if ( stmm_count(tEquiv) == 0 )
return;
- // assign levels to the nodes of the network
- Abc_NtkGetLevelNum( pNtk );
// merge nodes in the classes
if ( Abc_NtkHasMapping( pNtk ) )
{
@@ -257,8 +335,8 @@ void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUs
{
Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst;
Arrival2 = Abc_NodeReadArrival(pNode )->Worst;
- assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
- assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 );
+// 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 &&
@@ -277,8 +355,8 @@ void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUs
{
Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst;
Arrival2 = Abc_NodeReadArrival(pNode )->Worst;
- assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 );
- assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 );
+// 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 &&
@@ -352,7 +430,7 @@ void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv,
return;
// add the invertor
- pNodeMinInv = Abc_NodeCreateInv( pNtk, pNodeMin );
+ pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin );
// move the fanouts of the inverted nodes
for ( pNode = pListInv; pNode; pNode = pNode->pNext )
@@ -394,19 +472,36 @@ int Abc_NodeDroppingCost( Abc_Obj_t * pNode )
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
- vNodes = Abc_NtkDfs( pNtk, 0 );
- for ( i = 0; i < vNodes->nSize; i++ )
- {
- pNode = vNodes->pArray[i];
+ Vec_PtrForEachEntry( vNodes, pNode, i )
pNode->fMarkA = 1;
- }
- Vec_PtrFree( vNodes );
- // if it is an AIG, also mark the constant 1 node
- if ( Abc_NtkIsStrash(pNtk) )
- Abc_AigConst1(pNtk->pManFunc)->fMarkA = 1;
// remove the non-marked nodes
Counter = 0;
Abc_NtkForEachNode( pNtk, pNode, i )
@@ -416,16 +511,11 @@ int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose )
Counter++;
}
// unmark the remaining nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
+ Vec_PtrForEachEntry( vNodes, pNode, i )
pNode->fMarkA = 0;
- if ( fVerbose )
- printf( "Cleanup removed %d dangling nodes.\n", Counter );
// check
if ( !Abc_NtkCheck( pNtk ) )
- {
printf( "Abc_NtkCleanup: The network check has failed.\n" );
- return -1;
- }
return Counter;
}
@@ -445,85 +535,40 @@ int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose )
***********************************************************************/
int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose )
{
- Abc_Obj_t * pNode;
- int i, fConvert, nSwept, nSweptNew;
- assert( Abc_NtkIsSopLogic(pNtk) || Abc_NtkIsBddLogic(pNtk) );
- // convert to the BDD representation
- fConvert = 0;
- if ( Abc_NtkIsSopLogic(pNtk) )
- Abc_NtkSopToBdd(pNtk), fConvert = 1;
- // perform cleanup to get rid of dangling nodes
- nSwept = Abc_NtkCleanup( pNtk, 0 );
- // make the network minimum base
- Abc_NtkRemoveDupFanins(pNtk);
- Abc_NtkMinimumBase(pNtk);
- do
- {
- // sweep constants and single-input nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
- if ( Abc_ObjFaninNum(pNode) < 2 )
- Abc_NodeSweep( pNode, fVerbose );
- // make the network minimum base
- Abc_NtkRemoveDupFanins(pNtk);
- Abc_NtkMinimumBase(pNtk);
- // perform final clean up (in case new danglies are created)
- nSweptNew = Abc_NtkCleanup( pNtk, 0 );
- nSwept += nSweptNew;
- }
- while ( nSweptNew );
- // conver back to BDD
- if ( fConvert )
- Abc_NtkBddToSop(pNtk);
- // report
- if ( fVerbose )
- printf( "Sweep removed %d nodes.\n", nSwept );
- // check
- if ( !Abc_NtkCheck( pNtk ) )
+ 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) )
{
- printf( "Abc_NtkSweep: The network check has failed.\n" );
- return -1;
+ fprintf( stdout, "Converting to BDD has failed.\n" );
+ return 1;
}
- return nSwept;
-}
-
-/**Function*************************************************************
-
- Synopsis [Tranditional sweep of the network.]
-
- Description [Propagates constant and single-input node, removes dangling nodes.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose )
-{
- Vec_Ptr_t * vFanout = pNode->pNtk->vPtrTemp;
- Abc_Obj_t * pFanout, * pDriver;
- int i;
- assert( Abc_ObjFaninNum(pNode) < 2 );
- assert( Abc_ObjFanoutNum(pNode) > 0 );
- // iterate through the fanouts
- Abc_NodeCollectFanouts( pNode, vFanout );
- Vec_PtrForEachEntry( vFanout, pFanout, i )
+ // 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 )
{
- if ( Abc_ObjIsCo(pFanout) )
- {
- if ( Abc_ObjFaninNum(pNode) == 1 )
- {
- pDriver = Abc_ObjFanin0(pNode);
- if ( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 1 || Abc_ObjFanoutNum(pNode) > 1 )
- continue;
- // the driver is a node and its only fanout is this node
- if ( Abc_NodeIsInv(pNode) )
- pDriver->pData = Cudd_Not(pDriver->pData);
- // replace the fanin of the fanout
- Abc_ObjPatchFanin( pFanout, pNode, pDriver );
- }
+ // get any sweepable node
+ pNode = Vec_PtrPop(vNodes);
+ if ( !Abc_ObjIsNode(pNode) )
continue;
- }
- // the fanout is a regular node
+ // 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
@@ -534,9 +579,44 @@ void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose )
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.]
@@ -554,7 +634,7 @@ void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0
DdNode * bVar, * bTemp;
int iFanin;
assert( Abc_NtkIsBddLogic(pNode->pNtk) );
- if ( (iFanin = Vec_FanFindEntry( &pNode->vFanins, pFanin->Id )) == -1 )
+ 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) );
@@ -582,7 +662,7 @@ void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
DdNode * bVar, * bCof0, * bCof1;
int iFanin;
assert( Abc_NtkIsBddLogic(pNode->pNtk) );
- if ( (iFanin = Vec_FanFindEntry( &pNode->vFanins, pFanin->Id )) == -1 )
+ 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) );
@@ -597,6 +677,270 @@ void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
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
index f1e427c0..0f76065c 100644
--- a/src/base/abci/abcSymm.c
+++ b/src/base/abci/abcSymm.c
@@ -24,13 +24,13 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fVerbose );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -44,10 +44,10 @@ static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms )
SeeAlso []
***********************************************************************/
-void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fVerbose )
+void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose )
{
- if ( fUseBdds )
- Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fVerbose );
+ if ( fUseBdds || fNaive )
+ Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose );
else
Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose );
}
@@ -81,15 +81,19 @@ void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose )
SeeAlso []
***********************************************************************/
-void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fVerbose )
+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_NtkGlobalBdds( pNtk, 0 );
+ 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
@@ -97,10 +101,10 @@ clk = clock();
Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose );
clkSym = clock() - clk;
// undo the global functions
- Abc_NtkFreeGlobalBdds( pNtk );
- Extra_StopManager( dd );
- pNtk->pManGlob = NULL;
-
+ Abc_NtkFreeGlobalBdds( pNtk, 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 );
@@ -129,7 +133,8 @@ void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVer
// compute symmetry info for each PO
Abc_NtkForEachCo( pNtk, pNode, i )
{
- bFunc = pNtk->vFuncsGlob->pArray[i];
+// bFunc = pNtk->vFuncsGlob->pArray[i];
+ bFunc = Abc_ObjGlobalBdd( pNode );
nSupps += Cudd_SupportSize( dd, bFunc );
if ( Cudd_IsConstant(bFunc) )
continue;
diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c
index b8524bd5..967e4617 100644
--- a/src/base/abci/abcTiming.c
+++ b/src/base/abci/abcTiming.c
@@ -37,16 +37,16 @@ struct Abc_ManTime_t_
// static functions
static Abc_ManTime_t * Abc_ManTimeStart();
static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive );
-static void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk );
+void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk );
-static void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode );
+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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -254,9 +254,9 @@ void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk )
continue;
*pTime = pNtk->pManTime->tReqDef;
}
- // set the 0 arrival times for latches and constant nodes
+ // set the 0 arrival times for latch outputs and constant nodes
ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray;
- Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NtkForEachLatchOutput( pNtk, pObj, i )
{
pTime = ppTimes[pObj->Id];
pTime->Fall = pTime->Rise = pTime->Worst = 0.0;
@@ -470,9 +470,9 @@ void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld )
int i;
if ( pNtkOld->pManTime == NULL )
return;
- if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame())) == NULL )
+ if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen()) == NULL )
return;
- tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()));
+ tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen());
Abc_NtkForEachPi( pNtkOld, pNodeOld, i )
{
pNodeNew = pNodeOld->pCopy;
@@ -595,13 +595,12 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode )
// start the arrival time of the node
pTimeOut = Abc_NodeArrival(pNode);
- pTimeOut->Rise = pTimeOut->Fall = 0;
+ 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);
- assert( pTimeIn->Worst != -ABC_INFINITY );
// get the interesting parameters of this pin
PinPhase = Mio_PinReadPhase(pPin);
tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
@@ -631,38 +630,133 @@ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode )
/**Function*************************************************************
- Synopsis [Prepares the AIG for the comptuation of required levels.]
+ 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 AIG nodes in reverse topologogical order.]
+ from the COs of the network nodes in reverse topologogical order.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk )
+void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease )
{
Vec_Ptr_t * vNodes;
- Abc_Obj_t * pObj, * pFanout;
- int i, k, nLevelsCur;
- assert( Abc_NtkIsStrash(pNtk) );
+ Abc_Obj_t * pObj;
+ int i;
// remember the maximum number of direct levels
- pNtk->LevelMax = Abc_AigGetLevelNum(pNtk);
+ pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease;
// start the reverse levels
pNtk->vLevelsR = Vec_IntAlloc( 0 );
- Vec_IntFill( pNtk->vLevelsR, Abc_NtkObjNumMax(pNtk), 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 )
- {
- nLevelsCur = 0;
- Abc_ObjForEachFanout( pObj, pFanout, k )
- if ( nLevelsCur < Vec_IntEntry(pNtk->vLevelsR, pFanout->Id) )
- nLevelsCur = Vec_IntEntry(pNtk->vLevelsR, pFanout->Id);
- Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, nLevelsCur + 1 );
- }
+ Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) );
Vec_PtrFree( vNodes );
}
@@ -688,64 +782,120 @@ void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk )
/**Function*************************************************************
- Synopsis [Sets the reverse level of the node.]
+ Synopsis [Incrementally updates level of the nodes.]
- Description [The reverse level is the level of the node in reverse
- topological order, starting from the COs.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_NodeSetReverseLevel( Abc_Obj_t * pObj, int LevelR )
+void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
{
- Abc_Ntk_t * pNtk = pObj->pNtk;
- assert( Abc_NtkIsStrash(pNtk) );
- assert( pNtk->vLevelsR );
- Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
- Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR );
+ 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 [Returns the reverse level of the node.]
+ Synopsis [Incrementally updates level of the nodes.]
- Description [The reverse level is the level of the node in reverse
- topological order, starting from the COs.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NodeReadReverseLevel( Abc_Obj_t * pObj )
+void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
{
- Abc_Ntk_t * pNtk = pObj->pNtk;
- assert( Abc_NtkIsStrash(pNtk) );
- assert( pNtk->vLevelsR );
- Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 );
- return Vec_IntEntry(pNtk->vLevelsR, pObj->Id);
+ 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 [Returns required level of the node.]
+ Synopsis [Replaces the node and incrementally updates levels.]
- Description [Converts the reverse levels of the node into its required
- level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NodeReadRequiredLevel( Abc_Obj_t * pObj )
+void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
{
- Abc_Ntk_t * pNtk = pObj->pNtk;
- assert( Abc_NtkIsStrash(pNtk) );
- assert( pNtk->vLevelsR );
- return pNtk->LevelMax + 1 - Vec_IntEntry(pNtk->vLevelsR, pObj->Id);
+ // 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 );
}
////////////////////////////////////////////////////////////////////////
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
index abc02cc3..ea0a4cd2 100644
--- a/src/base/abci/abcUnreach.c
+++ b/src/base/abci/abcUnreach.c
@@ -30,7 +30,7 @@ static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk,
static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -58,11 +58,11 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose )
}
// compute the global BDDs of the latches
- dd = Abc_NtkGlobalBdds( pNtk, 1 );
+ dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
if ( dd == NULL )
return 0;
if ( fVerbose )
- printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ 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 );
@@ -87,13 +87,15 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose )
// 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;
+// pNtk->pManGlob = NULL;
// make sure that everything is okay
- if ( !Abc_NtkCheck( pNtk->pExdc ) )
+ if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) )
{
printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" );
Abc_NtkDelete( pNtk->pExdc );
@@ -135,13 +137,15 @@ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbo
Abc_NtkForEachLatch( pNtk, pNode, i )
{
bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i );
- bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd );
+// bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd );
+ bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd );
bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel );
Cudd_RecursiveDeref( dd, bTemp );
Cudd_RecursiveDeref( dd, bProd );
}
// free the global BDDs
- Abc_NtkFreeGlobalBdds( pNtk );
+// Abc_NtkFreeGlobalBdds( pNtk );
+ Abc_NtkFreeGlobalBdds( pNtk, 0 );
// quantify the PI variables
bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs );
@@ -217,7 +221,7 @@ DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * b
{
DdNode * bRelation, * bReached, * bCubeCs;
DdNode * bCurrent, * bNext, * bTemp;
- int nIters;
+ int nIters, nMints;
// perform reachability analisys
bCurrent = bInitial; Cudd_Ref( bCurrent );
@@ -254,9 +258,9 @@ DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * b
// report the stats
if ( fVerbose )
{
- fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters );
- fprintf( stdout, "The number of minterms in the reachable state set = %d.\n",
- (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) ) );
+ 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 );
@@ -282,15 +286,19 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn
int i;
// start the new network
- pNtkNew = Abc_NtkAlloc( ABC_TYPE_LOGIC, ABC_FUNC_BDD );
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
+ pNtkNew->pName = Extra_UtilStrsav( "exdc" );
+ pNtkNew->pSpec = NULL;
+
// create PIs corresponding to LOs
- Abc_NtkForEachLatch( pNtk, pNode, i )
- pNode->pCopy = Abc_NtkCreatePi(pNtkNew);
+ 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_NtkForEachLatch( pNtk, pNode, i )
+ Abc_NtkForEachLatchOutput( pNtk, pNode, i )
Abc_ObjAddFanin( pNodeNew, pNode->pCopy );
// create the logic function
@@ -304,28 +312,34 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn
free( pPermute );
Abc_NodeMinimumBase( pNodeNew );
- // make the new node drive all the COs
- Abc_NtkForEachCo( pNtk, pNode, i )
- Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), 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 );
- // store the PI names of the EXDC network
- Abc_NtkForEachLatch( pNtk, pNode, i )
- Abc_NtkLogicStoreName( Abc_NtkPi(pNtkNew,i), Abc_ObjName(pNode) );
- // store the PO names of the EXDC network
+ // link to the POs of the network
Abc_NtkForEachPo( pNtk, pNode, i )
- Abc_NtkLogicStoreName( Abc_NtkPo(pNtkNew,i), Abc_ObjName(pNode) );
- Abc_NtkForEachLatch( pNtk, pNode, i )
- Abc_NtkLogicStoreName( Abc_NtkCo(pNtkNew,Abc_NtkPoNum(pNtk) + i), Abc_ObjNameSuffix(pNode, "_in") );
+ if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
+ Abc_NtkForEachLatchInput( pNtk, pNode, i )
+ Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
- // make the network minimum base
- Abc_NtkMinimumBase( pNtkNew );
+ // 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
- Abc_NtkBddToSop( pNtkNew );
+ if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
+ {
+ printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" );
+ return NULL;
+ }
return pNtkNew;
+// return NULL;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c
index 55d6cf7d..9c9bbcfd 100644
--- a/src/base/abci/abcVerify.c
+++ b/src/base/abci/abcVerify.c
@@ -20,13 +20,17 @@
#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 DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -40,27 +44,32 @@
SeeAlso []
***********************************************************************/
-void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
+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 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
return;
}
RetValue = Abc_NtkMiterIsConstant( pMiter );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
- Abc_NtkDelete( pMiter );
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 == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pMiter );
printf( "Networks are equivalent after structural hashing.\n" );
@@ -68,7 +77,7 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
}
// convert the miter into a CNF
- pCnf = Abc_NtkRenode( pMiter, 0, 100, 1, 0, 0 );
+ pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 );
Abc_NtkDelete( pMiter );
if ( pCnf == NULL )
{
@@ -77,10 +86,16 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
}
// solve the CNF using the SAT solver
- if ( Abc_NtkMiterSat( pCnf, 0 ) )
+ 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 );
}
@@ -96,52 +111,329 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
SeeAlso []
***********************************************************************/
-void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fVerbose )
+void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose )
{
- Fraig_Params_t Params;
+ Prove_Params_t Params, * pParams = &Params;
+// Fraig_Params_t Params;
+// Fraig_Man_t * pMan;
Abc_Ntk_t * pMiter;
- Abc_Ntk_t * pFraig;
int RetValue;
// get the miter of the two networks
- pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1 );
+ 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 );
- printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
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;
}
- // convert the miter into a FRAIG
- Fraig_ParamsSetDefault( &Params );
- Params.fVerbose = fVerbose;
- pFraig = Abc_NtkFraig( pMiter, &Params, 0 );
+ 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 );
- if ( pFraig == NULL )
+}
+
+/**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( "Fraiging has failed.\n" );
+ printf( "Miter computation has failed.\n" );
return;
}
- RetValue = Abc_NtkMiterIsConstant( pFraig );
- Abc_NtkDelete( pFraig );
+ RetValue = Abc_NtkMiterIsConstant( pMiter );
if ( RetValue == 0 )
{
- printf( "Networks are equivalent after fraiging.\n" );
+ 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;
}
- printf( "Networks are NOT EQUIVALENT after fraiging.\n" );
+ 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*************************************************************
@@ -155,28 +447,29 @@ void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fVerbose )
SeeAlso []
***********************************************************************/
-void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
+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 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
return;
}
RetValue = Abc_NtkMiterIsConstant( pMiter );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
Abc_NtkDelete( pMiter );
printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
return;
}
- if ( RetValue == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pMiter );
printf( "Networks are equivalent after structural hashing.\n" );
@@ -192,13 +485,13 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
return;
}
RetValue = Abc_NtkMiterIsConstant( pFrames );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
Abc_NtkDelete( pFrames );
printf( "Networks are NOT EQUIVALENT after framing.\n" );
return;
}
- if ( RetValue == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pFrames );
printf( "Networks are equivalent after framing.\n" );
@@ -206,7 +499,7 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
}
// convert the miter into a CNF
- pCnf = Abc_NtkRenode( pFrames, 0, 100, 1, 0, 0 );
+ pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 );
Abc_NtkDelete( pFrames );
if ( pCnf == NULL )
{
@@ -215,7 +508,10 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
}
// solve the CNF using the SAT solver
- if ( Abc_NtkMiterSat( pCnf, 0 ) )
+ 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" );
@@ -233,33 +529,37 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
SeeAlso []
***********************************************************************/
-void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
+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 * pFraig;
Abc_Ntk_t * pFrames;
int RetValue;
// get the miter of the two networks
- pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0 );
+ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 );
if ( pMiter == NULL )
{
printf( "Miter computation has failed.\n" );
- return;
+ return 0;
}
RetValue = Abc_NtkMiterIsConstant( pMiter );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
- Abc_NtkDelete( pMiter );
printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
- return;
+ // 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 == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pMiter );
printf( "Networks are equivalent after structural hashing.\n" );
- return;
+ return 1;
}
// create the timeframes
@@ -268,39 +568,446 @@ void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames )
if ( pFrames == NULL )
{
printf( "Frames computation has failed.\n" );
- return;
+ return 0;
}
RetValue = Abc_NtkMiterIsConstant( pFrames );
- if ( RetValue == 1 )
+ if ( RetValue == 0 )
{
- Abc_NtkDelete( pFrames );
printf( "Networks are NOT EQUIVALENT after framing.\n" );
- return;
+ // 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 == 0 )
+ if ( RetValue == 1 )
{
Abc_NtkDelete( pFrames );
printf( "Networks are equivalent after framing.\n" );
- return;
+ return 1;
}
// convert the miter into a FRAIG
Fraig_ParamsSetDefault( &Params );
- pFraig = Abc_NtkFraig( pFrames, &Params, 0 );
+ 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 );
- if ( pFraig == NULL )
+ 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) )
{
- printf( "Fraiging has failed.\n" );
- return;
+ pNtk = Abc_NtkStrash(pNtk, 0, 0, 0);
+ fStrashed = 1;
}
- RetValue = Abc_NtkMiterIsConstant( pFraig );
- Abc_NtkDelete( pFraig );
- if ( RetValue == 0 )
+/*
+ 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 )
{
- printf( "Networks are equivalent after fraiging.\n" );
+ 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( "Networks are NOT EQUIVALENT after fraiging.\n" );
+
+ 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 );
}
diff --git a/src/base/abci/abcXsim.c b/src/base/abci/abcXsim.c
new file mode 100644
index 00000000..e5656170
--- /dev/null
+++ b/src/base/abci/abcXsim.c
@@ -0,0 +1,224 @@
+/**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_NtkForEachLatch( pNtk, pObj, i )
+// Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 );
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) );
+ // simulate for the given number of timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimRand2() );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) );
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) );
+ }
+ // set the final values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pData = (void *)Abc_ObjGetXsim(Abc_ObjFanout0(pObj));
+}
+
+///////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abc_.c b/src/base/abci/abc_.c
index bef3836f..75ec88c3 100644
--- a/src/base/abci/abc_.c
+++ b/src/base/abci/abc_.c
@@ -23,9 +23,9 @@
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -40,6 +40,7 @@
***********************************************************************/
+
////////////////////////////////////////////////////////////////////////
/// 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
index d7c0add2..4558119e 100644
--- a/src/base/abci/module.make
+++ b/src/base/abci/module.make
@@ -1,24 +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/abcCollapse.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/abcVerify.c \
+ src/base/abci/abcXsim.c