summaryrefslogtreecommitdiffstats
path: root/src/map
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2005-07-29 08:01:00 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2005-07-29 08:01:00 -0700
commit888e5bed5d7f56a5d86d91a6e8e88f3e5a3454dc (patch)
tree11d48c9e9069f54dc300c3571ae63c744c802c50 /src/map
parent7f94414388cce67bd3cc1a6d6269f0ed31ed0d06 (diff)
downloadabc-888e5bed5d7f56a5d86d91a6e8e88f3e5a3454dc.tar.gz
abc-888e5bed5d7f56a5d86d91a6e8e88f3e5a3454dc.tar.bz2
abc-888e5bed5d7f56a5d86d91a6e8e88f3e5a3454dc.zip
Version abc50729
Diffstat (limited to 'src/map')
-rw-r--r--src/map/fpga/fpga.c239
-rw-r--r--src/map/fpga/fpga.h158
-rw-r--r--src/map/fpga/fpgaCore.c241
-rw-r--r--src/map/fpga/fpgaCreate.c585
-rw-r--r--src/map/fpga/fpgaCut.c1150
-rw-r--r--src/map/fpga/fpgaCutUtils.c571
-rw-r--r--src/map/fpga/fpgaFanout.c139
-rw-r--r--src/map/fpga/fpgaGENERIC.c46
-rw-r--r--src/map/fpga/fpgaInt.h395
-rw-r--r--src/map/fpga/fpgaLib.c183
-rw-r--r--src/map/fpga/fpgaMatch.c729
-rw-r--r--src/map/fpga/fpgaTime.c189
-rw-r--r--src/map/fpga/fpgaTruth.c107
-rw-r--r--src/map/fpga/fpgaUtils.c1289
-rw-r--r--src/map/fpga/fpgaVec.c408
-rw-r--r--src/map/fpga/module.make12
-rw-r--r--src/map/mapper/mapper.c176
-rw-r--r--src/map/mapper/mapper.h181
-rw-r--r--src/map/mapper/mapperCanon.c161
-rw-r--r--src/map/mapper/mapperCore.c167
-rw-r--r--src/map/mapper/mapperCreate.c592
-rw-r--r--src/map/mapper/mapperCut.c1072
-rw-r--r--src/map/mapper/mapperCutUtils.c273
-rw-r--r--src/map/mapper/mapperFanout.c139
-rw-r--r--src/map/mapper/mapperGENERIC.c46
-rw-r--r--src/map/mapper/mapperInt.h475
-rw-r--r--src/map/mapper/mapperLib.c233
-rw-r--r--src/map/mapper/mapperMatch.c578
-rw-r--r--src/map/mapper/mapperRefs.c541
-rw-r--r--src/map/mapper/mapperSuper.c449
-rw-r--r--src/map/mapper/mapperTable.c402
-rw-r--r--src/map/mapper/mapperTime.c508
-rw-r--r--src/map/mapper/mapperTree.c804
-rw-r--r--src/map/mapper/mapperTruth.c449
-rw-r--r--src/map/mapper/mapperUtils.c1254
-rw-r--r--src/map/mapper/mapperVec.c318
-rw-r--r--src/map/mapper/module.make17
-rw-r--r--src/map/mio/mio.c269
-rw-r--r--src/map/mio/mio.h136
-rw-r--r--src/map/mio/mioApi.c145
-rw-r--r--src/map/mio/mioFunc.c268
-rw-r--r--src/map/mio/mioGENERIC.c46
-rw-r--r--src/map/mio/mioInt.h124
-rw-r--r--src/map/mio/mioRead.c572
-rw-r--r--src/map/mio/mioUtils.c531
-rw-r--r--src/map/mio/module.make5
-rw-r--r--src/map/super/module.make4
-rw-r--r--src/map/super/super.c319
-rw-r--r--src/map/super/super.h51
-rw-r--r--src/map/super/superAnd.c696
-rw-r--r--src/map/super/superGENERIC.c46
-rw-r--r--src/map/super/superGate.c1324
-rw-r--r--src/map/super/superInt.h62
-rw-r--r--src/map/super/superWrite.c76
54 files changed, 19950 insertions, 0 deletions
diff --git a/src/map/fpga/fpga.c b/src/map/fpga/fpga.c
new file mode 100644
index 00000000..6b107498
--- /dev/null
+++ b/src/map/fpga/fpga.c
@@ -0,0 +1,239 @@
+/**CFile****************************************************************
+
+ FileName [fpga.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Command file for the FPGA package.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpga.c,v 1.4 2004/10/28 17:36:07 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+#include "main.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv );
+
+// the library file format should be as follows:
+/*
+# The area/delay of k-variable LUTs:
+# k area delay
+1 1 1
+2 2 2
+3 4 3
+4 8 4
+5 16 5
+6 32 6
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Package initialization procedure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_Init( Abc_Frame_t * pAbc )
+{
+ // set the default library
+ //Fpga_LutLib_t s_LutLib = { "lutlib", 6, {0,1,2,4,8,16,32}, {0,1,2,3,4,5,6} };
+ Fpga_LutLib_t s_LutLib = { "lutlib", 5, {0,1,1,1,1,1}, {0,1,1,1,1,1} };
+ Abc_FrameSetLibLut( pAbc, Fpga_LutLibDup(&s_LutLib) );
+
+ Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut", Fpga_CommandReadLibrary, 0 );
+ Cmd_CommandAdd( pAbc, "FPGA mapping", "print_lut", Fpga_CommandPrintLibrary, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Package ending procedure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_End()
+{
+ Fpga_LutLibFree( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Command procedure to read LUT libraries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pFile;
+ FILE * pOut, * pErr;
+ Fpga_LutLib_t * pLib;
+ Abc_Ntk_t * pNet;
+ char * FileName;
+ int fVerbose;
+ int c;
+
+ pNet = Abc_FrameReadNet(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fVerbose = 1;
+ util_getopt_reset();
+ while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+
+ if ( argc != util_optind + 1 )
+ {
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[util_optind];
+ if ( (pFile = fopen( FileName, "r" )) == NULL )
+ {
+ fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+ if ( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) )
+ fprintf( pErr, "Did you mean \"%s\"?", FileName );
+ fprintf( pErr, "\n" );
+ return 1;
+ }
+ fclose( pFile );
+
+ // set the new network
+ pLib = Fpga_LutLibCreate( FileName, fVerbose );
+ if ( pLib == NULL )
+ {
+ fprintf( pErr, "Reading LUT library has failed.\n" );
+ goto usage;
+ }
+ // replace the current library
+ Fpga_LutLibFree( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) );
+ Abc_FrameSetLibLut( Abc_FrameGetGlobalFrame(), pLib );
+ return 0;
+
+usage:
+ fprintf( pErr, "\nusage: read_lut [-vh]\n");
+ fprintf( pErr, "\t read the LUT library from the file\n" );
+ fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\t \n");
+ fprintf( pErr, "\t File format for a LUT library:\n");
+ fprintf( pErr, "\t (the default library is shown)\n");
+ fprintf( pErr, "\t \n");
+ fprintf( pErr, "\t # The area/delay of k-variable LUTs:\n");
+ fprintf( pErr, "\t # k area delay\n");
+ fprintf( pErr, "\t 1 1 1\n");
+ fprintf( pErr, "\t 2 2 2\n");
+ fprintf( pErr, "\t 3 4 3\n");
+ fprintf( pErr, "\t 4 8 4\n");
+ fprintf( pErr, "\t 5 16 5\n");
+ fprintf( pErr, "\t 6 32 6\n");
+ return 1; /* error exit */
+}
+
+/**Function*************************************************************
+
+ Synopsis [Command procedure to read LUT libraries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNet;
+ int fVerbose;
+ int c;
+
+ pNet = Abc_FrameReadNet(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fVerbose = 1;
+ util_getopt_reset();
+ while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+
+ if ( argc != util_optind )
+ {
+ goto usage;
+ }
+
+ // set the new network
+ Fpga_LutLibPrint( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) );
+ return 0;
+
+usage:
+ fprintf( pErr, "\nusage: read_print [-vh]\n");
+ fprintf( pErr, "\t print the current LUT library\n" );
+ fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1; /* error exit */
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/fpga/fpga.h b/src/map/fpga/fpga.h
new file mode 100644
index 00000000..62a93a75
--- /dev/null
+++ b/src/map/fpga/fpga.h
@@ -0,0 +1,158 @@
+/**CFile****************************************************************
+
+ FileName [fpga.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpga.h,v 1.7 2004/09/30 21:18:09 satrajit Exp $]
+
+***********************************************************************/
+
+#ifndef __FPGA_H__
+#define __FPGA_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+// the maximum size of LUTs used for mapping
+#define FPGA_MAX_LUTSIZE 10
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fpga_ManStruct_t_ Fpga_Man_t;
+typedef struct Fpga_NodeStruct_t_ Fpga_Node_t;
+typedef struct Fpga_NodeVecStruct_t_ Fpga_NodeVec_t;
+typedef struct Fpga_CutStruct_t_ Fpga_Cut_t;
+typedef struct Fpga_LutLibStruct_t_ Fpga_LutLib_t;
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Fpga_IsComplement(p) (((int)((long) (p) & 01)))
+#define Fpga_Regular(p) ((Fpga_Node_t *)((unsigned)(p) & ~01))
+#define Fpga_Not(p) ((Fpga_Node_t *)((long)(p) ^ 01))
+#define Fpga_NotCond(p,c) ((Fpga_Node_t *)((long)(p) ^ (c)))
+
+#define Fpga_Ref(p)
+#define Fpga_Deref(p)
+#define Fpga_RecursiveDeref(p,c)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fpgaCreate.c =============================================================*/
+extern Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose );
+extern Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+extern void Fpga_ManFree( Fpga_Man_t * pMan );
+extern void Fpga_ManPrintTimeStats( Fpga_Man_t * p );
+
+extern int Fpga_ManReadInputNum( Fpga_Man_t * p );
+extern int Fpga_ManReadOutputNum( Fpga_Man_t * p );
+extern Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p );
+extern Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p );
+extern Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p );
+extern float * Fpga_ManReadInputArrivals( Fpga_Man_t * p );
+extern int Fpga_ManReadVerbose( Fpga_Man_t * p );
+extern float * Fpga_ManReadLutAreas( Fpga_Man_t * p );
+extern void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time );
+extern void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time );
+extern void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time );
+extern void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames );
+extern void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals );
+extern void Fpga_ManSetTree( Fpga_Man_t * p, int fTree );
+extern void Fpga_ManSetPower( Fpga_Man_t * p, int fPower );
+extern void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery );
+extern void Fpga_ManSetResyn( Fpga_Man_t * p, int fResynthesis );
+extern void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit );
+extern void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit );
+extern void Fpga_ManSetTimeLimit( Fpga_Man_t * p, float TimeLimit );
+extern void Fpga_ManSetObeyFanoutLimits( Fpga_Man_t * p, int fObeyFanoutLimits );
+extern void Fpga_ManSetNumIterations( Fpga_Man_t * p, int nNumIterations );
+extern int Fpga_ManReadFanoutViolations( Fpga_Man_t * p );
+extern void Fpga_ManSetFanoutViolations( Fpga_Man_t * p, int nVio );
+extern void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes );
+extern void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices );
+extern void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose );
+extern void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches );
+extern void Fpga_ManSetSequential( Fpga_Man_t * p, int fSequential );
+extern void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName );
+
+extern int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib );
+
+extern char * Fpga_NodeReadData0( Fpga_Node_t * p );
+extern Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p );
+extern int Fpga_NodeReadNum( Fpga_Node_t * p );
+extern int Fpga_NodeReadLevel( Fpga_Node_t * p );
+extern Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p );
+extern Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p );
+extern Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p );
+extern Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p );
+extern void Fpga_NodeSetLevel( Fpga_Node_t * p, Fpga_Node_t * pNode );
+extern void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData );
+extern void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode );
+extern void Fpga_NodeSetArrival( Fpga_Node_t * p, float Time );
+extern void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE );
+extern void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr );
+
+extern int Fpga_NodeIsConst( Fpga_Node_t * p );
+extern int Fpga_NodeIsVar( Fpga_Node_t * p );
+extern int Fpga_NodeIsAnd( Fpga_Node_t * p );
+extern int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 );
+
+extern int Fpga_CutReadLeavesNum( Fpga_Cut_t * p );
+extern Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p );
+
+extern Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+extern Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+extern Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+extern Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeT, Fpga_Node_t * pNodeE );
+extern void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew );
+
+extern void Fpga_ManStats( Fpga_Man_t * p );
+
+/*=== fpgaCore.c =============================================================*/
+extern int Fpga_Mapping( Fpga_Man_t * p );
+/*=== fpgaCut.c ===============================================================*/
+extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p );
+extern void Fpga_CutsCleanSign( Fpga_Man_t * pMan );
+/*=== fpgaCutUtils.c =============================================================*/
+extern void Fpga_CutCreateFromNode( Fpga_Man_t * p, int iRoot, int * pLeaves, int nLeaves );
+extern void Fpga_MappingSetUsedCuts( Fpga_Man_t * p );
+/*=== fpgaFraig.c =============================================================*/
+extern Fpga_Man_t * Fpga_ManDupFraig( Fraig_Man_t * pManFraig );
+extern Fpga_Man_t * Fpga_ManBalanceFraig( Fraig_Man_t * pManFraig, int * pInputArrivals );
+/*=== fpgaLib.c =============================================================*/
+extern Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p );
+/*=== fpgaTruth.c =============================================================*/
+extern void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut );
+/*=== fpgaUtil.c =============================================================*/
+extern int Fpga_ManCheckConsistency( Fpga_Man_t * p );
+extern void Fpga_ManCleanData0( Fpga_Man_t * pMan );
+extern Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode );
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/src/map/fpga/fpgaCore.c b/src/map/fpga/fpgaCore.c
new file mode 100644
index 00000000..37726542
--- /dev/null
+++ b/src/map/fpga/fpgaCore.c
@@ -0,0 +1,241 @@
+/**CFile****************************************************************
+
+ FileName [fpgaCore.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+//#include "res.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fpga_MappingPostProcess( Fpga_Man_t * p );
+
+extern void Fpga_Experiment( Fpga_Man_t * p );
+extern void Fpga_MappingCutsSeq( Fpga_Man_t * p );
+extern void Fpga_MappingLValues( Fpga_Man_t * pMan, int fVerbose );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs technology mapping for the given object graph.]
+
+ Description [The object graph is stored in the mapping manager.
+ First, all the AND-nodes, which fanout into the POs, are collected
+ in the DFS fashion. Next, three steps are performed: the k-feasible
+ cuts are computed for each node, the truth tables are computed for
+ each cut, and the delay-optimal matches are assigned for each node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_Mapping( Fpga_Man_t * p )
+{
+ int clk;
+
+ // collect the nodes reachable from POs in the DFS order (including the choices)
+ p->vAnds = Fpga_MappingDfs( p, 1 );
+ Fpga_ManReportChoices( p ); // recomputes levels
+ Fpga_MappingSetChoiceLevels( p );
+
+ if ( p->fSequential )
+ {
+// Fpga_MappingCutsSeq( p );
+ Fpga_MappingCuts( p );
+//clk = clock();
+// Fpga_MappingLValues( p, p->fVerbose );
+//PRT( "Time", clock() - clk );
+ return 0;
+ }
+
+ // compute the cuts of nodes in the DFS order
+ clk = clock();
+ Fpga_MappingCuts( p );
+ p->timeCuts = clock() - clk;
+
+// Fpga_MappingSortByLevel( p, p->vAnds, 1 );
+
+ // derive the truth tables
+ clk = clock();
+// Fpga_MappingTruths( p );
+ p->timeTruth = clock() - clk;
+
+ // match the truth tables to the supergates
+ clk = clock();
+ if ( !Fpga_MappingMatches( p, 1 ) )
+ return 0;
+ p->timeMatch = clock() - clk;
+
+ // perform area recovery
+ if ( p->fAreaRecovery )
+ {
+ clk = clock();
+ if ( !Fpga_MappingPostProcess( p ) )
+ return 0;
+ p->timeRecover = clock() - clk;
+ }
+
+ // perform resynthesis
+// if ( p->fResynthesis )
+// Res_Resynthesize( p, p->DelayLimit, p->AreaLimit, p->TimeLimit, 1 );
+
+ // print the AI-graph used for mapping
+ //Fpga_ManShow( p, "test" );
+ if ( p->fVerbose )
+ Fpga_MappingPrintOutputArrivals( p );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Postprocesses the mapped network for area recovery.]
+
+ Description [This procedure assumes that the mapping is assigned.
+ It iterates the loop, in which the required times are computed and
+ the mapping is updated. It is conceptually similar to the paper:
+ V. Manohararajah, S. D. Brown, Z. G. Vranesic, Heuristics for area
+ minimization in LUT-based FGPA technology mapping. Proc. IWLS '04.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingPostProcess( Fpga_Man_t * p )
+{
+ float aAreaTotalPrev, aAreaTotalCur, aAreaTotalCur2;
+ float aSwitchTotalPrev, aSwitchTotalCur;
+ int Iter, clk;
+
+if ( p->fVerbose )
+{
+printf( "Iteration %dD : Area = %11.1f ", 0, Fpga_MappingArea( p ) );
+PRT( "Time", p->timeMatch );
+}
+
+// aAreaTotalCur = FPGA_FLOAT_LARGE;
+ aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
+
+ Iter = 1;
+ do {
+clk = clock();
+ // save the previous area flow
+ aAreaTotalPrev = aAreaTotalCur;
+
+ // compute the required times and the fanouts
+ Fpga_TimeComputeRequiredGlobal( p );
+ // remap topologically
+ Fpga_MappingMatches( p, 0 );
+ // get the resulting area
+ aAreaTotalCur = Fpga_MappingArea( p );
+if ( p->fVerbose )
+{
+printf( "Iteration %dF : Area = %11.1f ", Iter++, aAreaTotalCur );
+PRT( "Time", clock() - clk );
+}
+ if ( p->fPower )
+ aSwitchTotalCur = Fpga_MappingPrintSwitching( p );
+ // quit if this iteration reduced area flow by less than 1%
+ } while ( aAreaTotalPrev > 1.02 * aAreaTotalCur );
+
+
+/*
+ // compute the area of each cut
+ aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
+ // compute the required times and the fanouts
+ Fpga_TimeComputeRequiredGlobal( p );
+ // perform experiment
+ Fpga_Experiment( p );
+*/
+
+
+ // compute the area of each cut
+ aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
+ aAreaTotalCur2 = Fpga_MappingComputeCutAreas( p );
+ assert( aAreaTotalCur == aAreaTotalCur2 );
+
+
+// aAreaTotalCur = FPGA_FLOAT_LARGE;
+// Iter = 1;
+ do {
+clk = clock();
+ // save the previous area flow
+ aAreaTotalPrev = aAreaTotalCur;
+
+ // compute the required times and the fanouts
+ Fpga_TimeComputeRequiredGlobal( p );
+ // remap topologically
+ Fpga_MappingMatchesArea( p );
+ // get the resulting area
+ aAreaTotalCur = Fpga_MappingArea( p );
+if ( p->fVerbose )
+{
+printf( "Iteration %dA : Area = %11.1f ", Iter++, aAreaTotalCur );
+PRT( "Time", clock() - clk );
+}
+ if ( p->fPower )
+ {
+ aSwitchTotalPrev = aSwitchTotalCur;
+ aSwitchTotalCur = Fpga_MappingPrintSwitching( p );
+ }
+ // quit if this iteration reduced area flow by less than 1%
+ } while ( aAreaTotalPrev > 1.02 * aAreaTotalCur );
+
+
+ if ( p->fPower )
+ {
+ do {
+clk = clock();
+ // save the previous area flow
+ aAreaTotalPrev = aAreaTotalCur;
+
+ // compute the required times and the fanouts
+ Fpga_TimeComputeRequiredGlobal( p );
+ // remap topologically
+ Fpga_MappingMatchesSwitch( p );
+ // get the resulting area
+ aAreaTotalCur = Fpga_MappingArea( p );
+if ( p->fVerbose )
+{
+printf( "Iteration %dS : Area = %11.1f ", Iter++, aAreaTotalCur );
+PRT( "Time", clock() - clk );
+}
+ aSwitchTotalPrev = aSwitchTotalCur;
+ aSwitchTotalCur = Fpga_MappingPrintSwitching( p );
+ // quit if this iteration reduced area flow by less than 1%
+ } while ( aSwitchTotalPrev > 1.01 * aSwitchTotalCur );
+ }
+
+/*
+ // compute the area of each cut
+ aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
+ // compute the required times and the fanouts
+ Fpga_TimeComputeRequiredGlobal( p );
+ // perform experiment
+ Fpga_Experiment( p );
+*/
+ p->fAreaGlo = aAreaTotalCur;
+ return 1;
+}
+
+
diff --git a/src/map/fpga/fpgaCreate.c b/src/map/fpga/fpgaCreate.c
new file mode 100644
index 00000000..fc6577fa
--- /dev/null
+++ b/src/map/fpga/fpgaCreate.c
@@ -0,0 +1,585 @@
+/**CFile****************************************************************
+
+ FileName [fpgaCreate.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaCreate.c,v 1.8 2004/09/30 21:18:09 satrajit Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+#include "main.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fpga_TableCreate( Fpga_Man_t * p );
+static void Fpga_TableResize( Fpga_Man_t * p );
+static Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+
+// hash key for the structural hash table
+static inline unsigned Fpga_HashKey2( Fpga_Node_t * p0, Fpga_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters of the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_ManReadInputNum( Fpga_Man_t * p ) { return p->nInputs; }
+int Fpga_ManReadOutputNum( Fpga_Man_t * p ) { return p->nOutputs; }
+Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p ) { return p->pInputs; }
+Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ) { return p->pOutputs; }
+Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ) { return p->pConst1; }
+float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ) { return p->pInputArrivals;}
+int Fpga_ManReadVerbose( Fpga_Man_t * p ) { return p->fVerbose; }
+float * Fpga_ManReadLutAreas( Fpga_Man_t * p ) { return p->pLutLib->pLutAreas; }
+void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time ) { p->timeToMap = Time; }
+void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time ) { p->timeToNet = Time; }
+void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time ) { p->timeTotal = Time; }
+void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; }
+void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ) { p->pInputArrivals = pArrivals; }
+void Fpga_ManSetTree( Fpga_Man_t * p, int fTree ) { p->fTree = fTree; }
+void Fpga_ManSetPower( Fpga_Man_t * p, int fPower ) { p->fPower = fPower; }
+void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;}
+void Fpga_ManSetResyn( Fpga_Man_t * p, int fResynthesis ) { p->fResynthesis = fResynthesis; }
+void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit ) { p->DelayLimit = DelayLimit; }
+void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit ) { p->AreaLimit = AreaLimit; }
+void Fpga_ManSetTimeLimit( Fpga_Man_t * p, float TimeLimit ) { p->TimeLimit = TimeLimit; }
+void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; }
+void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ) { p->nChoices = nChoices; }
+void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; }
+void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ) { p->nLatches = nLatches; }
+void Fpga_ManSetSequential( Fpga_Man_t * p, int fSequential ) { p->fSequential = fSequential; }
+void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ) { p->pFileName = pFileName; }
+
+/**Function*************************************************************
+
+ Synopsis [Reads the parameters of the LUT library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ) { return pLib->LutMax; }
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters of the mapping node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Fpga_NodeReadData0( Fpga_Node_t * p ) { return p->pData0; }
+Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ) { return p->pLevel; }
+int Fpga_NodeReadNum( Fpga_Node_t * p ) { return p->Num; }
+int Fpga_NodeReadLevel( Fpga_Node_t * p ) { return Fpga_Regular(p)->Level; }
+Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ) { return p->pCuts; }
+Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p ) { return p->pCutBest; }
+Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p ) { return p->p1; }
+Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p ) { return p->p2; }
+void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData ) { p->pData0 = pData; }
+void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode ) { p->pLevel = pNode; }
+void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ) { p->pNextE = pNextE; }
+void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr ) { p->pRepr = pRepr; }
+
+/**Function*************************************************************
+
+ Synopsis [Checks the type of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_NodeIsConst( Fpga_Node_t * p ) { return (Fpga_Regular(p))->Num == -1; }
+int Fpga_NodeIsVar( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 == NULL && (Fpga_Regular(p))->Num >= 0; }
+int Fpga_NodeIsAnd( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 != NULL; }
+int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ) { assert( !Fpga_IsComplement(p1) ); assert( !Fpga_IsComplement(p2) ); return p1->fInv ^ p2->fInv; }
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters from the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutReadLeavesNum( Fpga_Cut_t * p ) { return p->nLeaves; }
+Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p ) { return p->ppLeaves; }
+
+
+/**Function*************************************************************
+
+ Synopsis [Create the mapping manager.]
+
+ Description [The number of inputs and outputs is assumed to be
+ known is advance. It is much simpler to have them fixed upfront.
+ When it comes to representing the object graph in the form of
+ AIG, the resulting manager is similar to the regular AIG manager,
+ except that it does not use reference counting (and therefore
+ does not have garbage collections). It does have table resizing.
+ The data structure is more flexible to represent additional
+ information needed for mapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose )
+{
+ Fpga_Man_t * p;
+ int i;
+
+ // start the manager
+ p = ALLOC( Fpga_Man_t, 1 );
+ memset( p, 0, sizeof(Fpga_Man_t) );
+ p->pLutLib = Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame());
+ p->nVarsMax = p->pLutLib->LutMax;
+ p->fVerbose = fVerbose;
+ p->fAreaRecovery = 1;
+ p->fTree = 0;
+ p->fRefCount = 1;
+ p->fEpsilon = (float)0.00001;
+
+ Fpga_TableCreate( p );
+//if ( p->fVerbose )
+// printf( "Node = %d (%d) bytes. Cut = %d bytes.\n", sizeof(Fpga_Node_t), FPGA_NUM_BYTES(sizeof(Fpga_Node_t)), sizeof(Fpga_Cut_t) );
+ p->mmNodes = Extra_MmFixedStart( FPGA_NUM_BYTES(sizeof(Fpga_Node_t)) );
+ p->mmCuts = Extra_MmFixedStart( sizeof(Fpga_Cut_t) );
+
+ assert( p->nVarsMax > 0 );
+ Fpga_MappingSetupTruthTables( p->uTruths );
+
+ // make sure the constant node will get index -1
+ p->nNodes = -1;
+ // create the constant node
+ p->pConst1 = Fpga_NodeCreate( p, NULL, NULL );
+ p->vNodesAll = Fpga_NodeVecAlloc( 100 );
+
+ // create the PI nodes
+ p->nInputs = nInputs;
+ p->pInputs = ALLOC( Fpga_Node_t *, nInputs );
+ for ( i = 0; i < nInputs; i++ )
+ p->pInputs[i] = Fpga_NodeCreate( p, NULL, NULL );
+
+ // create the place for the output nodes
+ p->nOutputs = nOutputs;
+ p->pOutputs = ALLOC( Fpga_Node_t *, nOutputs );
+ memset( p->pOutputs, 0, sizeof(Fpga_Node_t *) * nOutputs );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_ManFree( Fpga_Man_t * p )
+{
+// Fpga_ManStats( p );
+
+// int i;
+// for ( i = 0; i < p->vNodesAll->nSize; i++ )
+// Fpga_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts );
+// Fpga_NodeVecFree( p->pConst1->vFanouts );
+ if ( p->vAnds )
+ Fpga_NodeVecFree( p->vAnds );
+ if ( p->vNodesAll )
+ Fpga_NodeVecFree( p->vNodesAll );
+ Extra_MmFixedStop( p->mmNodes, 0 );
+ Extra_MmFixedStop( p->mmCuts, 0 );
+ FREE( p->pInputArrivals );
+ FREE( p->pInputs );
+ FREE( p->pOutputs );
+ FREE( p->pBins );
+// FREE( p->ppOutputNames );
+ if ( p->pSimInfo )
+ {
+ FREE( p->pSimInfo[0] );
+ FREE( p->pSimInfo );
+ }
+ FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints runtime statistics of the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_ManPrintTimeStats( Fpga_Man_t * p )
+{
+ extern char * pNetName;
+ extern int TotalLuts;
+// FILE * pTable;
+
+
+/*
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNetName );
+ fprintf( pTable, "%.0f ", p->fRequiredGlo );
+// fprintf( pTable, "%.0f ", p->fAreaGlo );//+ (float)nOutputInvs );
+ fprintf( pTable, "%.0f ", (float)TotalLuts );
+ fprintf( pTable, "%4.2f\n", (float)(p->timeTotal-p->timeToMap)/(float)(CLOCKS_PER_SEC) );
+ fclose( pTable );
+*/
+
+// printf( "N-canonical = %d. Matchings = %d. ", p->nCanons, p->nMatches );
+// printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices );
+ PRT( "ToMap", p->timeToMap );
+ PRT( "Cuts ", p->timeCuts );
+ PRT( "Match", p->timeMatch );
+ PRT( "Area ", p->timeRecover );
+ PRT( "ToNet", p->timeToNet );
+ PRT( "TOTAL", p->timeTotal );
+ if ( p->time1 ) { PRT( "time1", p->time1 ); }
+ if ( p->time2 ) { PRT( "time2", p->time2 ); }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description [This procedure should be called to create the constant
+ node and the PI nodes first.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ Fpga_Node_t * pNode;
+ // create the node
+ pNode = (Fpga_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes );
+ memset( pNode, 0, sizeof(Fpga_Node_t) );
+ // set very large required time
+ pNode->tRequired = FPGA_FLOAT_LARGE;
+ pNode->aEstFanouts = -1;
+ pNode->p1 = p1;
+ pNode->p2 = p2;
+ // set the number of this node
+ pNode->Num = p->nNodes++;
+ // place to store the fanouts
+// pNode->vFanouts = Fpga_NodeVecAlloc( 5 );
+ // store this node in the internal array
+ if ( pNode->Num >= 0 )
+ Fpga_NodeVecPush( p->vNodesAll, pNode );
+ else
+ pNode->fInv = 1;
+ // set the level of this node
+ if ( p1 )
+ {
+ // create the fanout info
+ Fpga_NodeAddFaninFanout( Fpga_Regular(p1), pNode );
+ Fpga_NodeAddFaninFanout( Fpga_Regular(p2), pNode );
+ // compute the level
+ pNode->Level = 1 + FPGA_MAX(Fpga_Regular(p1)->Level, Fpga_Regular(p2)->Level);
+ pNode->fInv = Fpga_NodeIsSimComplement(p1) & Fpga_NodeIsSimComplement(p2);
+ }
+ // reference the inputs (will be used to compute the number of fanouts)
+ if ( p->fRefCount )
+ {
+ if ( p1 ) Fpga_NodeRef(p1);
+ if ( p2 ) Fpga_NodeRef(p2);
+ }
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the unique table of AND gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_TableCreate( Fpga_Man_t * pMan )
+{
+ assert( pMan->pBins == NULL );
+ pMan->nBins = Cudd_Prime(50000);
+ pMan->pBins = ALLOC( Fpga_Node_t *, pMan->nBins );
+ memset( pMan->pBins, 0, sizeof(Fpga_Node_t *) * pMan->nBins );
+ pMan->nNodes = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the AND2 node in the unique table.]
+
+ Description [This procedure implements one-level hashing. All the nodes
+ are hashed by their children. If the node with the same children was already
+ created, it is returned by the call to this procedure. If it does not exist,
+ this procedure creates a new node with these children. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * pMan, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ Fpga_Node_t * pEnt;
+ unsigned Key;
+
+ if ( p1 == p2 )
+ return p1;
+ if ( p1 == Fpga_Not(p2) )
+ return Fpga_Not(pMan->pConst1);
+ if ( Fpga_NodeIsConst(p1) )
+ {
+ if ( p1 == pMan->pConst1 )
+ return p2;
+ return Fpga_Not(pMan->pConst1);
+ }
+ if ( Fpga_NodeIsConst(p2) )
+ {
+ if ( p2 == pMan->pConst1 )
+ return p1;
+ return Fpga_Not(pMan->pConst1);
+ }
+
+ if ( Fpga_Regular(p1)->Num > Fpga_Regular(p2)->Num )
+ pEnt = p1, p1 = p2, p2 = pEnt;
+
+ Key = Fpga_HashKey2( p1, p2, pMan->nBins );
+ for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( pEnt->p1 == p1 && pEnt->p2 == p2 )
+ return pEnt;
+ // resize the table
+ if ( pMan->nNodes >= 2 * pMan->nBins )
+ {
+ Fpga_TableResize( pMan );
+ Key = Fpga_HashKey2( p1, p2, pMan->nBins );
+ }
+ // create the new node
+ pEnt = Fpga_NodeCreate( pMan, p1, p2 );
+ // add the node to the corresponding linked list in the table
+ pEnt->pNext = pMan->pBins[Key];
+ pMan->pBins[Key] = pEnt;
+ return pEnt;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_TableResize( Fpga_Man_t * pMan )
+{
+ Fpga_Node_t ** pBinsNew;
+ Fpga_Node_t * pEnt, * pEnt2;
+ int nBinsNew, Counter, i, clk;
+ unsigned Key;
+
+clk = clock();
+ // get the new table size
+ nBinsNew = Cudd_Prime(2 * pMan->nBins);
+ // allocate a new array
+ pBinsNew = ALLOC( Fpga_Node_t *, nBinsNew );
+ memset( pBinsNew, 0, sizeof(Fpga_Node_t *) * nBinsNew );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( i = 0; i < pMan->nBins; i++ )
+ for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt;
+ pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL )
+ {
+ Key = Fpga_HashKey2( pEnt->p1, pEnt->p2, nBinsNew );
+ pEnt->pNext = pBinsNew[Key];
+ pBinsNew[Key] = pEnt;
+ Counter++;
+ }
+ assert( Counter == pMan->nNodes - pMan->nInputs );
+ if ( pMan->fVerbose )
+ {
+// printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew );
+// PRT( "Time", clock() - clk );
+ }
+ // replace the table and the parameters
+ free( pMan->pBins );
+ pMan->pBins = pBinsNew;
+ pMan->nBins = nBinsNew;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Elementary AND operation on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ Fpga_Node_t * pNode;
+ pNode = Fpga_TableLookup( p, p1, p2 );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Elementary OR operation on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ Fpga_Node_t * pNode;
+ pNode = Fpga_Not( Fpga_TableLookup( p, Fpga_Not(p1), Fpga_Not(p2) ) );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Elementary EXOR operation on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ return Fpga_NodeMux( p, p1, Fpga_Not(p2), p2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Elementary MUX operation on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pC, Fpga_Node_t * pT, Fpga_Node_t * pE )
+{
+ Fpga_Node_t * pAnd1, * pAnd2, * pRes;
+ pAnd1 = Fpga_TableLookup( p, pC, pT );
+ pAnd2 = Fpga_TableLookup( p, Fpga_Not(pC), pE );
+ pRes = Fpga_NodeOr( p, pAnd1, pAnd2 );
+ return pRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets the node to be equivalent to the given one.]
+
+ Description [This procedure is a work-around for the equivalence check.
+ Does not verify the equivalence. Use at the user's risk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew )
+{
+ pNodeNew->pNextE = pNodeOld->pNextE;
+ pNodeOld->pNextE = pNodeNew;
+ pNodeNew->pRepr = pNodeOld;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints some interesting stats.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_ManStats( Fpga_Man_t * p )
+{
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", p->pFileName );
+ fprintf( pTable, "%4d ", p->nInputs - p->nLatches );
+ fprintf( pTable, "%4d ", p->nOutputs - p->nLatches );
+ fprintf( pTable, "%4d ", p->nLatches );
+ fprintf( pTable, "%7d ", p->vAnds->nSize );
+ fprintf( pTable, "%7d ", Fpga_CutCountAll(p) );
+ fprintf( pTable, "%2d\n", (int)p->fRequiredGlo );
+ fclose( pTable );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/fpga/fpgaCut.c b/src/map/fpga/fpgaCut.c
new file mode 100644
index 00000000..27079953
--- /dev/null
+++ b/src/map/fpga/fpgaCut.c
@@ -0,0 +1,1150 @@
+/**CFile****************************************************************
+
+ FileName [fpgaCut.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaCut.c,v 1.3 2004/07/06 04:55:57 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fpga_CutTableStrutct_t Fpga_CutTable_t;
+struct Fpga_CutTableStrutct_t
+{
+ Fpga_Cut_t ** pBins; // the table used for linear probing
+ int nBins; // the size of the table
+ int * pCuts; // the array of cuts currently stored
+ int nCuts; // the number of cuts currently stored
+ Fpga_Cut_t ** pArray; // the temporary array of cuts
+ Fpga_Cut_t ** pCuts1; // the temporary array of cuts
+ Fpga_Cut_t ** pCuts2; // the temporary array of cuts
+};
+
+// the largest number of cuts considered
+#define FPGA_CUTS_MAX_COMPUTE 500
+// the largest number of cuts used
+#define FPGA_CUTS_MAX_USE 200
+
+// primes used to compute the hash key
+static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 };
+
+static int bit_count[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+#define FPGA_COUNT_ONES(u) (bit_count[(u)&255]+bit_count[((u)>>8)&255]+bit_count[((u)>>16)&255]+bit_count[(u)>>24])
+
+static Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode );
+static void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode );
+static Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 );
+static int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax );
+static Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 );
+static int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes );
+extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p );
+extern int Fpga_CutCountAll( Fpga_Man_t * pMan );
+
+static void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot );
+static void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot );
+static void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot );
+
+static Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan );
+static void Fpga_CutTableStop( Fpga_CutTable_t * p );
+static unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes );
+static int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes );
+static Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes );
+static void Fpga_CutTableRestart( Fpga_CutTable_t * p );
+
+static int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 );
+static Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList );
+static int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList );
+static Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts );
+
+
+// iterator through all the cuts of the list
+#define Fpga_ListForEachCut( pList, pCut ) \
+ for ( pCut = pList; \
+ pCut; \
+ pCut = pCut->pNext )
+#define Fpga_ListForEachCutSafe( pList, pCut, pCut2 ) \
+ for ( pCut = pList, \
+ pCut2 = pCut? pCut->pNext: NULL; \
+ pCut; \
+ pCut = pCut2, \
+ pCut2 = pCut? pCut->pNext: NULL )
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for each node in the object graph.]
+
+ Description [The cuts are computed in one sweep over the mapping graph.
+ First, the elementary cuts, which include the node itself, are assigned
+ to the PI nodes. The internal nodes are considered in the DFS order.
+ Each node is two-input AND-gate. So to compute the cuts at a node, we
+ need to merge the sets of cuts of its two predecessors. The merged set
+ contains only unique cuts with the number of inputs equal to k or less.
+ Finally, the elementary cut, composed of the node itself, is added to
+ the set of cuts for the node.
+
+ This procedure is pretty fast for 5-feasible cuts, but it dramatically
+ slows down on some "dense" networks when computing 6-feasible cuts.
+ The problem is that there are too many cuts in this case. We should
+ think how to heuristically trim the number of cuts in such cases,
+ to have reasonable runtime.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingCuts( Fpga_Man_t * p )
+{
+ ProgressBar * pProgress;
+ Fpga_CutTable_t * pTable;
+ Fpga_Node_t * pNode;
+ int nCuts, nNodes, i;
+
+ // set the elementary cuts for the PI variables
+ assert( p->nVarsMax > 1 && p->nVarsMax < 7 );
+ Fpga_MappingCreatePiCuts( p );
+
+ // compute the cuts for the internal nodes
+ nNodes = p->vAnds->nSize;
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ pTable = Fpga_CutTableStart( p );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." );
+ pNode = p->vAnds->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ Fpga_CutCompute( p, pTable, pNode );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Fpga_CutTableStop( pTable );
+
+ // report the stats
+ if ( p->fVerbose )
+ {
+ nCuts = Fpga_CutCountAll(p);
+ printf( "Nodes = %6d. Total %d-feasible cuts = %d. Cuts per node = %.1f.\n",
+ p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes );
+ }
+
+ // print the cuts for the first primary output
+// Fpga_CutListPrint( p, Fpga_Regular(p->pOutputs[0]) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs technology mapping for variable-size-LUTs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingCreatePiCuts( Fpga_Man_t * p )
+{
+ Fpga_Cut_t * pCut;
+ int i;
+
+ // set the elementary cuts for the PI variables
+ for ( i = 0; i < p->nInputs; i++ )
+ {
+ pCut = Fpga_CutAlloc( p );
+ pCut->nLeaves = 1;
+ pCut->ppLeaves[0] = p->pInputs[i];
+ pCut->uSign = (1 << (i%31));
+ p->pInputs[i]->pCuts = pCut;
+ p->pInputs[i]->pCutBest = pCut;
+ // set the input arrival times
+// p->pInputs[i]->pCut[1]->tArrival = p->pInputArrivals[i];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode )
+{
+ Fpga_Node_t * pTemp;
+ Fpga_Cut_t * pList, * pList1, * pList2;
+ Fpga_Cut_t * pCut;
+ int fPivot1 = p->fTree && (Fpga_NodeReadRef(pNode->p1)>2);
+ int fPivot2 = p->fTree && (Fpga_NodeReadRef(pNode->p2)>2);
+
+ // if the cuts are computed return them
+ if ( pNode->pCuts )
+ return pNode->pCuts;
+
+ // compute the cuts for the children
+ pList1 = Fpga_Regular(pNode->p1)->pCuts;
+ pList2 = Fpga_Regular(pNode->p2)->pCuts;
+ // merge the lists
+ pList = Fpga_CutMergeLists( p, pTable, pList1, pList2,
+ Fpga_IsComplement(pNode->p1), Fpga_IsComplement(pNode->p2),
+ fPivot1, fPivot2 );
+ // if there are functionally equivalent nodes, union them with this list
+ assert( pList );
+ // only add to the list of cuts if the node is a representative one
+ if ( pNode->pRepr == NULL )
+ {
+ for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+ {
+ assert( pTemp->pCuts );
+ pList = Fpga_CutUnionLists( pList, pTemp->pCuts );
+ assert( pTemp->pCuts );
+ pList = Fpga_CutSortCuts( p, pTable, pList );
+ }
+ }
+ // add the new cut
+ pCut = Fpga_CutAlloc( p );
+ pCut->nLeaves = 1;
+ pCut->ppLeaves[0] = pNode;
+ pCut->uSign = (1 << (pNode->Num%31));
+ pCut->fLevel = (float)pCut->ppLeaves[0]->Level;
+ // append (it is important that the elementary cut is appended first)
+ pCut->pNext = pList;
+ // set at the node
+ pNode->pCuts = pCut;
+ // remove the dominated cuts
+ Fpga_CutFilter( p, pNode );
+ // set the phase correctly
+ if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) )
+ {
+ Fpga_ListForEachCut( pNode->pCuts, pCut )
+ pCut->Phase = 1;
+ }
+
+
+/*
+ {
+ Fpga_Cut_t * pPrev;
+ int i, Counter = 0;
+ for ( pCut = pNode->pCuts->pNext, pPrev = pNode->pCuts; pCut; pCut = pCut->pNext )
+ {
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ if ( pCut->ppLeaves[i]->Level >= pNode->Level )
+ break;
+ if ( i != pCut->nLeaves )
+ pPrev->pNext = pCut->pNext;
+ else
+ pPrev = pCut;
+ }
+ }
+ {
+ int i, Counter = 0;;
+ for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ Counter += (pCut->ppLeaves[i]->Level >= pNode->Level);
+ if ( Counter )
+ printf( " %d", Counter );
+ }
+*/
+
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filter the cuts using dominance.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode )
+{
+ Fpga_Cut_t * pTemp, * pPrev, * pCut, * pCut2;
+ int i, k, Counter;
+
+ Counter = 0;
+ pPrev = pNode->pCuts;
+ Fpga_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 )
+ {
+ // go through all the previous cuts up to pCut
+ for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext )
+ {
+ // check if every node in pTemp is contained in pCut
+ for ( i = 0; i < pTemp->nLeaves; i++ )
+ {
+ for ( k = 0; k < pCut->nLeaves; k++ )
+ if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] )
+ break;
+ if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut
+ break;
+ }
+ if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut
+ {
+ Counter++;
+ break;
+ }
+ }
+ if ( pTemp != pCut ) // pTemp contain pCut
+ {
+ pPrev->pNext = pCut->pNext; // skip pCut
+ // recycle pCut
+ Fpga_CutFree( p, pCut );
+ }
+ else
+ pPrev = pCut;
+ }
+// printf( "Dominated = %3d. \n", Counter );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Merges two lists of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable,
+ Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 )
+{
+ Fpga_Node_t * ppNodes[6];
+ Fpga_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
+ Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
+ int nNodes, Counter, i;
+ Fpga_Cut_t ** ppArray1, ** ppArray2, ** ppArray3;
+ int nCuts1, nCuts2, nCuts3, k, fComp3;
+
+ ppArray1 = pTable->pCuts1;
+ ppArray2 = pTable->pCuts2;
+ nCuts1 = Fpga_CutList2Array( ppArray1, pList1 );
+ nCuts2 = Fpga_CutList2Array( ppArray2, pList2 );
+ if ( fPivot1 )
+ nCuts1 = 1;
+ if ( fPivot2 )
+ nCuts2 = 1;
+ // swap the lists based on their length
+ if ( nCuts1 > nCuts2 )
+ {
+ ppArray3 = ppArray1;
+ ppArray1 = ppArray2;
+ ppArray2 = ppArray3;
+
+ nCuts3 = nCuts1;
+ nCuts1 = nCuts2;
+ nCuts2 = nCuts3;
+
+ fComp3 = fComp1;
+ fComp1 = fComp2;
+ fComp2 = fComp3;
+ }
+ // pList1 is shorter or equal length compared to pList2
+
+ // prepare the manager for the cut computation
+ Fpga_CutTableRestart( pTable );
+ // go through the cut pairs
+ Counter = 0;
+// for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext )
+// for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext )
+ for ( i = 0; i < nCuts1; i++ )
+ {
+ for ( k = 0; k <= i; k++ )
+ {
+ pTemp1 = ppArray1[i];
+ pTemp2 = ppArray2[k];
+
+ if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+ {
+ if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+ continue;
+ if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+ continue;
+ }
+
+ // check if k-feasible cut exists
+ nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+ if ( nNodes == 0 )
+ continue;
+ // consider the cut for possible addition to the set of new cuts
+ pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes );
+ if ( pCut == NULL )
+ continue;
+ // add data to the cut
+ pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 );
+ pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 );
+ // create the signature
+ pCut->uSign = pTemp1->uSign | pTemp2->uSign;
+ // add it to the corresponding list
+ pCut->pNext = pLists[pCut->nLeaves];
+ pLists[pCut->nLeaves] = pCut;
+ // count this cut and quit if limit is reached
+ Counter++;
+ if ( Counter == FPGA_CUTS_MAX_COMPUTE )
+ goto QUITS;
+ }
+ for ( k = 0; k < i; k++ )
+ {
+ pTemp1 = ppArray1[k];
+ pTemp2 = ppArray2[i];
+
+ if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+ {
+ if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+ continue;
+ if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+ continue;
+ }
+
+
+ // check if k-feasible cut exists
+ nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+ if ( nNodes == 0 )
+ continue;
+ // consider the cut for possible addition to the set of new cuts
+ pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes );
+ if ( pCut == NULL )
+ continue;
+ // add data to the cut
+ pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 );
+ pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 );
+ // create the signature
+ pCut->uSign = pTemp1->uSign | pTemp2->uSign;
+ // add it to the corresponding list
+ pCut->pNext = pLists[pCut->nLeaves];
+ pLists[pCut->nLeaves] = pCut;
+ // count this cut and quit if limit is reached
+ Counter++;
+ if ( Counter == FPGA_CUTS_MAX_COMPUTE )
+ goto QUITS;
+ }
+ }
+ // consider the rest of them
+ for ( i = nCuts1; i < nCuts2; i++ )
+ for ( k = 0; k < nCuts1; k++ )
+ {
+ pTemp1 = ppArray1[k];
+ pTemp2 = ppArray2[i];
+
+ if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax )
+ {
+ if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] )
+ continue;
+ if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] )
+ continue;
+ if ( pTemp1->ppLeaves[2] != pTemp2->ppLeaves[2] )
+ continue;
+ }
+
+
+ // check if k-feasible cut exists
+ nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+ if ( nNodes == 0 )
+ continue;
+ // consider the cut for possible addition to the set of new cuts
+ pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes );
+ if ( pCut == NULL )
+ continue;
+ // add data to the cut
+ pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 );
+ pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 );
+ // create the signature
+ pCut->uSign = pTemp1->uSign | pTemp2->uSign;
+ // add it to the corresponding list
+ pCut->pNext = pLists[pCut->nLeaves];
+ pLists[pCut->nLeaves] = pCut;
+ // count this cut and quit if limit is reached
+ Counter++;
+ if ( Counter == FPGA_CUTS_MAX_COMPUTE )
+ goto QUITS;
+ }
+QUITS :
+ // combine all the lists into one
+ pListNew = NULL;
+ ppListNew = &pListNew;
+ for ( i = 1; i <= p->nVarsMax; i++ )
+ {
+ if ( pLists[i] == NULL )
+ continue;
+ // find the last entry
+ for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut;
+ pPrev = pCut, pCut = pCut->pNext );
+ // connect these lists
+ *ppListNew = pLists[i];
+ ppListNew = &pPrev->pNext;
+ }
+ *ppListNew = NULL;
+ // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE
+ pListNew = Fpga_CutSortCuts( p, pTable, pListNew );
+ return pListNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Merges two lists of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutMergeLists2( Fpga_Man_t * p, Fpga_CutTable_t * pTable,
+ Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 )
+{
+ Fpga_Node_t * ppNodes[6];
+ Fpga_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
+ Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
+ int nNodes, Counter, i;
+
+ // prepare the manager for the cut computation
+ Fpga_CutTableRestart( pTable );
+ // go through the cut pairs
+ Counter = 0;
+ for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext )
+ for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext )
+ {
+ // check if k-feasible cut exists
+ nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+ if ( nNodes == 0 )
+ continue;
+ // consider the cut for possible addition to the set of new cuts
+ pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes );
+ if ( pCut == NULL )
+ continue;
+ // add data to the cut
+ pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 );
+ pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 );
+ // add it to the corresponding list
+ pCut->pNext = pLists[pCut->nLeaves];
+ pLists[pCut->nLeaves] = pCut;
+ // count this cut and quit if limit is reached
+ Counter++;
+ if ( Counter == FPGA_CUTS_MAX_COMPUTE )
+ goto QUITS;
+ }
+QUITS :
+ // combine all the lists into one
+ pListNew = NULL;
+ ppListNew = &pListNew;
+ for ( i = 1; i <= p->nVarsMax; i++ )
+ {
+ if ( pLists[i] == NULL )
+ continue;
+ // find the last entry
+ for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut;
+ pPrev = pCut, pCut = pCut->pNext );
+ // connect these lists
+ *ppListNew = pLists[i];
+ ppListNew = &pPrev->pNext;
+ }
+ *ppListNew = NULL;
+ // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE
+ pListNew = Fpga_CutSortCuts( p, pTable, pListNew );
+ return pListNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two cuts.]
+
+ Description [Returns the number of nodes in the resulting cut, or 0 if the
+ cut is infeasible. Returns the resulting nodes in the array ppNodes[].]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax )
+{
+ Fpga_Node_t * pNodeTemp;
+ int nTotal, i, k, min, Counter;
+ unsigned uSign;
+
+ // use quick prefiltering
+ uSign = pCut1->uSign | pCut2->uSign;
+ Counter = FPGA_COUNT_ONES(uSign);
+ if ( Counter > nNodesMax )
+ return 0;
+/*
+ // check the special case when at least of the cuts is the largest
+ if ( pCut1->nLeaves == nNodesMax )
+ {
+ if ( pCut2->nLeaves == nNodesMax )
+ {
+ // return 0 if the cuts are different
+ for ( i = 0; i < nNodesMax; i++ )
+ if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] )
+ return 0;
+ // return nNodesMax if they are the same
+ for ( i = 0; i < nNodesMax; i++ )
+ ppNodes[i] = pCut1->ppLeaves[i];
+ return nNodesMax;
+ }
+ else if ( pCut2->nLeaves == nNodesMax - 1 )
+ {
+ // return 0 if the cuts are different
+ fMismatch = 0;
+ for ( i = 0; i < nNodesMax; i++ )
+ if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] )
+ {
+ if ( fMismatch == 1 )
+ return 0;
+ fMismatch = 1;
+ }
+ // return nNodesMax if they are the same
+ for ( i = 0; i < nNodesMax; i++ )
+ ppNodes[i] = pCut1->ppLeaves[i];
+ return nNodesMax;
+ }
+ }
+ else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax )
+ {
+ // return 0 if the cuts are different
+ fMismatch = 0;
+ for ( i = 0; i < nNodesMax; i++ )
+ if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] )
+ {
+ if ( fMismatch == 1 )
+ return 0;
+ fMismatch = 1;
+ }
+ // return nNodesMax if they are the same
+ for ( i = 0; i < nNodesMax; i++ )
+ ppNodes[i] = pCut2->ppLeaves[i];
+ return nNodesMax;
+ }
+*/
+ // count the number of unique entries in pCut2
+ nTotal = pCut1->nLeaves;
+ for ( i = 0; i < pCut2->nLeaves; i++ )
+ {
+ // try to find this entry among the leaves of pCut1
+ for ( k = 0; k < pCut1->nLeaves; k++ )
+ if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] )
+ break;
+ if ( k < pCut1->nLeaves ) // found
+ continue;
+ // we found a new entry to add
+ if ( nTotal == nNodesMax )
+ return 0;
+ ppNodes[nTotal++] = pCut2->ppLeaves[i];
+ }
+ // we know that the feasible cut exists
+
+ // add the starting entries
+ for ( k = 0; k < pCut1->nLeaves; k++ )
+ ppNodes[k] = pCut1->ppLeaves[k];
+
+ // selection-sort the entries
+ for ( i = 0; i < nTotal - 1; i++ )
+ {
+ min = i;
+ for ( k = i+1; k < nTotal; k++ )
+ if ( ppNodes[k] < ppNodes[min] )
+ min = k;
+ pNodeTemp = ppNodes[i];
+ ppNodes[i] = ppNodes[min];
+ ppNodes[min] = pNodeTemp;
+ }
+
+ return nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the union of the two lists of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 )
+{
+ Fpga_Cut_t * pTemp, * pRoot;
+ // find the last cut in the first list
+ pRoot = pList1;
+ Fpga_ListForEachCut( pList1, pTemp )
+ pRoot = pTemp;
+ // attach the non-trival part of the second cut to the end of the first
+ assert( pRoot->pNext == NULL );
+ pRoot->pNext = pList2->pNext;
+ pList2->pNext = NULL;
+ return pList1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks whether the given cut belongs to the list.]
+
+ Description [This procedure takes most of the runtime in the cut
+ computation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes )
+{
+ Fpga_Cut_t * pTemp;
+ int i;
+ for ( pTemp = pList; pTemp; pTemp = pTemp->pNext )
+ {
+ for ( i = 0; i < nNodes; i++ )
+ if ( pTemp->ppLeaves[i] != ppNodes[i] )
+ break;
+ if ( i == nNodes )
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts all the cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutCountAll( Fpga_Man_t * pMan )
+{
+ Fpga_Node_t * pNode;
+ Fpga_Cut_t * pCut;
+ int i, nCuts;
+ // go through all the nodes in the unique table of the manager
+ nCuts = 0;
+ for ( i = 0; i < pMan->nBins; i++ )
+ for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
+ for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
+ if ( pCut->nLeaves > 1 ) // skip the elementary cuts
+ nCuts++;
+ return nCuts;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Clean the signatures.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutsCleanSign( Fpga_Man_t * pMan )
+{
+ Fpga_Node_t * pNode;
+ Fpga_Cut_t * pCut;
+ int i;
+ for ( i = 0; i < pMan->nBins; i++ )
+ for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
+ for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
+ pCut->uSign = 0;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the cuts in the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot )
+{
+ Fpga_Cut_t * pTemp;
+ int Counter;
+ for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
+ {
+ printf( "%2d : ", Counter + 1 );
+ Fpga_CutPrint_( pMan, pTemp, pRoot );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the cuts in the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot )
+{
+ Fpga_Cut_t * pTemp;
+ int Counter;
+ for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
+ {
+ printf( "%2d : ", Counter + 1 );
+ Fpga_CutPrint_( pMan, pTemp, pRoot );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot )
+{
+ int i;
+ printf( "(%3d) {", pRoot->Num );
+ for ( i = 0; i < pMan->nVarsMax; i++ )
+ if ( pCut->ppLeaves[i] )
+ printf( " %3d", pCut->ppLeaves[i]->Num );
+ printf( " }\n" );
+}
+
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the hash table to canonicize cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan )
+{
+ Fpga_CutTable_t * p;
+ // allocate the table
+ p = ALLOC( Fpga_CutTable_t, 1 );
+ memset( p, 0, sizeof(Fpga_CutTable_t) );
+ p->nBins = Cudd_Prime( 10 * FPGA_CUTS_MAX_COMPUTE );
+ p->pBins = ALLOC( Fpga_Cut_t *, p->nBins );
+ memset( p->pBins, 0, sizeof(Fpga_Cut_t *) * p->nBins );
+ p->pCuts = ALLOC( int, 2 * FPGA_CUTS_MAX_COMPUTE );
+ p->pArray = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE );
+ p->pCuts1 = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE );
+ p->pCuts2 = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutTableStop( Fpga_CutTable_t * p )
+{
+ free( p->pCuts1 );
+ free( p->pCuts2 );
+ free( p->pArray );
+ free( p->pBins );
+ free( p->pCuts );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the hash value of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes )
+{
+ unsigned uRes;
+ int i;
+ uRes = 0;
+ for ( i = 0; i < nNodes; i++ )
+ uRes += s_HashPrimes[i] * ppNodes[i]->Num;
+ return uRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the table for the available cut.]
+
+ Description [Returns -1 if the same cut is found. Returns the index
+ of the cell where the cut should be added, if it does not exist.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes )
+{
+ Fpga_Cut_t * pCut;
+ unsigned Key;
+ int b, i;
+
+ Key = Fpga_CutTableHash(ppNodes, nNodes) % p->nBins;
+ for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins )
+ {
+ pCut = p->pBins[b];
+ if ( pCut->nLeaves != nNodes )
+ continue;
+ for ( i = 0; i < nNodes; i++ )
+ if ( pCut->ppLeaves[i] != ppNodes[i] )
+ break;
+ if ( i == nNodes )
+ return -1;
+ }
+ return b;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the hash table to canonicize cuts.]
+
+ Description [Considers addition of the cut to the hash table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes )
+{
+ Fpga_Cut_t * pCut;
+ int Place, i;
+ // check the cut
+ Place = Fpga_CutTableLookup( p, ppNodes, nNodes );
+ if ( Place == -1 )
+ return NULL;
+ assert( nNodes > 0 );
+ // create the new cut
+ pCut = Fpga_CutAlloc( pMan );
+ pCut->nLeaves = nNodes;
+ pCut->fLevel = 0.0;
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pCut->ppLeaves[i] = ppNodes[i];
+ pCut->fLevel += ppNodes[i]->Level;
+ }
+ pCut->fLevel /= nNodes;
+ // add the cut to the table
+ assert( p->pBins[Place] == NULL );
+ p->pBins[Place] = pCut;
+ // add the cut to the new list
+ p->pCuts[ p->nCuts++ ] = Place;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the table to be used with other cuts.]
+
+ Description [Restarts the table by cleaning the info about cuts stored
+ when the previous node was considered.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutTableRestart( Fpga_CutTable_t * p )
+{
+ int i;
+ for ( i = 0; i < p->nCuts; i++ )
+ {
+ assert( p->pBins[ p->pCuts[i] ] );
+ p->pBins[ p->pCuts[i] ] = NULL;
+ }
+ p->nCuts = 0;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares the cuts by the number of leaves and then by delay.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 )
+{
+ if ( (*pC1)->nLeaves < (*pC2)->nLeaves )
+ return -1;
+ if ( (*pC1)->nLeaves > (*pC2)->nLeaves )
+ return 1;
+/*
+ if ( (*pC1)->fLevel > (*pC2)->fLevel )
+ return -1;
+ if ( (*pC1)->fLevel < (*pC2)->fLevel )
+ return 1;
+*/
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorts the cuts by average arrival time.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList )
+{
+ Fpga_Cut_t * pListNew;
+ int nCuts, i;
+ // move the cuts from the list into the array
+ nCuts = Fpga_CutList2Array( p->pCuts1, pList );
+ assert( nCuts <= FPGA_CUTS_MAX_COMPUTE );
+ // sort the cuts
+ qsort( (void *)p->pCuts1, nCuts, sizeof(Fpga_Cut_t *),
+ (int (*)(const void *, const void *)) Fpga_CutSortCutsCompare );
+ // move them back into the list
+ if ( nCuts > FPGA_CUTS_MAX_USE - 1 )
+ {
+// printf( "*" );
+ // free the remaining cuts
+ for ( i = FPGA_CUTS_MAX_USE - 1; i < nCuts; i++ )
+ Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] );
+ // update the number of cuts
+ nCuts = FPGA_CUTS_MAX_USE - 1;
+ }
+ pListNew = Fpga_CutArray2List( p->pCuts1, nCuts );
+ return pListNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves the nodes from the list into the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList )
+{
+ int i;
+ for ( i = 0; pList; pList = pList->pNext, i++ )
+ pArray[i] = pList;
+ return i;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves the nodes from the array into the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts )
+{
+ Fpga_Cut_t * pListNew, ** ppListNew;
+ int i;
+ pListNew = NULL;
+ ppListNew = &pListNew;
+ for ( i = 0; i < nCuts; i++ )
+ {
+ // connect these lists
+ *ppListNew = pArray[i];
+ ppListNew = &pArray[i]->pNext;
+//printf( " %d(%.2f)", pArray[i]->nLeaves, pArray[i]->fLevel );
+ }
+//printf( "\n" );
+
+ *ppListNew = NULL;
+ return pListNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/fpga/fpgaCutUtils.c b/src/map/fpga/fpgaCutUtils.c
new file mode 100644
index 00000000..abe703a2
--- /dev/null
+++ b/src/map/fpga/fpgaCutUtils.c
@@ -0,0 +1,571 @@
+/**CFile****************************************************************
+
+ FileName [fpgaCutUtils.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p )
+{
+ Fpga_Cut_t * pCut;
+ pCut = (Fpga_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts );
+ memset( pCut, 0, sizeof(Fpga_Cut_t) );
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld )
+{
+ Fpga_Cut_t * pCutNew;
+ int i;
+ pCutNew = Fpga_CutAlloc( p );
+ pCutNew->pRoot = pCutOld->pRoot;
+ pCutNew->nLeaves = pCutOld->nLeaves;
+ for ( i = 0; i < pCutOld->nLeaves; i++ )
+ pCutNew->ppLeaves[i] = pCutOld->ppLeaves[i];
+ return pCutNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut )
+{
+ if ( pCut )
+ Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut )
+{
+ int i;
+ printf( "CUT: Delay = %4.2f. Area = %4.2f. Nodes = %d -> {",
+ pCut->tArrival, pCut->aFlow, pRoot->Num );
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ printf( " %d", pCut->ppLeaves[i]->Num );
+ printf( " } \n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode )
+{
+ Fpga_Cut_t * pCut;
+ pCut = Fpga_CutAlloc( p );
+ pCut->pRoot = pNode;
+ pCut->nLeaves = 1;
+ pCut->ppLeaves[0] = pNode;
+ pCut->uSign = FPGA_SEQ_SIGN(pCut->ppLeaves[0]);
+ return pCut;
+}
+
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut )
+{
+ return p->pLutLib->pLutAreas[pCut->nLeaves];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets )
+{
+ Fpga_Cut_t * pPrev, * pTemp;
+ if ( pSetAll == NULL )
+ return pSets;
+ if ( pSets == NULL )
+ return pSetAll;
+ // find the last one
+ for ( pTemp = pSets; pTemp; pTemp = pTemp->pNext )
+ pPrev = pTemp;
+ // append all the end of the current set
+ assert( pPrev->pNext == NULL );
+ pPrev->pNext = pSetAll;
+ return pSets;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave )
+{
+ Fpga_Cut_t * pNext, * pTemp;
+ for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL;
+ pTemp;
+ pTemp = pNext, pNext = pNext? pNext->pNext : NULL )
+ if ( pTemp != pSave )
+ Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutListCount( Fpga_Cut_t * pSets )
+{
+ Fpga_Cut_t * pTemp;
+ int i;
+ for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ );
+ return i;
+}
+
+#if 0
+
+/**function*************************************************************
+
+ synopsis [Removes the fanouts of the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut )
+{
+ Fpga_NodeVec_t * vFanouts;
+ int i, k;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ vFanouts = pCut->ppLeaves[i]->vFanouts;
+ for ( k = 0; k < vFanouts->nSize; k++ )
+ if ( vFanouts->pArray[k] == pNode )
+ break;
+ assert( k != vFanouts->nSize );
+ for ( k++; k < vFanouts->nSize; k++ )
+ vFanouts->pArray[k-1] = vFanouts->pArray[k];
+ vFanouts->nSize--;
+ }
+}
+
+/**function*************************************************************
+
+ synopsis [Removes the fanouts of the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut )
+{
+ int i;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ Fpga_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode );
+}
+#endif
+
+/**Function*************************************************************
+
+ Synopsis [Computes the arrival time and the area flow of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+ Fpga_Cut_t * pFaninCut;
+ int i;
+ pCut->tArrival = -FPGA_FLOAT_LARGE;
+ pCut->aFlow = pMan->pLutLib->pLutAreas[pCut->nLeaves];
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pFaninCut = pCut->ppLeaves[i]->pCutBest;
+ if ( pCut->tArrival < pFaninCut->tArrival )
+ pCut->tArrival = pFaninCut->tArrival;
+ // if the fanout count is not set, assume it to be 1
+ if ( pCut->ppLeaves[i]->nRefs == 0 )
+ pCut->aFlow += pFaninCut->aFlow;
+ else
+// pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->nRefs;
+ pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->aEstFanouts;
+ }
+ pCut->tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves];
+}
+
+
+/**function*************************************************************
+
+ synopsis [Computes the area flow of the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+ Fpga_Cut_t * pCutFanin;
+ int i;
+ pCut->aFlow = pMan->pLutLib->pLutAreas[pCut->nLeaves];
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ // get the cut implementing this phase of the fanin
+ pCutFanin = pCut->ppLeaves[i]->pCutBest;
+ assert( pCutFanin );
+ pCut->aFlow += pCutFanin->aFlow / pCut->ppLeaves[i]->nRefs;
+ }
+ return pCut->aFlow;
+}
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+ float aResult, aResult2;
+ if ( pCut->nLeaves == 1 )
+ return 0;
+ aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 );
+ aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 );
+ assert( aResult == aResult2 );
+ return aResult;
+}
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+ float aResult, aResult2;
+ if ( pCut->nLeaves == 1 )
+ return 0;
+ aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 );
+ aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 );
+ assert( aResult == aResult2 );
+ return aResult;
+}
+
+/**function*************************************************************
+
+ synopsis [References the cut.]
+
+ description [This procedure is similar to the procedure NodeReclaim.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts )
+{
+ Fpga_Node_t * pNodeChild;
+ float aArea;
+ int i;
+
+ // deref the fanouts
+// if ( fFanouts )
+// Fpga_CutInsertFanouts( pMan, pNode, pCut );
+
+ // start the area of this cut
+ aArea = pMan->pLutLib->pLutAreas[pCut->nLeaves];
+ // go through the children
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pNodeChild = pCut->ppLeaves[i];
+ assert( pNodeChild->nRefs >= 0 );
+ if ( pNodeChild->nRefs++ > 0 )
+ continue;
+ if ( !Fpga_NodeIsAnd(pNodeChild) )
+ continue;
+ aArea += Fpga_CutRef( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts );
+ }
+ return aArea;
+}
+
+/**function*************************************************************
+
+ synopsis [Dereferences the cut.]
+
+ description [This procedure is similar to the procedure NodeRecusiveDeref.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts )
+{
+ Fpga_Node_t * pNodeChild;
+ float aArea;
+ int i;
+
+ // deref the fanouts
+// if ( fFanouts )
+// Fpga_CutRemoveFanouts( pMan, pNode, pCut );
+
+ // start the area of this cut
+ aArea = pMan->pLutLib->pLutAreas[pCut->nLeaves];
+ // go through the children
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pNodeChild = pCut->ppLeaves[i];
+ assert( pNodeChild->nRefs > 0 );
+ if ( --pNodeChild->nRefs > 0 )
+ continue;
+ if ( !Fpga_NodeIsAnd(pNodeChild) )
+ continue;
+ aArea += Fpga_CutDeref( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts );
+ }
+ return aArea;
+}
+
+
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut )
+{
+ float aResult, aResult2;
+ if ( pCut->nLeaves == 1 )
+ return 0;
+ aResult2 = Fpga_CutRefSwitch( pMan, pNode, pCut, 0 );
+ aResult = Fpga_CutDerefSwitch( pMan, pNode, pCut, 0 );
+// assert( aResult == aResult2 );
+ return aResult;
+}
+
+/**function*************************************************************
+
+ synopsis [References the cut.]
+
+ description [This procedure is similar to the procedure NodeReclaim.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts )
+{
+ Fpga_Node_t * pNodeChild;
+ float aArea;
+ int i;
+
+ // deref the fanouts
+// if ( fFanouts )
+// Fpga_CutInsertFanouts( pMan, pNode, pCut );
+
+ // start the area of this cut
+ aArea = pNode->SwitchProb;
+ // go through the children
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pNodeChild = pCut->ppLeaves[i];
+ assert( pNodeChild->nRefs >= 0 );
+ if ( pNodeChild->nRefs++ > 0 )
+ continue;
+ if ( !Fpga_NodeIsAnd(pNodeChild) )
+ {
+ aArea += pNodeChild->SwitchProb;
+ continue;
+ }
+ aArea += Fpga_CutRefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts );
+ }
+ return aArea;
+}
+
+/**function*************************************************************
+
+ synopsis [Dereferences the cut.]
+
+ description [This procedure is similar to the procedure NodeRecusiveDeref.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts )
+{
+ Fpga_Node_t * pNodeChild;
+ float aArea;
+ int i;
+
+ // deref the fanouts
+// if ( fFanouts )
+// Fpga_CutRemoveFanouts( pMan, pNode, pCut );
+
+ // start the area of this cut
+ aArea = pNode->SwitchProb;
+ // go through the children
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pNodeChild = pCut->ppLeaves[i];
+ assert( pNodeChild->nRefs > 0 );
+ if ( --pNodeChild->nRefs > 0 )
+ continue;
+ if ( !Fpga_NodeIsAnd(pNodeChild) )
+ {
+ aArea += pNodeChild->SwitchProb;
+ continue;
+ }
+ aArea += Fpga_CutDerefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts );
+ }
+ return aArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the used cuts to be the currently selected ones.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingSetUsedCuts( Fpga_Man_t * pMan )
+{
+ int i;
+ for ( i = 0; i < pMan->vNodesAll->nSize; i++ )
+ if ( pMan->vNodesAll->pArray[i]->pCutOld )
+ {
+ pMan->vNodesAll->pArray[i]->pCutBest = pMan->vNodesAll->pArray[i]->pCutOld;
+ pMan->vNodesAll->pArray[i]->pCutOld = NULL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/fpga/fpgaFanout.c b/src/map/fpga/fpgaFanout.c
new file mode 100644
index 00000000..50809f65
--- /dev/null
+++ b/src/map/fpga/fpgaFanout.c
@@ -0,0 +1,139 @@
+/**CFile****************************************************************
+
+ FileName [fpgaFanout.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaFanout.c,v 1.1 2005/01/23 06:59:41 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Add the fanout to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout )
+{
+ Fpga_Node_t * pPivot;
+
+ // pFanins is a fanin of pFanout
+ assert( !Fpga_IsComplement(pFanin) );
+ assert( !Fpga_IsComplement(pFanout) );
+ assert( Fpga_Regular(pFanout->p1) == pFanin || Fpga_Regular(pFanout->p2) == pFanin );
+
+ pPivot = pFanin->pFanPivot;
+ if ( pPivot == NULL )
+ {
+ pFanin->pFanPivot = pFanout;
+ return;
+ }
+
+ if ( Fpga_Regular(pPivot->p1) == pFanin )
+ {
+ if ( Fpga_Regular(pFanout->p1) == pFanin )
+ {
+ pFanout->pFanFanin1 = pPivot->pFanFanin1;
+ pPivot->pFanFanin1 = pFanout;
+ }
+ else // if ( Fpga_Regular(pFanout->p2) == pFanin )
+ {
+ pFanout->pFanFanin2 = pPivot->pFanFanin1;
+ pPivot->pFanFanin1 = pFanout;
+ }
+ }
+ else // if ( Fpga_Regular(pPivot->p2) == pFanin )
+ {
+ assert( Fpga_Regular(pPivot->p2) == pFanin );
+ if ( Fpga_Regular(pFanout->p1) == pFanin )
+ {
+ pFanout->pFanFanin1 = pPivot->pFanFanin2;
+ pPivot->pFanFanin2 = pFanout;
+ }
+ else // if ( Fpga_Regular(pFanout->p2) == pFanin )
+ {
+ pFanout->pFanFanin2 = pPivot->pFanFanin2;
+ pPivot->pFanFanin2 = pFanout;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the fanout to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove )
+{
+ Fpga_Node_t * pFanout, * pFanout2, ** ppFanList;
+ // start the linked list of fanouts
+ ppFanList = &pFanin->pFanPivot;
+ // go through the fanouts
+ Fpga_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 )
+ {
+ // skip the fanout-to-remove
+ if ( pFanout == pFanoutToRemove )
+ continue;
+ // add useful fanouts to the list
+ *ppFanList = pFanout;
+ ppFanList = Fpga_NodeReadNextFanoutPlace( pFanin, pFanout );
+ }
+ *ppFanList = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of fanouts of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode )
+{
+ Fpga_Node_t * pFanout;
+ int Counter = 0;
+ Fpga_NodeForEachFanout( pNode, pFanout )
+ Counter++;
+ return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/fpga/fpgaGENERIC.c b/src/map/fpga/fpgaGENERIC.c
new file mode 100644
index 00000000..f272c1b8
--- /dev/null
+++ b/src/map/fpga/fpgaGENERIC.c
@@ -0,0 +1,46 @@
+/**CFile****************************************************************
+
+ FileName [fpga__.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: fpga__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/fpga/fpgaInt.h b/src/map/fpga/fpgaInt.h
new file mode 100644
index 00000000..0fea9ec8
--- /dev/null
+++ b/src/map/fpga/fpgaInt.h
@@ -0,0 +1,395 @@
+/**CFile****************************************************************
+
+ FileName [fpgaInt.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $]
+
+***********************************************************************/
+
+#ifndef __FPGA_INT_H__
+#define __FPGA_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+//#include "leaks.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "extra.h"
+#include "fraig.h"
+#include "fpga.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#ifdef _WIN32
+#define inline __inline // compatible with MS VS 6.0
+#endif
+
+// the maximum number of cut leaves (currently does not work for 7)
+#define FPGA_MAX_LEAVES 6
+
+// the bit masks
+#define FPGA_MASK(n) ((~((unsigned)0)) >> (32-(n)))
+#define FPGA_FULL (~((unsigned)0))
+#define FPGA_NO_VAR (-9999.0)
+#define FPGA_NUM_BYTES(n) (((n)/16 + (((n)%16) > 0))*16)
+
+// maximum/minimum operators
+#define FPGA_MIN(a,b) (((a) < (b))? (a) : (b))
+#define FPGA_MAX(a,b) (((a) > (b))? (a) : (b))
+
+// the small and large numbers (min/max float are 1.17e-38/3.40e+38)
+#define FPGA_FLOAT_LARGE ((float)1.0e+20)
+#define FPGA_FLOAT_SMALL ((float)1.0e-20)
+#define FPGA_INT_LARGE (10000000)
+
+// the macro to compute the signature
+#define FPGA_SEQ_SIGN(p) (1 << (((unsigned)p)%31));
+
+// internal macros to work with cuts
+#define Fpga_CutIsComplement(p) (((int)((long) (p) & 01)))
+#define Fpga_CutRegular(p) ((Fpga_Cut_t *)((unsigned)(p) & ~01))
+#define Fpga_CutNot(p) ((Fpga_Cut_t *)((long)(p) ^ 01))
+#define Fpga_CutNotCond(p,c) ((Fpga_Cut_t *)((long)(p) ^ (c)))
+
+// the cut nodes
+#define Fpga_SeqIsComplement( p ) (((int)((long) (p) & 01)))
+#define Fpga_SeqRegular( p ) ((Fpga_Node_t *)((unsigned)(p) & ~015))
+#define Fpga_SeqIndex( p ) ((((unsigned)(p)) >> 1) & 07)
+#define Fpga_SeqIndexCreate( p, Ind ) (((unsigned)(p)) | (1 << (((unsigned)(Ind)) & 07)))
+
+// internal macros for referencing of nodes
+#define Fpga_NodeReadRef(p) ((Fpga_Regular(p))->nRefs)
+#define Fpga_NodeRef(p) ((Fpga_Regular(p))->nRefs++)
+
+// returns the complemented attribute of the node
+#define Fpga_NodeIsSimComplement(p) (Fpga_IsComplement(p)? !(Fpga_Regular(p)->fInv) : (p)->fInv)
+
+// generating random unsigned (#define RAND_MAX 0x7fff)
+#define FPGA_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+// outputs the runtime in seconds
+#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the mapping manager
+struct Fpga_ManStruct_t_
+{
+ // the mapping graph
+ Fpga_Node_t ** pBins; // the table of nodes hashed by their children
+ int nBins; // the size of the table
+ Fpga_Node_t ** pInputs; // the array of inputs
+ int nInputs; // the number of inputs
+ Fpga_Node_t ** pOutputs; // the array of outputs
+ int nOutputs; // the number of outputs
+ int nNodes; // the total number of nodes
+ Fpga_Node_t * pConst1; // the constant 1 node
+ Fpga_NodeVec_t * vAnds; // the array of pointer to nodes by number
+ Fpga_NodeVec_t * vNodesAll; // the array of pointer to nodes by number
+ int nLatches; // the number of latches in the circuit
+
+ // info about the original circuit
+ char * pFileName; // the file name
+ char ** ppOutputNames; // the primary output names
+ float * pInputArrivals;// the PI arrival times
+
+ // mapping parameters
+ int nVarsMax; // the max number of variables
+ int fTree; // the flag to enable tree mapping
+ int fPower; // the flag to enable power optimization
+ int fAreaRecovery; // the flag to use area flow as the first parameter
+ int fVerbose; // the verbosiness flag
+ int fRefCount; // enables reference counting
+ int fSequential; // use sequential mapping
+ int nTravIds;
+
+ // support of choice nodes
+ int nChoiceNodes; // the number of choice nodes
+ int nChoices; // the number of all choices
+
+ int nCanons;
+ int nMatches;
+
+ // the supergate library
+ Fpga_LutLib_t * pLutLib; // the current LUT library
+ unsigned uTruths[6][2]; // the elementary truth tables
+
+ // the memory managers
+ Extra_MmFixed_t * mmNodes; // the memory manager for nodes
+ Extra_MmFixed_t * mmCuts; // the memory manager for cuts
+
+ // simulation info from the FRAIG manager
+ int nSimRounds; // the number of words in the simulation info
+ unsigned ** pSimInfo; // the simulation info for each PI
+
+ // resynthesis parameters
+ int fResynthesis; // the resynthesis flag
+ float fRequiredGlo; // the global required times
+ float fRequiredShift;// the shift of the required times
+ float fRequiredStart;// the starting global required times
+ float fRequiredGain; // the reduction in delay
+ float fAreaGlo; // the total area
+ float fAreaGain; // the reduction in area
+ float fEpsilon; // the epsilon used to compare floats
+ float fDelayWindow; // the delay window for delay-oriented resynthesis
+ float DelayLimit; // for resynthesis
+ float AreaLimit; // for resynthesis
+ float TimeLimit; // for resynthesis
+
+ // runtime statistics
+ int timeToMap; // time to transfer to the mapping structure
+ int timeCuts; // time to compute k-feasible cuts
+ int timeTruth; // time to compute the truth table for each cut
+ int timeMatch; // time to perform matching for each node
+ int timeRecover; // time to perform area recovery
+ int timeToNet; // time to transfer back to the network
+ int timeTotal; // the total mapping time
+ int time1; // time to transfer to the mapping structure
+ int time2; // time to transfer to the mapping structure
+};
+
+// the LUT library
+struct Fpga_LutLibStruct_t_
+{
+ char * pName; // the name of the LUT library
+ int LutMax; // the maximum LUT size
+ float pLutAreas[FPGA_MAX_LUTSIZE+1]; // the areas of LUTs
+ float pLutDelays[FPGA_MAX_LUTSIZE+1];// the delays of LUTs
+};
+
+// the mapping node
+struct Fpga_NodeStruct_t_
+{
+ // general information about the node
+ Fpga_Node_t * pNext; // the next node in the hash table
+ Fpga_Node_t * pLevel; // the next node in the linked list by level
+ int Num; // the unique number of this node
+ int NumA; // the unique number of this node
+ short Num2; // the temporary number of this node
+ short nRefs; // the number of references (fanouts) of the given node
+ unsigned fMark0 : 1; // the mark used for traversals
+ unsigned fMark1 : 1; // the mark used for traversals
+ unsigned fInv : 1; // the complemented attribute for the equivalent nodes
+ unsigned Value : 2; // the value of the nodes
+ unsigned fUsed : 1; // the flag indicating that the node is used in the mapping
+ unsigned fTemp : 1; // unused
+ unsigned Level :11; // the level of the given node
+ unsigned uData :14; // used to mark the fanins, for which resynthesis was tried
+ int TravId;
+
+ // the successors of this node
+ Fpga_Node_t * p1; // the first child
+ Fpga_Node_t * p2; // the second child
+ Fpga_Node_t * pNextE; // the next functionally equivalent node
+ Fpga_Node_t * pRepr; // the representative of the functionally equivalent class
+// Fpga_NodeVec_t * vFanouts; // the array of fanouts of the node
+
+ // representation of node's fanouts
+ Fpga_Node_t * pFanPivot; // the first fanout of this node
+ Fpga_Node_t * pFanFanin1; // the next fanout of p1
+ Fpga_Node_t * pFanFanin2; // the next fanout of p2
+
+ // the delay information
+ float tRequired; // the best area flow
+ float aEstFanouts; // the fanout estimation
+ float SwitchProb; // the probability of switching
+ int LValue; // the l-value of the node
+ short nLatches1; // the number of latches on the first edge
+ short nLatches2; // the number of latches on the second edge
+
+ // cut information
+ Fpga_Cut_t * pCutBest; // the best mapping
+ Fpga_Cut_t * pCutOld; // the old mapping
+ Fpga_Cut_t * pCuts; // mapping choices for the node (elementary comes first)
+ Fpga_Cut_t * pCutsN; // mapping choices for the node (elementary comes first)
+
+ // misc information
+ char * pData0; // temporary storage for the corresponding network node
+};
+
+// the cuts used for matching
+struct Fpga_CutStruct_t_
+{
+ Fpga_Cut_t * pOne; // the father of this cut
+ Fpga_Cut_t * pTwo; // the mother of this cut
+ Fpga_Node_t * pRoot; // the root of the cut
+ Fpga_Node_t * ppLeaves[FPGA_MAX_LEAVES+1]; // the leaves of this cut
+ float fLevel; // the average level of the fanins
+ unsigned uSign; // signature for quick comparison
+ char fMark; // the mark to denote visited cut
+ char Phase; // the mark to denote complemented cut
+ char nLeaves; // the number of leaves of this cut
+ char nVolume; // the volume of this cut
+ float tArrival; // the arrival time
+ float aFlow; // the area flow of the cut
+ Fpga_Cut_t * pNext; // the pointer to the next cut in the list
+};
+
+// the vector of nodes
+struct Fpga_NodeVecStruct_t_
+{
+ Fpga_Node_t ** pArray; // the array of nodes
+ int nSize; // the number of entries in the array
+ int nCap; // the number of allocated entries
+};
+
+// getting hold of the next fanout of the node
+#define Fpga_NodeReadNextFanout( pNode, pFanout ) \
+ ( ( pFanout == NULL )? NULL : \
+ ((Fpga_Regular((pFanout)->p1) == (pNode))? \
+ (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) )
+
+// getting hold of the place where the next fanout will be attached
+#define Fpga_NodeReadNextFanoutPlace( pNode, pFanout ) \
+ ( (Fpga_Regular((pFanout)->p1) == (pNode))? \
+ &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 )
+
+// iterator through the fanouts of the node
+#define Fpga_NodeForEachFanout( pNode, pFanout ) \
+ for ( pFanout = (pNode)->pFanPivot; pFanout; \
+ pFanout = Fpga_NodeReadNextFanout(pNode, pFanout) )
+
+// safe iterator through the fanouts of the node
+#define Fpga_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \
+ for ( pFanout = (pNode)->pFanPivot, \
+ pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout); \
+ pFanout; \
+ pFanout = pFanout2, \
+ pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout) )
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fpgaCut.c ===============================================================*/
+extern void Fpga_MappingCuts( Fpga_Man_t * p );
+extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p );
+extern int Fpga_CutCountAll( Fpga_Man_t * pMan );
+/*=== fpgaCutUtils.c ===============================================================*/
+extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p );
+extern Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld );
+extern void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut );
+extern void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut );
+extern Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode );
+extern float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut );
+extern Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets );
+extern void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave );
+extern int Fpga_CutListCount( Fpga_Cut_t * pSets );
+extern void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut );
+extern void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut );
+extern float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts );
+extern float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts );
+extern float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut );
+extern float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts );
+extern float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts );
+extern float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+/*=== fraigFanout.c =============================================================*/
+extern void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout );
+extern void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove );
+extern int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode );
+/*=== fpgaLib.c ============================================================*/
+extern Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose );
+extern void Fpga_LutLibFree( Fpga_LutLib_t * p );
+extern void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib );
+extern int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib );
+/*=== fpgaMatch.c ===============================================================*/
+extern int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented );
+extern int Fpga_MappingMatchesArea( Fpga_Man_t * p );
+extern int Fpga_MappingMatchesSwitch( Fpga_Man_t * p );
+/*=== fpgaShow.c =============================================================*/
+extern void Fpga_MappingShow( Fpga_Man_t * pMan, char * pFileName );
+extern void Fpga_MappingShowNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppRoots, int nRoots, char * pFileName );
+/*=== fpgaTime.c ===============================================================*/
+extern float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut );
+extern float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p );
+extern void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p );
+extern void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired );
+extern void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes );
+/*=== fpgaTruth.c ===============================================================*/
+extern void Fpga_MappingTruths( Fpga_Man_t * pMan );
+/*=== fpgaVec.c =============================================================*/
+extern Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap );
+extern void Fpga_NodeVecFree( Fpga_NodeVec_t * p );
+extern Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p );
+extern int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p );
+extern void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin );
+extern void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew );
+extern void Fpga_NodeVecClear( Fpga_NodeVec_t * p );
+extern void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry );
+extern int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry );
+extern Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p );
+extern void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry );
+extern Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i );
+extern void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p );
+extern void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p );
+extern void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 );
+extern void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing );
+extern void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes );
+
+/*=== fpgaUtils.c ===============================================================*/
+extern Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv );
+extern Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv );
+extern Fpga_NodeVec_t * Fpga_MappingDfsCutsNode( Fpga_Man_t * pMan, Fpga_Node_t * pNode );
+//extern Sat_IntVec_t * Fpga_MappingDfsNodesSat( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes );
+extern Fpga_NodeVec_t * Fpga_MappingDfsCuts( Fpga_Man_t * pMan );
+extern int Fpga_CountLevels( Fpga_Man_t * pMan );
+extern int Fpga_CountLevelsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppRoots, int nRoots );
+extern void Fpga_MappingMarkUsed( Fpga_Man_t * pMan );
+extern float Fpga_MappingGetAreaFlow( Fpga_Man_t * p );
+extern float Fpga_MappingArea( Fpga_Man_t * pMan );
+extern float Fpga_MappingComputeCutAreas( Fpga_Man_t * pMan );
+extern float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan );
+extern int Fpga_MappingCountLevels( Fpga_Man_t * pMan );
+extern void Fpga_MappingUnmark( Fpga_Man_t * pMan );
+extern void Fpga_MappingUnmark_rec( Fpga_Node_t * pNode );
+extern void Fpga_MappingMark_rec( Fpga_Node_t * pNode );
+extern void Fpga_MappedMark_rec( Fpga_Node_t * pNode );
+extern void Fpga_MappedUnmark_rec( Fpga_Node_t * pNode );
+extern void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p );
+extern void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] );
+extern void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax );
+extern void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing );
+extern Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels );
+extern Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes );
+extern float Fpga_MappingPrintSwitching( Fpga_Man_t * pMan );
+extern int Fpga_GetMaxLevel( Fpga_Man_t * pMan );
+extern void Fpga_ManReportChoices( Fpga_Man_t * pMan );
+extern void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan );
+
+/*=== CUDD package.c ===============================================================*/
+extern unsigned int Cudd_Prime( unsigned int p );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/map/fpga/fpgaLib.c b/src/map/fpga/fpgaLib.c
new file mode 100644
index 00000000..9fd8e281
--- /dev/null
+++ b/src/map/fpga/fpgaLib.c
@@ -0,0 +1,183 @@
+/**CFile****************************************************************
+
+ FileName [fpgaLib.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaLib.c,v 1.4 2005/01/23 06:59:41 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the description of LUTs from the LUT library file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose )
+{
+ char pBuffer[1000], * pToken;
+ Fpga_LutLib_t * p;
+ FILE * pFile;
+ int i;
+
+ pFile = fopen( FileName, "r" );
+ if ( pFile == NULL )
+ {
+ printf( "Cannot open LUT library file \"%s\".\n", FileName );
+ return NULL;
+ }
+
+ p = ALLOC( Fpga_LutLib_t, 1 );
+ memset( p, 0, sizeof(Fpga_LutLib_t) );
+ p->pName = util_strsav( FileName );
+
+ i = 1;
+ while ( fgets( pBuffer, 1000, pFile ) != NULL )
+ {
+ pToken = strtok( pBuffer, " \t\n" );
+ if ( pToken == NULL )
+ continue;
+ if ( pToken[0] == '#' )
+ continue;
+ if ( i != atoi(pToken) )
+ {
+ printf( "Error in the LUT library file \"%s\".\n", FileName );
+ free( p );
+ return NULL;
+ }
+
+ pToken = strtok( NULL, " \t\n" );
+ p->pLutAreas[i] = (float)atof(pToken);
+
+ pToken = strtok( NULL, " \t\n" );
+ p->pLutDelays[i] = (float)atof(pToken);
+
+ if ( i == FPGA_MAX_LUTSIZE )
+ {
+ printf( "Skipping LUTs of size more than %d.\n", i );
+ break;
+ }
+ i++;
+ }
+ p->LutMax = i-1;
+ if ( p->LutMax > FPGA_MAX_LEAVES )
+ {
+ p->LutMax = FPGA_MAX_LEAVES;
+ printf( "Warning: LUTs with more than %d input will not be used.\n", FPGA_MAX_LEAVES );
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the LUT library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p )
+{
+ Fpga_LutLib_t * pNew;
+ pNew = ALLOC( Fpga_LutLib_t, 1 );
+ *pNew = *p;
+ pNew->pName = util_strsav( pNew->pName );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the LUT library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_LutLibFree( Fpga_LutLib_t * pLutLib )
+{
+ if ( pLutLib == NULL )
+ return;
+ FREE( pLutLib->pName );
+ FREE( pLutLib );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the LUT library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib )
+{
+ int i;
+ printf( "# The area/delay of k-variable LUTs:\n" );
+ printf( "# k area delay\n" );
+ for ( i = 1; i <= pLutLib->LutMax; i++ )
+ printf( "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the delays are discrete.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib )
+{
+ float Delay;
+ int i;
+ for ( i = 1; i <= pLutLib->LutMax; i++ )
+ {
+ Delay = pLutLib->pLutDelays[i];
+ if ( ((float)((int)Delay)) != Delay )
+ return 0;
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/fpga/fpgaMatch.c b/src/map/fpga/fpgaMatch.c
new file mode 100644
index 00000000..8668ce4b
--- /dev/null
+++ b/src/map/fpga/fpgaMatch.c
@@ -0,0 +1,729 @@
+/**CFile****************************************************************
+
+ FileName [fpgaMatch.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented );
+static int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode );
+static int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode );
+
+static Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pFanout, Fpga_Node_t * pNodeNo );
+static int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Finds the best delay assignment of LUTs.]
+
+ Description [This procedure iterates through all the nodes
+ of the object graph reachable from the POs and assigns the best
+ match to each of them. If the flag fDelayOriented is set to 1, it
+ tries to minimize the arrival time and uses the area flow as a
+ tie-breaker. If the flag is set to 0, it considers all the cuts,
+ whose arrival times matches the required time at the node, and
+ minimizes the area flow using the arrival time as a tie-breaker.
+
+ Before this procedure is called, the required times should be set
+ and the fanout counts should be computed. In the first iteration,
+ the required times are set to very large number (by NodeCreate)
+ and the fanout counts are set to the number of fanouts in the AIG.
+ In the following iterations, the required times are set by the
+ backward traversal, while the fanouts are estimated approximately.
+
+ If the arrival times of the PI nodes are given, they should be
+ assigned to the PIs after the cuts are computed and before this
+ procedure is called for the first time.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented )
+{
+ ProgressBar * pProgress;
+ Fpga_Node_t * pNode;
+ int i, nNodes;
+
+ // assign the arrival times of the PIs
+ for ( i = 0; i < p->nInputs; i++ )
+ p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i];
+
+ // match LUTs with nodes in the topological order
+ nNodes = p->vAnds->nSize;
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ // skip a secondary node
+ if ( pNode->pRepr )
+ continue;
+ // match the node
+ Fpga_MatchNode( p, pNode, fDelayOriented );
+ Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
+ }
+ Extra_ProgressBarStop( pProgress );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the best matching for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented )
+{
+ Fpga_Cut_t * pCut, * pCutBestOld;
+ int clk;
+ // make sure that at least one cut other than the trivial is present
+ if ( pNode->pCuts->pNext == NULL )
+ {
+ printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+ return 0;
+ }
+
+ // estimate the fanouts of the node
+ if ( pNode->aEstFanouts < 0 )
+ pNode->aEstFanouts = (float)pNode->nRefs;
+ else
+ pNode->aEstFanouts = (float)((2.0 * pNode->aEstFanouts + pNode->nRefs) / 3.0);
+// pNode->aEstFanouts = (float)pNode->nRefs;
+
+ pCutBestOld = pNode->pCutBest;
+ pNode->pCutBest = NULL;
+ for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+ {
+ // compute the arrival time of the cut and its area flow
+clk = clock();
+ Fpga_CutGetParameters( p, pCut );
+//p->time2 += clock() - clk;
+ // drop the cut if it does not meet the required times
+ if ( pCut->tArrival > pNode->tRequired )
+ continue;
+ // if no cut is assigned, use the current one
+ if ( pNode->pCutBest == NULL )
+ {
+ pNode->pCutBest = pCut;
+ continue;
+ }
+ // choose the best cut using one of the two criteria:
+ // (1) delay oriented mapping (first traversal), delay first, area-flow as a tie-breaker
+ // (2) area recovery (subsequent traversals), area-flow first, delay as a tie-breaker
+ if ( (fDelayOriented &&
+ (pNode->pCutBest->tArrival > pCut->tArrival ||
+ pNode->pCutBest->tArrival == pCut->tArrival && pNode->pCutBest->aFlow > pCut->aFlow)) ||
+ (!fDelayOriented &&
+ (pNode->pCutBest->aFlow > pCut->aFlow ||
+ pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival)) )
+ {
+ pNode->pCutBest = pCut;
+ }
+ }
+
+ // make sure the match is found
+ if ( pNode->pCutBest == NULL )
+ {
+ if ( pCutBestOld == NULL )
+ {
+// printf( "\nError: Could not match a node in the object graph.\n" );
+ return 0;
+ }
+ pNode->pCutBest = pCutBestOld;
+ }
+ return 1;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds the best area assignment of LUTs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingMatchesArea( Fpga_Man_t * p )
+{
+ ProgressBar * pProgress;
+ Fpga_Node_t * pNode;
+ int i, nNodes;
+
+ // assign the arrival times of the PIs
+ for ( i = 0; i < p->nInputs; i++ )
+ p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i];
+
+ // match LUTs with nodes in the topological order
+ nNodes = p->vAnds->nSize;
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ // skip a secondary node
+ if ( pNode->pRepr )
+ continue;
+ // match the node
+ Fpga_MatchNodeArea( p, pNode );
+ Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
+ }
+ Extra_ProgressBarStop( pProgress );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the best area assignment of LUTs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes )
+{
+ Fpga_Node_t * pNode;
+ int i;
+
+ // match LUTs with nodes in the topological order
+ for ( i = 0; i < vNodes->nSize; i++ )
+ {
+ pNode = vNodes->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ // skip a secondary node
+ if ( pNode->pRepr )
+ continue;
+ // match the node
+ if ( !Fpga_MatchNodeArea( p, pNode ) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the best matching for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode )
+{
+ Fpga_Cut_t * pCut, * pCutBestOld;
+ float aAreaCutBest;
+ int clk;
+ // make sure that at least one cut other than the trivial is present
+ if ( pNode->pCuts->pNext == NULL )
+ {
+ printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+ return 0;
+ }
+
+ // remember the old cut
+ pCutBestOld = pNode->pCutBest;
+ // deref the old cut
+ if ( pNode->nRefs )
+ aAreaCutBest = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 );
+
+ // search for a better cut
+ pNode->pCutBest = NULL;
+ for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+ {
+ // compute the arrival time of the cut and its area flow
+clk = clock();
+ pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut );
+//p->time2 += clock() - clk;
+ // drop the cut if it does not meet the required times
+ if ( pCut->tArrival > pNode->tRequired )
+ continue;
+ // get the area of this cut
+ pCut->aFlow = Fpga_CutGetAreaDerefed( p, pCut );
+ // if no cut is assigned, use the current one
+ if ( pNode->pCutBest == NULL )
+ {
+ pNode->pCutBest = pCut;
+ continue;
+ }
+ // choose the best cut as follows: exact area first, delay as a tie-breaker
+ if ( pNode->pCutBest->aFlow > pCut->aFlow ||
+ pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival )
+ {
+ pNode->pCutBest = pCut;
+ }
+ }
+
+ // make sure the match is found
+ if ( pNode->pCutBest == NULL )
+ {
+ pNode->pCutBest = pCutBestOld;
+ // insert the new cut
+ if ( pNode->nRefs )
+ pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 );
+// printf( "\nError: Could not match a node in the object graph.\n" );
+ return 0;
+ }
+
+ // insert the new cut
+ // make sure the area selected is not worse then the original area
+ if ( pNode->nRefs )
+ {
+ pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 );
+ assert( pNode->pCutBest->aFlow <= aAreaCutBest );
+// assert( pNode->tRequired < FPGA_FLOAT_LARGE );
+ }
+ return 1;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds the best area assignment of LUTs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingMatchesSwitch( Fpga_Man_t * p )
+{
+ ProgressBar * pProgress;
+ Fpga_Node_t * pNode;
+ int i, nNodes;
+
+ // assign the arrival times of the PIs
+ for ( i = 0; i < p->nInputs; i++ )
+ p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i];
+
+ // match LUTs with nodes in the topological order
+ nNodes = p->vAnds->nSize;
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ // skip a secondary node
+ if ( pNode->pRepr )
+ continue;
+ // match the node
+ Fpga_MatchNodeSwitch( p, pNode );
+ Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
+ }
+ Extra_ProgressBarStop( pProgress );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the best matching for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode )
+{
+ Fpga_Cut_t * pCut, * pCutBestOld;
+ float aAreaCutBest;
+ int clk;
+ // make sure that at least one cut other than the trivial is present
+ if ( pNode->pCuts->pNext == NULL )
+ {
+ printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+ return 0;
+ }
+
+ // remember the old cut
+ pCutBestOld = pNode->pCutBest;
+ // deref the old cut
+ if ( pNode->nRefs )
+ aAreaCutBest = Fpga_CutDerefSwitch( p, pNode, pNode->pCutBest, 0 );
+
+ // search for a better cut
+ pNode->pCutBest = NULL;
+ for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+ {
+ // compute the arrival time of the cut and its area flow
+clk = clock();
+ pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut );
+//p->time2 += clock() - clk;
+ // drop the cut if it does not meet the required times
+ if ( pCut->tArrival > pNode->tRequired )
+ continue;
+ // get the area of this cut
+ pCut->aFlow = Fpga_CutGetSwitchDerefed( p, pNode, pCut );
+ // if no cut is assigned, use the current one
+ if ( pNode->pCutBest == NULL )
+ {
+ pNode->pCutBest = pCut;
+ continue;
+ }
+ // choose the best cut as follows: exact area first, delay as a tie-breaker
+ if ( pNode->pCutBest->aFlow > pCut->aFlow ||
+ pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival )
+ {
+ pNode->pCutBest = pCut;
+ }
+ }
+
+ // make sure the match is found
+ if ( pNode->pCutBest == NULL )
+ {
+ pNode->pCutBest = pCutBestOld;
+ // insert the new cut
+ if ( pNode->nRefs )
+ pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 );
+// printf( "\nError: Could not match a node in the object graph.\n" );
+ return 0;
+ }
+
+ // insert the new cut
+ // make sure the area selected is not worse then the original area
+ if ( pNode->nRefs )
+ {
+ pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 );
+ assert( pNode->pCutBest->aFlow <= aAreaCutBest );
+// assert( pNode->tRequired < FPGA_FLOAT_LARGE );
+ }
+ return 1;
+}
+
+
+#if 0
+/**function*************************************************************
+
+ synopsis [References the cut.]
+
+ description [This procedure is similar to the procedure NodeReclaim.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+void Fpga_Experiment( Fpga_Man_t * p )
+{
+ int Counter[10] = {0};
+ Fpga_Node_t * pNode;
+ int i;
+
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ pNode = Fpga_Regular(p->pOutputs[i]);
+ pNode->vFanouts = NULL;
+ }
+
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ if ( pNode->vFanouts == NULL )
+ continue;
+ if ( pNode->vFanouts->nSize >= 10 )
+ continue;
+ Counter[pNode->vFanouts->nSize]++;
+ }
+
+ printf( "Fanout stats: " );
+ for ( i = 0; i < 10; i++ )
+ printf( " %d=%d", i, Counter[i] );
+ printf( "\n" );
+ printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) );
+
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ Fpga_NodeVec_t * vNodesTfo;
+ float AreaBefore;
+
+ pNode = p->vAnds->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ if ( pNode->vFanouts == NULL )
+ continue;
+ if ( pNode->vFanouts->nSize != 1 && pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 )
+ continue;
+
+// assert( pNode->nRefs > 0 );
+ if ( pNode->nRefs == 0 )
+ continue;
+
+ AreaBefore = pNode->pCutBest->aFlow;
+ pNode->pCutBest->aFlow = FPGA_FLOAT_LARGE;
+
+ Fpga_TimeComputeRequiredGlobal( p );
+
+ vNodesTfo = Fpga_CollectNodeTfo( p, pNode );
+ if ( Fpga_MappingMatchesAreaArray( p, vNodesTfo ) == 0 )
+ printf( "attempt failed\n" );
+ else
+ printf( "attempt succeeded\n" );
+ Fpga_NodeVecFree( vNodesTfo );
+
+ pNode->pCutBest->aFlow = AreaBefore;
+// break;
+ }
+ printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) );
+// printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) );
+}
+
+
+
+/**function*************************************************************
+
+ synopsis [References the cut.]
+
+ description [This procedure is similar to the procedure NodeReclaim.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+void Fpga_Experiment2( Fpga_Man_t * p )
+{
+ int Counter[10] = {0};
+ Fpga_Cut_t * ppCutsNew[10];
+ Fpga_Cut_t * ppCutsOld[10];
+ Fpga_Node_t * pFanout, * pNode;
+ float Gain, Loss, GainTotal, Area1, Area2;
+ int i, k;
+
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ pNode = Fpga_Regular(p->pOutputs[i]);
+ pNode->vFanouts = NULL;
+ }
+
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ if ( pNode->vFanouts == NULL )
+ continue;
+ if ( pNode->vFanouts->nSize >= 10 )
+ continue;
+ Counter[pNode->vFanouts->nSize]++;
+ }
+
+ printf( "Fanout stats: " );
+ for ( i = 0; i < 10; i++ )
+ printf( " %d=%d", i, Counter[i] );
+ printf( "\n" );
+ printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) );
+
+ GainTotal = 0;
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+ if ( !Fpga_NodeIsAnd( pNode ) )
+ continue;
+ if ( pNode->vFanouts == NULL )
+ continue;
+ if ( pNode->vFanouts->nSize != 2 )//&& pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 )
+ continue;
+
+ assert( pNode->nRefs > 0 );
+
+ // for all fanouts, find the best cut without this node
+ for ( k = 0; k < pNode->vFanouts->nSize; k++ )
+ {
+ pFanout = pNode->vFanouts->pArray[k];
+ ppCutsOld[k] = pFanout->pCutBest;
+ ppCutsNew[k] = Fpga_MappingAreaWithoutNode( p, pFanout, pNode );
+ if ( ppCutsNew[k] == NULL )
+ break;
+ }
+ if ( k != pNode->vFanouts->nSize )
+ {
+ printf( "Node %4d: Skipped.\n", pNode->Num );
+ continue;
+ }
+
+
+ // compute the area after replacing all the cuts
+ Gain = 0;
+ for ( k = 0; k < pNode->vFanouts->nSize; k++ )
+ {
+ pFanout = pNode->vFanouts->pArray[k];
+ // deref old cut
+ Area1 = Fpga_MatchAreaDeref( p, ppCutsOld[k] );
+ // assign new cut
+ pFanout->pCutBest = ppCutsNew[k];
+ // ref new cut
+ Area2 = Fpga_MatchAreaRef( p, ppCutsNew[k] );
+ // compute the gain
+ Gain += Area1 - Area2;
+ }
+
+ printf( "%d ", pNode->nRefs );
+
+ // undo the whole thing
+ Loss = 0;
+ for ( k = 0; k < pNode->vFanouts->nSize; k++ )
+ {
+ pFanout = pNode->vFanouts->pArray[k];
+ // deref old cut
+ Area1 = Fpga_MatchAreaDeref( p, ppCutsNew[k] );
+ // assign new cut
+ pFanout->pCutBest = ppCutsOld[k];
+ // ref new cut
+ Area2 = Fpga_MatchAreaRef( p, ppCutsOld[k] );
+ // compute the gain
+ Loss += Area2 - Area1;
+ }
+ assert( Gain == Loss );
+
+
+ printf( "Node %4d: Fanouts = %d. Cut area = %4.2f. Gain = %4.2f.\n",
+ pNode->Num, pNode->nRefs, pNode->pCutBest->aFlow, Gain );
+
+ if ( Gain > 0 )
+ GainTotal += Gain;
+ }
+ printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) );
+ printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) );
+}
+
+
+/**function*************************************************************
+
+ synopsis [Computes the loss of area when node is not allowed.]
+
+ description [Returning FPGA_FLOAT_LARGE means it does not exist.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeNo )
+{
+ Fpga_Cut_t * pCut, * pCutBestOld, * pCutRes;
+ float aAreaCutBest;
+ int i, clk;
+ // make sure that at least one cut other than the trivial is present
+ if ( pNode->pCuts->pNext == NULL )
+ {
+ printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+ return 0;
+ }
+
+ assert( pNode->nRefs > 0 );
+
+ // remember the old cut
+ pCutBestOld = pNode->pCutBest;
+ // deref the old cut
+ aAreaCutBest = Fpga_MatchAreaDeref( p, pNode->pCutBest );
+
+ // search for a better cut
+ pNode->pCutBest = NULL;
+ for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+ {
+ // compute the arrival time of the cut and its area flow
+clk = clock();
+ Fpga_MatchCutGetArrTime( p, pCut );
+//p->time2 += clock() - clk;
+ // drop the cut if it does not meet the required times
+ if ( pCut->tArrival > pNode->tRequired )
+ continue;
+
+ // skip the cut if it contains the no-node
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ if ( pCut->ppLeaves[i] == pNodeNo )
+ break;
+ if ( i != pCut->nLeaves )
+ continue;
+
+ // get the area of this cut
+ pCut->aFlow = Fpga_MatchAreaCount( p, pCut );
+ // if no cut is assigned, use the current one
+ if ( pNode->pCutBest == NULL )
+ {
+ pNode->pCutBest = pCut;
+ continue;
+ }
+ // choose the best cut as follows: exact area first, delay as a tie-breaker
+ if ( pNode->pCutBest->aFlow > pCut->aFlow ||
+ pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival )
+ {
+ pNode->pCutBest = pCut;
+ }
+ }
+
+ // make sure the match is found
+ if ( pNode->pCutBest == NULL )
+ {
+ pNode->pCutBest = pCutBestOld;
+ // insert the new cut
+ pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest );
+ return NULL;
+ }
+
+ pCutRes = pNode->pCutBest;
+ pNode->pCutBest = pCutBestOld;
+
+ // insert the new cut
+ pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest );
+
+ // make sure the area selected is not worse then the original area
+ assert( pNode->pCutBest->aFlow == aAreaCutBest );
+ assert( pNode->tRequired < FPGA_FLOAT_LARGE );
+ return pCutRes;
+}
+
+#endif
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/map/fpga/fpgaTime.c b/src/map/fpga/fpgaTime.c
new file mode 100644
index 00000000..df98faa1
--- /dev/null
+++ b/src/map/fpga/fpgaTime.c
@@ -0,0 +1,189 @@
+/**CFile****************************************************************
+
+ FileName [fpgaTime.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaTime.c,v 1.1 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the arrival times of the cut.]
+
+ Description [Computes the maximum arrival time of the cut leaves and
+ adds the delay of the LUT.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+ int i;
+ float tArrival;
+ tArrival = -FPGA_FLOAT_LARGE;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ if ( tArrival < pCut->ppLeaves[i]->pCutBest->tArrival )
+ tArrival = pCut->ppLeaves[i]->pCutBest->tArrival;
+ tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves];
+ return tArrival;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the arrival times of the cut recursively.]
+
+ Description [When computing the arrival time for the previously unused
+ cuts, their arrival time may be incorrect because their fanins have
+ incorrect arrival time. This procedure is called to fix this problem.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut )
+{
+ int i;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ if ( pCut->ppLeaves[i]->nRefs == 0 )
+ Fpga_TimeCutComputeArrival_rec( pMan, pCut->ppLeaves[i]->pCutBest );
+ return Fpga_TimeCutComputeArrival( pMan, pCut );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the maximum arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p )
+{
+ float fRequired;
+ int i;
+ // get the critical PO arrival time
+ fRequired = -FPGA_FLOAT_LARGE;
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ if ( Fpga_NodeIsConst(p->pOutputs[i]) )
+ continue;
+ fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival );
+ }
+ return fRequired;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p )
+{
+ p->fRequiredGlo = Fpga_TimeComputeArrivalMax( p );
+ Fpga_TimeComputeRequired( p, p->fRequiredGlo );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired )
+{
+ Fpga_NodeVec_t * vNodes;
+ int i;
+
+ // clean the required times and the fanout counts for all nodes
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ p->vAnds->pArray[i]->tRequired = FPGA_FLOAT_LARGE;
+
+ // set the required times for the POs
+ for ( i = 0; i < p->nOutputs; i++ )
+ Fpga_Regular(p->pOutputs[i])->tRequired = fRequired;
+
+ // collect nodes reachable from POs in the DFS order through the best cuts
+ vNodes = Fpga_MappingDfsCuts( p );
+ Fpga_TimePropagateRequired( p, vNodes );
+ Fpga_NodeVecFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times of the given nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes )
+{
+ Fpga_Node_t * pNode, * pChild;
+ float fRequired;
+ int i, k;
+
+ // sorts the nodes in the decreasing order of levels
+ Fpga_MappingSortByLevel( p, vNodes, 0 );
+ // go through the nodes in the reverse topological order
+ for ( k = 0; k < vNodes->nSize; k++ )
+ {
+ pNode = vNodes->pArray[k];
+ if ( !Fpga_NodeIsAnd(pNode) )
+ continue;
+ // get the required time for children
+ fRequired = pNode->tRequired - p->pLutLib->pLutDelays[pNode->pCutBest->nLeaves];
+ // update the required time of the children
+ for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+ {
+ pChild = pNode->pCutBest->ppLeaves[i];
+ pChild->tRequired = FPGA_MIN( pChild->tRequired, fRequired );
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/fpga/fpgaTruth.c b/src/map/fpga/fpgaTruth.c
new file mode 100644
index 00000000..17c6385c
--- /dev/null
+++ b/src/map/fpga/fpgaTruth.c
@@ -0,0 +1,107 @@
+/**CFile****************************************************************
+
+ FileName [fpgaTruth.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaTruth.c,v 1.4 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+#include "cudd.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Recursively derives the truth table for the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Fpga_TruthsCutBdd_rec( DdManager * dd, Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited )
+{
+ DdNode * bFunc, * bFunc0, * bFunc1;
+ assert( !Fpga_IsComplement(pCut) );
+ // if the cut is visited, return the result
+ if ( pCut->uSign )
+ return (DdNode *)pCut->uSign;
+ // compute the functions of the children
+ bFunc0 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pOne), vVisited ); Cudd_Ref( bFunc0 );
+ bFunc0 = Cudd_NotCond( bFunc0, Fpga_CutIsComplement(pCut->pOne) );
+ bFunc1 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pTwo), vVisited ); Cudd_Ref( bFunc1 );
+ bFunc1 = Cudd_NotCond( bFunc1, Fpga_CutIsComplement(pCut->pTwo) );
+ // get the function of the cut
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ bFunc = Cudd_NotCond( bFunc, pCut->Phase );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ assert( pCut->uSign == 0 );
+ pCut->uSign = (unsigned)bFunc;
+ // add this cut to the visited list
+ Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the truth table for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut )
+{
+ Fpga_NodeVec_t * vVisited;
+ DdNode * bFunc;
+ int i;
+ assert( pCut->nLeaves > 1 );
+ // set the leaf variables
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ pCut->ppLeaves[i]->pCuts->uSign = (unsigned)Cudd_bddIthVar( dd, i );
+ // recursively compute the function
+ vVisited = Fpga_NodeVecAlloc( 10 );
+ bFunc = Fpga_TruthsCutBdd_rec( dd, pCut, vVisited ); Cudd_Ref( bFunc );
+ // clean the intermediate BDDs
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ pCut->ppLeaves[i]->pCuts->uSign = 0;
+ for ( i = 0; i < vVisited->nSize; i++ )
+ {
+ pCut = (Fpga_Cut_t *)vVisited->pArray[i];
+ Cudd_RecursiveDeref( dd, (DdNode*)pCut->uSign );
+ pCut->uSign = 0;
+ }
+ Fpga_NodeVecFree( vVisited );
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/fpga/fpgaUtils.c b/src/map/fpga/fpgaUtils.c
new file mode 100644
index 00000000..a5b2cb32
--- /dev/null
+++ b/src/map/fpga/fpgaUtils.c
@@ -0,0 +1,1289 @@
+/**CFile****************************************************************
+
+ FileName [fpgaUtils.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaUtils.c,v 1.3 2004/07/06 04:55:58 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv );
+static void Fpga_MappingDfsCuts_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes );
+static float Fpga_MappingArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes );
+static int Fpga_MappingCountLevels_rec( Fpga_Node_t * pNode );
+static void Fpga_MappingMarkUsed_rec( Fpga_Node_t * pNode );
+static int Fpga_MappingCompareOutputDelay( int * pOut1, int * pOut2 );
+static float Fpga_MappingSetRefsAndArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode );
+static Fpga_Man_t * s_pMan = NULL;
+
+static void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes );
+static int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv )
+{
+ Fpga_NodeVec_t * vNodes;
+ Fpga_Node_t * pNode;
+ int i;
+ // start the array
+ vNodes = Fpga_NodeVecAlloc( 100 );
+ // collect the PIs
+ for ( i = 0; i < pMan->nInputs; i++ )
+ {
+ pNode = pMan->pInputs[i];
+ Fpga_NodeVecPush( vNodes, pNode );
+ pNode->fMark0 = 1;
+ }
+ // perform the traversal
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_MappingDfs_rec( Fpga_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ vNodes->pArray[i]->fMark0 = 0;
+// for ( i = 0; i < pMan->nOutputs; i++ )
+// Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv )
+{
+ assert( !Fpga_IsComplement(pNode) );
+ if ( pNode->fMark0 )
+ return;
+ // visit the transitive fanin
+ if ( Fpga_NodeIsAnd(pNode) )
+ {
+ Fpga_MappingDfs_rec( Fpga_Regular(pNode->p1), vNodes, fCollectEquiv );
+ Fpga_MappingDfs_rec( Fpga_Regular(pNode->p2), vNodes, fCollectEquiv );
+ }
+ // visit the equivalent nodes
+ if ( fCollectEquiv && pNode->pNextE )
+ Fpga_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv );
+ // make sure the node is not visited through the equivalent nodes
+ assert( pNode->fMark0 == 0 );
+ // mark the node as visited
+ pNode->fMark0 = 1;
+ // add the node to the list
+ Fpga_NodeVecPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv )
+{
+ Fpga_NodeVec_t * vNodes;
+ int i;
+ // perform the traversal
+ vNodes = Fpga_NodeVecAlloc( 200 );
+ for ( i = 0; i < nNodes; i++ )
+ Fpga_MappingDfs_rec( ppNodes[i], vNodes, fEquiv );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ vNodes->pArray[i]->fMark0 = 0;
+ return vNodes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the number of logic levels not counting PIs/POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CountLevels( Fpga_Man_t * pMan )
+{
+ int i, LevelsMax, LevelsCur;
+ // perform the traversal
+ LevelsMax = -1;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ LevelsCur = Fpga_Regular(pMan->pOutputs[i])->Level;
+ if ( LevelsMax < LevelsCur )
+ LevelsMax = LevelsCur;
+ }
+ return LevelsMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the number of logic levels not counting PIs/POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CountLevelsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppRoots, int nRoots )
+{
+ int i, LevelsMax, LevelsCur;
+ // perform the traversal
+ LevelsMax = -1;
+ for ( i = 0; i < nRoots; i++ )
+ {
+ LevelsCur = Fpga_Regular(ppRoots[i])->Level;
+ if ( LevelsMax < LevelsCur )
+ LevelsMax = LevelsCur;
+ }
+ return LevelsMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes visible in current mapping.]
+
+ Description [The node is visible if it appears as a root of one of the best
+ cuts (that is cuts selected for the current mapping).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingDfsCuts( Fpga_Man_t * pMan )
+{
+ Fpga_NodeVec_t * vNodes;
+ int i;
+ // perform the traversal
+ vNodes = Fpga_NodeVecAlloc( 100 );
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_MappingDfsCuts_rec( Fpga_Regular(pMan->pOutputs[i]), vNodes );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ vNodes->pArray[i]->fMark0 = 0;
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes visible in current mapping.]
+
+ Description [The node is visible if it appears as a root of one of the best
+ cuts (that is cuts selected for the current mapping).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingDfsCutsNode( Fpga_Man_t * pMan, Fpga_Node_t * pNode )
+{
+ Fpga_NodeVec_t * vNodes;
+ int i;
+ // perform the traversal
+ vNodes = Fpga_NodeVecAlloc( 100 );
+ Fpga_MappingDfsCuts_rec( pNode, vNodes );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ vNodes->pArray[i]->fMark0 = 0;
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingDfsCuts_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes )
+{
+ int i;
+ assert( !Fpga_IsComplement(pNode) );
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return;
+ if ( pNode->fMark0 )
+ return;
+ assert( pNode->pCutBest != NULL );
+ // visit the transitive fanin of the selected cut
+ for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+ Fpga_MappingDfsCuts_rec( pNode->pCutBest->ppLeaves[i], vNodes );
+ // make sure the node is not visited through the fanin nodes
+ assert( pNode->fMark0 == 0 );
+ // mark the node as visited
+ pNode->fMark0 = 1;
+ // add the node to the list
+ Fpga_NodeVecPush( vNodes, pNode );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks the nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingMarkUsed( Fpga_Man_t * pMan )
+{
+ int i;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_MappingMarkUsed_rec( Fpga_Regular(pMan->pOutputs[i]) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingMarkUsed_rec( Fpga_Node_t * pNode )
+{
+ int i;
+ assert( !Fpga_IsComplement(pNode) );
+ if ( pNode->fUsed )
+ return;
+ pNode->fUsed = 1;
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return;
+ assert( pNode->pCutBest != NULL );
+ // visit the transitive fanin of the selected cut
+ for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+ Fpga_MappingMarkUsed_rec( pNode->pCutBest->ppLeaves[i] );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_MappingGetAreaFlow( Fpga_Man_t * p )
+{
+ float aFlowFlowTotal = 0;
+ int i;
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ if ( Fpga_NodeIsConst(p->pOutputs[i]) )
+ continue;
+ aFlowFlowTotal += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow;
+ }
+ return aFlowFlowTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the area of the current mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_MappingArea( Fpga_Man_t * pMan )
+{
+ Fpga_NodeVec_t * vNodes;
+ float aTotal;
+ int i;
+ // perform the traversal
+ aTotal = 0;
+ vNodes = Fpga_NodeVecAlloc( 100 );
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ aTotal += Fpga_MappingArea_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), vNodes );
+ // add the area for single-input nodes (if any) at the POs
+// if ( Fpga_NodeIsVar(pMan->pOutputs[i]) || Fpga_IsComplement(pMan->pOutputs[i]) )
+// aTotal += pMan->pLutLib->pLutAreas[1];
+ }
+ for ( i = 0; i < vNodes->nSize; i++ )
+ vNodes->pArray[i]->fMark0 = 0;
+ Fpga_NodeVecFree( vNodes );
+ return aTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_MappingArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes )
+{
+ float aArea;
+ int i;
+ assert( !Fpga_IsComplement(pNode) );
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return 0;
+ if ( pNode->fMark0 )
+ return 0;
+ assert( pNode->pCutBest != NULL );
+ // visit the transitive fanin of the selected cut
+ aArea = 0;
+ for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+ aArea += Fpga_MappingArea_rec( pMan, pNode->pCutBest->ppLeaves[i], vNodes );
+ // make sure the node is not visited through the fanin nodes
+ assert( pNode->fMark0 == 0 );
+ // mark the node as visited
+ pNode->fMark0 = 1;
+ // add the node to the list
+ aArea += pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves];
+ // add the node to the list
+ Fpga_NodeVecPush( vNodes, pNode );
+ return aArea;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets the correct reference counts for the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_MappingComputeCutAreas( Fpga_Man_t * pMan )
+{
+ Fpga_NodeVec_t * vNodes;
+ Fpga_Node_t * pNode;
+ float Area = 0;
+ int i;
+ // collect nodes reachable from POs in the DFS order through the best cuts
+ vNodes = Fpga_MappingDfsCuts( pMan );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ {
+ pNode = vNodes->pArray[i];
+ pNode->pCutBest->aFlow = Fpga_CutGetAreaRefed( pMan, pNode->pCutBest );
+ Area += pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves];
+ }
+ Fpga_NodeVecFree( vNodes );
+ return Area;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the correct reference counts for the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan )
+{
+ Fpga_Node_t * pNode;
+ float aArea;
+ int i;
+ // clean all references
+ for ( i = 0; i < pMan->vNodesAll->nSize; i++ )
+ pMan->vNodesAll->pArray[i]->nRefs = 0;
+ // collect nodes reachable from POs in the DFS order through the best cuts
+ aArea = 0;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ pNode = Fpga_Regular(pMan->pOutputs[i]);
+ if ( pNode == pMan->pConst1 )
+ continue;
+ aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode );
+ pNode->nRefs++;
+ }
+ return aArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_MappingSetRefsAndArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode )
+{
+ float aArea;
+ int i;
+ assert( !Fpga_IsComplement(pNode) );
+ if ( pNode->nRefs++ )
+ return 0;
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return 0;
+ assert( pNode->pCutBest != NULL );
+ // visit the transitive fanin of the selected cut
+ aArea = pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves];
+ for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+ aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode->pCutBest->ppLeaves[i] );
+ return aArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the number of logic levels not counting PIs/POs.]
+
+ Description []
+
+ SideEffects [Note that this procedure will reassign the levels assigned
+ originally by NodeCreate() because it counts the number of levels with
+ choices differently!]
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingCountLevels( Fpga_Man_t * pMan )
+{
+ int i, LevelsMax, LevelsCur;
+ // perform the traversal
+ LevelsMax = -1;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ LevelsCur = Fpga_MappingCountLevels_rec( Fpga_Regular(pMan->pOutputs[i]) );
+ if ( LevelsMax < LevelsCur )
+ LevelsMax = LevelsCur;
+ }
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) );
+ return LevelsMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the number of logic levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingCountLevels_rec( Fpga_Node_t * pNode )
+{
+ int Level1, Level2;
+ assert( !Fpga_IsComplement(pNode) );
+ if ( !Fpga_NodeIsAnd(pNode) )
+ {
+ pNode->Level = 0;
+ return 0;
+ }
+ if ( pNode->fMark0 )
+ return pNode->Level;
+ pNode->fMark0 = 1;
+ // visit the transitive fanin
+ Level1 = Fpga_MappingCountLevels_rec( Fpga_Regular(pNode->p1) );
+ Level2 = Fpga_MappingCountLevels_rec( Fpga_Regular(pNode->p2) );
+ // set the number of levels
+ pNode->Level = 1 + ((Level1>Level2)? Level1: Level2);
+ return pNode->Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Unmarks the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingUnmark( Fpga_Man_t * pMan )
+{
+ int i;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively unmarks the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingUnmark_rec( Fpga_Node_t * pNode )
+{
+ assert( !Fpga_IsComplement(pNode) );
+ if ( pNode->fMark0 == 0 )
+ return;
+ pNode->fMark0 = 0;
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return;
+ Fpga_MappingUnmark_rec( Fpga_Regular(pNode->p1) );
+ Fpga_MappingUnmark_rec( Fpga_Regular(pNode->p2) );
+ // visit the equivalent nodes
+ if ( pNode->pNextE )
+ Fpga_MappingUnmark_rec( pNode->pNextE );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively unmarks the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingMark_rec( Fpga_Node_t * pNode )
+{
+ assert( !Fpga_IsComplement(pNode) );
+ if ( pNode->fMark0 == 1 )
+ return;
+ pNode->fMark0 = 1;
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return;
+ Fpga_MappingMark_rec( Fpga_Regular(pNode->p1) );
+ Fpga_MappingMark_rec( Fpga_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappedMark_rec( Fpga_Node_t * pNode )
+{
+ int i;
+ assert( !Fpga_IsComplement(pNode) );
+ if ( pNode->fMark0 == 1 )
+ return;
+ pNode->fMark0 = 1;
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return;
+ assert( pNode->pCutBest != NULL );
+ // visit the transitive fanin of the selected cut
+ for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+ Fpga_MappedMark_rec( pNode->pCutBest->ppLeaves[i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively unmarks the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappedUnmark_rec( Fpga_Node_t * pNode )
+{
+ int i;
+ assert( !Fpga_IsComplement(pNode) );
+ if ( pNode->fMark0 == 0 )
+ return;
+ pNode->fMark0 = 0;
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return;
+ assert( pNode->pCutBest != NULL );
+ // visit the transitive fanin of the selected cut
+ for ( i = 0; i < pNode->pCutBest->nLeaves; i++ )
+ Fpga_MappedUnmark_rec( pNode->pCutBest->ppLeaves[i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints a bunch of latest arriving outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p )
+{
+ Fpga_Node_t * pNode;
+ int fCompl, Limit, i;
+ int * pSorted;
+
+ // sort outputs by arrival time
+ s_pMan = p;
+ pSorted = ALLOC( int, p->nOutputs );
+ for ( i = 0; i < p->nOutputs; i++ )
+ pSorted[i] = i;
+ qsort( (void *)pSorted, p->nOutputs, sizeof(int),
+ (int (*)(const void *, const void *)) Fpga_MappingCompareOutputDelay );
+ assert( Fpga_MappingCompareOutputDelay( pSorted, pSorted + p->nOutputs - 1 ) <= 0 );
+ s_pMan = NULL;
+
+ // print the latest outputs
+ Limit = (p->nOutputs > 5)? 5 : p->nOutputs;
+ for ( i = 0; i < Limit; i++ )
+ {
+ // get the i-th latest output
+ pNode = Fpga_Regular(p->pOutputs[pSorted[i]]);
+ fCompl = Fpga_IsComplement(p->pOutputs[pSorted[i]]);
+ // print out the best arrival time
+ printf( "Output %20s : ", p->ppOutputNames[pSorted[i]] );
+ printf( "Delay = %8.2f ", (double)pNode->pCutBest->tArrival );
+ if ( fCompl )
+ printf( "NEG" );
+ else
+ printf( "POS" );
+ printf( "\n" );
+ }
+ free( pSorted );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the outputs by their arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingCompareOutputDelay( int * pOut1, int * pOut2 )
+{
+ Fpga_Node_t * pNode1 = Fpga_Regular(s_pMan->pOutputs[*pOut1]);
+ Fpga_Node_t * pNode2 = Fpga_Regular(s_pMan->pOutputs[*pOut2]);
+ float pTime1 = pNode1->pCutBest? pNode1->pCutBest->tArrival : 0;
+ float pTime2 = pNode2->pCutBest? pNode2->pCutBest->tArrival : 0;
+ if ( pTime1 > pTime2 )
+ return -1;
+ if ( pTime1 < pTime2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] )
+{
+ int m, v;
+ // set up the truth tables
+ for ( m = 0; m < 32; m++ )
+ for ( v = 0; v < 5; v++ )
+ if ( m & (1 << v) )
+ uTruths[v][0] |= (1 << m);
+ // make adjustments for the case of 6 variables
+ for ( v = 0; v < 5; v++ )
+ uTruths[v][1] = uTruths[v][0];
+ uTruths[5][0] = 0;
+ uTruths[5][1] = FPGA_FULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax )
+{
+ if ( nVarsMax == 6 )
+ uMask[0] = uMask[1] = FPGA_FULL;
+ else
+ {
+ uMask[0] = FPGA_MASK(1 << nVarsMax);
+ uMask[1] = 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify one useful property.]
+
+ Description [This procedure verifies one useful property. After
+ the FRAIG construction with choice nodes is over, each primary node
+ should have fanins that are primary nodes. The primary nodes is the
+ one that does not have pNode->pRepr set to point to another node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_ManCheckConsistency( Fpga_Man_t * p )
+{
+ Fpga_Node_t * pNode;
+ Fpga_NodeVec_t * pVec;
+ int i;
+ pVec = Fpga_MappingDfs( p, 0 );
+ for ( i = 0; i < pVec->nSize; i++ )
+ {
+ pNode = pVec->pArray[i];
+ if ( Fpga_NodeIsVar(pNode) )
+ {
+ if ( pNode->pRepr )
+ printf( "Primary input %d is a secondary node.\n", pNode->Num );
+ }
+ else if ( Fpga_NodeIsConst(pNode) )
+ {
+ if ( pNode->pRepr )
+ printf( "Constant 1 %d is a secondary node.\n", pNode->Num );
+ }
+ else
+ {
+ if ( pNode->pRepr )
+ printf( "Internal node %d is a secondary node.\n", pNode->Num );
+ if ( Fpga_Regular(pNode->p1)->pRepr )
+ printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num );
+ if ( Fpga_Regular(pNode->p2)->pRepr )
+ printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num );
+ }
+ }
+ Fpga_NodeVecFree( pVec );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the supergates by their level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CompareNodesByLevelDecreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 )
+{
+ if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level )
+ return -1;
+ if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the supergates by their level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CompareNodesByLevelIncreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 )
+{
+ if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level )
+ return -1;
+ if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Orders the nodes in the decreasing order of levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing )
+{
+ if ( fIncreasing )
+ qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *),
+ (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelIncreasing );
+ else
+ qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *),
+ (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelDecreasing );
+// assert( Fpga_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the limited DFS ordering for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels )
+{
+ Fpga_NodeVec_t * vNodes;
+ int i;
+ // perform the traversal
+ vNodes = Fpga_NodeVecAlloc( 100 );
+ Fpga_DfsLim_rec( pNode, nLevels, vNodes );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ vNodes->pArray[i]->fMark0 = 0;
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes )
+{
+ assert( !Fpga_IsComplement(pNode) );
+ if ( pNode->fMark0 )
+ return;
+ pNode->fMark0 = 1;
+ // visit the transitive fanin
+ Level--;
+ if ( Level > 0 && Fpga_NodeIsAnd(pNode) )
+ {
+ Fpga_DfsLim_rec( Fpga_Regular(pNode->p1), Level, vNodes );
+ Fpga_DfsLim_rec( Fpga_Regular(pNode->p2), Level, vNodes );
+ }
+ // add the node to the list
+ Fpga_NodeVecPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the limited DFS ordering for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_ManCleanData0( Fpga_Man_t * pMan )
+{
+ int i;
+ for ( i = 0; i < pMan->vNodesAll->nSize; i++ )
+ pMan->vNodesAll->pArray[i]->pData0 = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the TFO of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode )
+{
+ Fpga_NodeVec_t * vVisited, * vTfo;
+ int i;
+ // perform the traversal
+ vVisited = Fpga_NodeVecAlloc( 100 );
+ vTfo = Fpga_NodeVecAlloc( 100 );
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_CollectNodeTfo_rec( Fpga_Regular(pMan->pOutputs[i]), pNode, vVisited, vTfo );
+ for ( i = 0; i < vVisited->nSize; i++ )
+ vVisited->pArray[i]->fMark0 = vVisited->pArray[i]->fMark1 = 0;
+ Fpga_NodeVecFree( vVisited );
+ return vTfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the TFO of the node.]
+
+ Description [Returns 1 if the node should be collected.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo )
+{
+ int Ret1, Ret2;
+ assert( !Fpga_IsComplement(pNode) );
+ // skip visited nodes
+ if ( pNode->fMark0 )
+ return pNode->fMark1;
+ pNode->fMark0 = 1;
+ Fpga_NodeVecPush( vVisited, pNode );
+
+ // return the pivot node
+ if ( pNode == pPivot )
+ {
+ pNode->fMark1 = 1;
+ return 1;
+ }
+ if ( pNode->Level < pPivot->Level )
+ {
+ pNode->fMark1 = 0;
+ return 0;
+ }
+ // visit the transitive fanin
+ assert( Fpga_NodeIsAnd(pNode) );
+ Ret1 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p1), pPivot, vVisited, vTfo );
+ Ret2 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p2), pPivot, vVisited, vTfo );
+ if ( Ret1 || Ret2 )
+ {
+ pNode->fMark1 = 1;
+ Fpga_NodeVecPush( vTfo, pNode );
+ }
+ else
+ pNode->fMark1 = 0;
+ return pNode->fMark1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Levelizes the nodes accessible from the POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes )
+{
+ Fpga_NodeVec_t * vLevels;
+ Fpga_Node_t ** ppNodes;
+ Fpga_Node_t * pNode;
+ int nNodes, nLevelsMax, i;
+
+ // reassign the levels (this may be necessary for networks which choices)
+ ppNodes = vNodes->pArray;
+ nNodes = vNodes->nSize;
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = ppNodes[i];
+ if ( !Fpga_NodeIsAnd(pNode) )
+ {
+ pNode->Level = 0;
+ continue;
+ }
+ pNode->Level = 1 + FPGA_MAX( Fpga_Regular(pNode->p1)->Level, Fpga_Regular(pNode->p2)->Level );
+ }
+
+ // get the max levels
+ nLevelsMax = 0;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ nLevelsMax = FPGA_MAX( nLevelsMax, (int)Fpga_Regular(pMan->pOutputs[i])->Level );
+ nLevelsMax++;
+
+ // allocate storage for levels
+ vLevels = Fpga_NodeVecAlloc( nLevelsMax );
+ for ( i = 0; i < nLevelsMax; i++ )
+ Fpga_NodeVecPush( vLevels, NULL );
+
+ // go through the nodes and add them to the levels
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = ppNodes[i];
+ pNode->pLevel = NULL;
+ if ( !Fpga_NodeIsAnd(pNode) )
+ continue;
+ // attach the node to this level
+ pNode->pLevel = Fpga_NodeVecReadEntry( vLevels, pNode->Level );
+ Fpga_NodeVecWriteEntry( vLevels, pNode->Level, pNode );
+ }
+ return vLevels;
+}
+/**Function*************************************************************
+
+ Synopsis [Prints the switching activity changes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fpga_MappingPrintSwitching( Fpga_Man_t * p )
+{
+ Fpga_Node_t * pNode;
+ float SwitchTotal = 0.0;
+ int nNodes = 0;
+ int i;
+ for ( i = 0; i < p->vNodesAll->nSize; i++ )
+ {
+ // skip primary inputs
+ pNode = p->vNodesAll->pArray[i];
+// if ( !Fpga_NodeIsAnd( pNode ) )
+// continue;
+ // skip a secondary node
+ if ( pNode->pRepr )
+ continue;
+ // count the switching nodes
+ if ( pNode->nRefs > 0 )
+ {
+ SwitchTotal += pNode->SwitchProb;
+ nNodes++;
+ }
+ }
+ if ( p->fVerbose )
+ printf( "Total switching = %10.2f. Average switching = %6.4f.\n", SwitchTotal, SwitchTotal/nNodes );
+ return SwitchTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_GetMaxLevel( Fpga_Man_t * pMan )
+{
+ int nLevelMax, i;
+ nLevelMax = 0;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ nLevelMax = nLevelMax > (int)Fpga_Regular(pMan->pOutputs[i])->Level?
+ nLevelMax : (int)Fpga_Regular(pMan->pOutputs[i])->Level;
+ return nLevelMax;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Analyses choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_MappingUpdateLevel_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int fMaximum )
+{
+ Fpga_Node_t * pTemp;
+ int Level1, Level2, LevelE;
+ assert( !Fpga_IsComplement(pNode) );
+ if ( !Fpga_NodeIsAnd(pNode) )
+ return pNode->Level;
+ // skip the visited node
+ if ( pNode->TravId == pMan->nTravIds )
+ return pNode->Level;
+ pNode->TravId = pMan->nTravIds;
+ // compute levels of the children nodes
+ Level1 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p1), fMaximum );
+ Level2 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p2), fMaximum );
+ pNode->Level = 1 + FPGA_MAX( Level1, Level2 );
+ if ( pNode->pNextE )
+ {
+ LevelE = Fpga_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum );
+ if ( fMaximum )
+ {
+ if ( pNode->Level < (unsigned)LevelE )
+ pNode->Level = LevelE;
+ }
+ else
+ {
+ if ( pNode->Level > (unsigned)LevelE )
+ pNode->Level = LevelE;
+ }
+ // set the level of all equivalent nodes to be the same minimum
+ if ( pNode->pRepr == NULL ) // the primary node
+ for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+ pTemp->Level = pNode->Level;
+ }
+ return pNode->Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resets the levels of the nodes in the choice graph.]
+
+ Description [Makes the level of the choice nodes to be equal to the
+ maximum of the level of the nodes in the equivalence class. This way
+ sorting by level leads to the reverse topological order, which is
+ needed for the required time computation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan )
+{
+ int i;
+ pMan->nTravIds++;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports statistics on choice nodes.]
+
+ Description [The number of choice nodes is the number of primary nodes,
+ which has pNextE set to a pointer. The number of choices is the number
+ of entries in the equivalent-node lists of the primary nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_ManReportChoices( Fpga_Man_t * pMan )
+{
+ Fpga_Node_t * pNode, * pTemp;
+ int nChoiceNodes, nChoices;
+ int i, LevelMax1, LevelMax2;
+
+ // report the number of levels
+ LevelMax1 = Fpga_GetMaxLevel( pMan );
+ pMan->nTravIds++;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 0 );
+ LevelMax2 = Fpga_GetMaxLevel( pMan );
+
+ // report statistics about choices
+ nChoiceNodes = nChoices = 0;
+ for ( i = 0; i < pMan->vAnds->nSize; i++ )
+ {
+ pNode = pMan->vAnds->pArray[i];
+ if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
+ { // this is a choice node = the primary node that has equivalent nodes
+ nChoiceNodes++;
+ for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
+ nChoices++;
+ }
+ }
+ if ( pMan->fVerbose )
+ {
+ printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
+ printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
+ }
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "stats_choice.txt", "a+" );
+ fprintf( pTable, "%s ", pMan->pFileName );
+ fprintf( pTable, "%4d ", LevelMax1 );
+ fprintf( pTable, "%4d ", pMan->vAnds->nSize - pMan->nInputs );
+ fprintf( pTable, "%4d ", LevelMax2 );
+ fprintf( pTable, "%7d ", nChoiceNodes );
+ fprintf( pTable, "%7d ", nChoices + nChoiceNodes );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/fpga/fpgaVec.c b/src/map/fpga/fpgaVec.c
new file mode 100644
index 00000000..a8c6b983
--- /dev/null
+++ b/src/map/fpga/fpgaVec.c
@@ -0,0 +1,408 @@
+/**CFile****************************************************************
+
+ FileName [fpgaVec.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaVec.c,v 1.3 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap )
+{
+ Fpga_NodeVec_t * p;
+ p = ALLOC( Fpga_NodeVec_t, 1 );
+ if ( nCap > 0 && nCap < 16 )
+ nCap = 16;
+ p->nSize = 0;
+ p->nCap = nCap;
+ p->pArray = p->nCap? ALLOC( Fpga_Node_t *, p->nCap ) : NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecFree( Fpga_NodeVec_t * p )
+{
+ FREE( p->pArray );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p )
+{
+ return p->pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the vector to the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin )
+{
+ if ( p->nCap >= nCapMin )
+ return;
+ p->pArray = REALLOC( Fpga_Node_t *, p->pArray, nCapMin );
+ p->nCap = nCapMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew )
+{
+ assert( p->nSize >= nSizeNew );
+ p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecClear( Fpga_NodeVec_t * p )
+{
+ p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry )
+{
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Fpga_NodeVecGrow( p, 16 );
+ else
+ Fpga_NodeVecGrow( p, 2 * p->nCap );
+ }
+ p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the element while ensuring uniqueness.]
+
+ Description [Returns 1 if the element was found, and 0 if it was new. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return 1;
+ Fpga_NodeVecPush( p, Entry );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p )
+{
+ return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 )
+{
+ int Level1 = Fpga_Regular(*pp1)->Level;
+ int Level2 = Fpga_Regular(*pp2)->Level;
+ if ( Level1 < Level2 )
+ return -1;
+ if ( Level1 > Level2 )
+ return 1;
+ if ( Fpga_Regular(*pp1)->Num < Fpga_Regular(*pp2)->Num )
+ return -1;
+ if ( Fpga_Regular(*pp1)->Num > Fpga_Regular(*pp2)->Num )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p )
+{
+ qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *),
+ (int (*)(const void *, const void *)) Fpga_NodeVecCompareLevels );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_NodeVecCompareArrivals( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 )
+{
+ if ( (*ppS1)->pCutBest->tArrival < (*ppS2)->pCutBest->tArrival )
+ return -1;
+ if ( (*ppS1)->pCutBest->tArrival > (*ppS2)->pCutBest->tArrival )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Orders the nodes in the increasing order of the arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p )
+{
+ qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *),
+ (int (*)(const void *, const void *)) Fpga_NodeVecCompareArrivals );
+// assert( Fpga_CompareNodesByLevel( p->pArray, p->pArray + p->nSize - 1 ) <= 0 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the union of nodes in two arrays.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 )
+{
+ int i;
+ Fpga_NodeVecClear( p );
+ for ( i = 0; i < p1->nSize; i++ )
+ Fpga_NodeVecPush( p, p1->pArray[i] );
+ for ( i = 0; i < p2->nSize; i++ )
+ Fpga_NodeVecPush( p, p2->pArray[i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts a new node in the order by arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing )
+{
+ Fpga_Node_t * pNode1, * pNode2;
+ int i;
+ Fpga_NodeVecPush( vNodes, pNode );
+ // find the place of the node
+ for ( i = vNodes->nSize-1; i > 0; i-- )
+ {
+ pNode1 = vNodes->pArray[i ];
+ pNode2 = vNodes->pArray[i-1];
+ if ( fIncreasing && pNode1->pCutBest->tArrival >= pNode2->pCutBest->tArrival ||
+ !fIncreasing && pNode1->pCutBest->tArrival <= pNode2->pCutBest->tArrival )
+ break;
+ vNodes->pArray[i ] = pNode2;
+ vNodes->pArray[i-1] = pNode1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts a new node in the order by arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes )
+{
+ Fpga_Node_t * pNode1, * pNode2;
+ int i;
+ for ( i = 0; i < vNodes->nSize/2; i++ )
+ {
+ pNode1 = vNodes->pArray[i];
+ pNode2 = vNodes->pArray[vNodes->nSize-1-i];
+ vNodes->pArray[i] = pNode2;
+ vNodes->pArray[vNodes->nSize-1-i] = pNode1;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/fpga/module.make b/src/map/fpga/module.make
new file mode 100644
index 00000000..409e4b54
--- /dev/null
+++ b/src/map/fpga/module.make
@@ -0,0 +1,12 @@
+SRC += src/map/fpga/fpga.c \
+ src/map/fpga/fpgaCore.c \
+ src/map/fpga/fpgaCreate.c \
+ src/map/fpga/fpgaCut.c \
+ src/map/fpga/fpgaCutUtils.c \
+ src/map/fpga/fpgaFanout.c \
+ src/map/fpga/fpgaLib.c \
+ src/map/fpga/fpgaMatch.c \
+ src/map/fpga/fpgaTime.c \
+ src/map/fpga/fpgaTruth.c \
+ src/map/fpga/fpgaUtils.c \
+ src/map/fpga/fpgaVec.c
diff --git a/src/map/mapper/mapper.c b/src/map/mapper/mapper.c
new file mode 100644
index 00000000..546186a2
--- /dev/null
+++ b/src/map/mapper/mapper.c
@@ -0,0 +1,176 @@
+/**CFile****************************************************************
+
+ FileName [mapper.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Command file for the mapper package.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapper.c,v 1.7 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "mainInt.h"
+#include "mio.h"
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Map_CommandReadLibrary ( Abc_Frame_t * pAbc, int argc, char **argv );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_Init( Abc_Frame_t * pAbc )
+{
+ Cmd_CommandAdd( pAbc, "SC mapping", "read_super", Map_CommandReadLibrary, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_End()
+{
+// Map_SuperLibFree( s_pSuperLib );
+ Map_SuperLibFree( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pFile;
+ FILE * pOut, * pErr;
+ Map_SuperLib_t * pLib;
+ Abc_Ntk_t * pNet;
+ char * FileName, * ExcludeFile;
+ int fVerbose;
+ int fAlgorithm;
+ int c;
+
+ pNet = Abc_FrameReadNet(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fVerbose = 1;
+ fAlgorithm = 1;
+ ExcludeFile = 0;
+ util_getopt_reset();
+ while ( (c = util_getopt(argc, argv, "eovh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'e':
+ ExcludeFile = argv[util_optind];
+ if ( ExcludeFile == 0 )
+ goto usage;
+ util_optind++;
+ break;
+ case 'o':
+ fAlgorithm ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+
+ if ( argc != util_optind + 1 )
+ {
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[util_optind];
+// if ( (pFile = Io_FileOpen( FileName, "open_path", "r" )) == NULL )
+ if ( (pFile = fopen( FileName, "r" )) == NULL )
+ {
+ fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+ if ( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) )
+ fprintf( pErr, "Did you mean \"%s\"?", FileName );
+ fprintf( pErr, "\n" );
+ return 1;
+ }
+ fclose( pFile );
+
+ // set the new network
+ pLib = Map_SuperLibCreate( FileName, ExcludeFile, fAlgorithm, fVerbose );
+ if ( pLib == NULL )
+ {
+ fprintf( pErr, "Reading supergate library has failed.\n" );
+ goto usage;
+ }
+ // replace the current library
+// Map_SuperLibFree( s_pSuperLib );
+// s_pSuperLib = pLib;
+ Map_SuperLibFree( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) );
+ Abc_FrameSetLibSuper( Abc_FrameGetGlobalFrame(), pLib );
+ // replace the current genlib library
+// if ( s_pLib ) Mio_LibraryDelete( s_pLib );
+// s_pLib = s_pSuperLib->pGenlib;
+ Mio_LibraryDelete( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
+ Abc_FrameSetLibGen( Abc_FrameGetGlobalFrame(), pLib->pGenlib );
+ return 0;
+
+usage:
+ fprintf( pErr, "\nusage: read_super [-ovh]\n");
+ fprintf( pErr, "\t read the supergate library from the file\n" );
+ fprintf( pErr, "\t-e file : file contains list of genlib gates to exclude\n" );
+ fprintf( pErr, "\t-o : toggles the use of old file format [default = %s]\n", (fAlgorithm? "new" : "old") );
+ fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1; /* error exit */
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapper.h b/src/map/mapper/mapper.h
new file mode 100644
index 00000000..a6bfccf8
--- /dev/null
+++ b/src/map/mapper/mapper.h
@@ -0,0 +1,181 @@
+/**CFile****************************************************************
+
+ FileName [mapper.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapper.h,v 1.11 2005/02/28 05:34:26 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __MAPPER_H__
+#define __MAPPER_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Map_ManStruct_t_ Map_Man_t;
+typedef struct Map_NodeStruct_t_ Map_Node_t;
+typedef struct Map_NodeVecStruct_t_ Map_NodeVec_t;
+typedef struct Map_CutStruct_t_ Map_Cut_t;
+typedef struct Map_MatchStruct_t_ Map_Match_t;
+typedef struct Map_SuperStruct_t_ Map_Super_t;
+typedef struct Map_SuperLibStruct_t_ Map_SuperLib_t;
+typedef struct Map_HashTableStruct_t_ Map_HashTable_t;
+typedef struct Map_HashEntryStruct_t_ Map_HashEntry_t;
+typedef struct Map_TimeStruct_t_ Map_Time_t;
+
+// the pair of rise/fall time parameters
+struct Map_TimeStruct_t_
+{
+ float Rise;
+ float Fall;
+ float Worst;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Map_IsComplement(p) (((int)((long) (p) & 01)))
+#define Map_Regular(p) ((Map_Node_t *)((unsigned)(p) & ~01))
+#define Map_Not(p) ((Map_Node_t *)((long)(p) ^ 01))
+#define Map_NotCond(p,c) ((Map_Node_t *)((long)(p) ^ (c)))
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mapperCreate.c =============================================================*/
+extern Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose );
+extern Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 );
+extern void Map_ManFree( Map_Man_t * pMan );
+extern void Map_ManPrintTimeStats( Map_Man_t * p );
+extern void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, int Time );
+extern int Map_ManReadInputNum( Map_Man_t * p );
+extern int Map_ManReadOutputNum( Map_Man_t * p );
+extern Map_Node_t ** Map_ManReadInputs ( Map_Man_t * p );
+extern Map_Node_t ** Map_ManReadOutputs( Map_Man_t * p );
+extern Map_Node_t * Map_ManReadConst1 ( Map_Man_t * p );
+extern Map_Time_t * Map_ManReadInputArrivals( Map_Man_t * p );
+extern Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p );
+extern bool Map_ManReadVerbose( Map_Man_t * p );
+extern void Map_ManSetTimeToMap( Map_Man_t * p, int Time );
+extern void Map_ManSetTimeToNet( Map_Man_t * p, int Time );
+extern void Map_ManSetTimeSweep( Map_Man_t * p, int Time );
+extern void Map_ManSetTimeTotal( Map_Man_t * p, int Time );
+extern void Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames );
+extern void Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery );
+extern void Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget );
+extern void Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals );
+extern void Map_ManSetObeyFanoutLimits( Map_Man_t * p, bool fObeyFanoutLimits );
+extern void Map_ManSetNumIterations( Map_Man_t * p, int nNumIterations );
+extern int Map_ManReadPass( Map_Man_t * p );
+extern void Map_ManSetPass( Map_Man_t * p, int nPass );
+extern int Map_ManReadFanoutViolations( Map_Man_t * p );
+extern void Map_ManSetFanoutViolations( Map_Man_t * p, int nVio );
+extern void Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes );
+extern void Map_ManSetChoiceNum( Map_Man_t * p, int nChoices );
+extern void Map_ManSetVerbose( Map_Man_t * p, int fVerbose );
+
+extern Map_Man_t * Map_NodeReadMan( Map_Node_t * p );
+extern char * Map_NodeReadData( Map_Node_t * p, int fPhase );
+extern int Map_NodeReadNum( Map_Node_t * p );
+extern int Map_NodeReadLevel( Map_Node_t * p );
+extern Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p );
+extern Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase );
+extern Map_Node_t * Map_NodeReadOne( Map_Node_t * p );
+extern Map_Node_t * Map_NodeReadTwo( Map_Node_t * p );
+extern void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData );
+extern void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE );
+extern void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr );
+
+extern int Map_NodeIsConst( Map_Node_t * p );
+extern int Map_NodeIsVar( Map_Node_t * p );
+extern int Map_NodeIsAnd( Map_Node_t * p );
+extern int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 );
+
+extern Map_Super_t * Map_CutReadSuperBest( Map_Cut_t * p, int fPhase );
+extern Map_Super_t * Map_CutReadSuper0( Map_Cut_t * p );
+extern Map_Super_t * Map_CutReadSuper1( Map_Cut_t * p );
+extern int Map_CutReadLeavesNum( Map_Cut_t * p );
+extern Map_Node_t ** Map_CutReadLeaves( Map_Cut_t * p );
+extern unsigned Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase );
+extern unsigned Map_CutReadPhase0( Map_Cut_t * p );
+extern unsigned Map_CutReadPhase1( Map_Cut_t * p );
+
+extern char * Map_SuperReadFormula( Map_Super_t * p );
+extern Mio_Gate_t * Map_SuperReadRoot( Map_Super_t * p );
+extern int Map_SuperReadNum( Map_Super_t * p );
+extern Map_Super_t ** Map_SuperReadFanins( Map_Super_t * p );
+extern int Map_SuperReadFaninNum( Map_Super_t * p );
+extern Map_Super_t * Map_SuperReadNext( Map_Super_t * p );
+extern int Map_SuperReadNumPhases( Map_Super_t * p );
+extern unsigned char * Map_SuperReadPhases( Map_Super_t * p );
+extern int Map_SuperReadFanoutLimit( Map_Super_t * p );
+
+extern Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p );
+extern float Map_SuperLibReadAreaInv( Map_SuperLib_t * p );
+extern Map_Time_t Map_SuperLibReadDelayInv( Map_SuperLib_t * p );
+extern int Map_SuperLibReadVarsMax( Map_SuperLib_t * p );
+
+extern Map_Node_t * Map_NodeAnd( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 );
+extern Map_Node_t * Map_NodeOr( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 );
+extern Map_Node_t * Map_NodeExor( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 );
+extern Map_Node_t * Map_NodeMux( Map_Man_t * p, Map_Node_t * pNode, Map_Node_t * pNodeT, Map_Node_t * pNodeE );
+extern void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew );
+
+/*=== resmCanon.c =============================================================*/
+extern int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] );
+/*=== mapperCut.c =============================================================*/
+extern void Map_MappingCreatePiCuts( Map_Man_t * p );
+extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p );
+/*=== mapperCutUtils.c =============================================================*/
+extern void Map_CutCreateFromNode( Map_Man_t * p, Map_Super_t * pSuper, int iRoot, unsigned uPhaseRoot,
+ int * pLeaves, int nLeaves, unsigned uPhaseLeaves );
+/*=== mapperCore.c =============================================================*/
+extern int Map_Mapping( Map_Man_t * p );
+/*=== mapperLib.c =============================================================*/
+extern int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib );
+/*=== mapperMntk.c =============================================================*/
+//extern Mntk_Man_t * Map_ConvertMappingToMntk( Map_Man_t * pMan );
+/*=== mapperSuper.c =============================================================*/
+extern char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings );
+/*=== mapperSweep.c =============================================================*/
+extern void Map_NetworkSweep( Abc_Ntk_t * pNet );
+/*=== mapperTable.c =============================================================*/
+extern Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * pLib, unsigned uTruth[] );
+/*=== mapperTime.c =============================================================*/
+/*=== mapperUtil.c =============================================================*/
+extern int Map_ManCheckConsistency( Map_Man_t * p );
+extern st_table * Map_CreateTableGate2Super( Map_Man_t * p );
+extern void Map_ManCleanData( Map_Man_t * p );
+extern void Map_MappingSetupTruthTables( unsigned uTruths[][2] );
+extern void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/src/map/mapper/mapperCanon.c b/src/map/mapper/mapperCanon.c
new file mode 100644
index 00000000..c5186c7e
--- /dev/null
+++ b/src/map/mapper/mapperCanon.c
@@ -0,0 +1,161 @@
+/**CFile****************************************************************
+
+ FileName [mapperCanon.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperCanon.c,v 1.2 2005/01/23 06:59:42 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase );
+static void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the N-canonical form of the Boolean function.]
+
+ Description [The N-canonical form is defined as the truth table with
+ the minimum integer value. This function exhaustively enumerates
+ through the complete set of 2^N phase assignments.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] )
+{
+ unsigned uTruthPerm[2];
+ int nMints, nPhases, m;
+
+ nPhases = 0;
+ nMints = (1 << nVarsReal);
+ if ( nVarsMax < 6 )
+ {
+ uTruthRes[0] = MAP_MASK(32);
+ for ( m = 0; m < nMints; m++ )
+ {
+ uTruthPerm[0] = Map_CanonComputePhase( uTruths, nVarsMax, uTruth[0], m );
+ if ( uTruthRes[0] > uTruthPerm[0] )
+ {
+ uTruthRes[0] = uTruthPerm[0];
+ nPhases = 0;
+ puPhases[nPhases++] = (unsigned char)m;
+ }
+ else if ( uTruthRes[0] == uTruthPerm[0] )
+ {
+ if ( nPhases < 4 ) // the max number of phases in Map_Super_t
+ puPhases[nPhases++] = (unsigned char)m;
+ }
+ }
+ uTruthRes[1] = uTruthRes[0];
+ }
+ else
+ {
+ uTruthRes[0] = MAP_MASK(32);
+ uTruthRes[1] = MAP_MASK(32);
+ for ( m = 0; m < nMints; m++ )
+ {
+ Map_CanonComputePhase6( uTruths, nVarsMax, uTruth, m, uTruthPerm );
+ if ( uTruthRes[1] > uTruthPerm[1] || uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] > uTruthPerm[0] )
+ {
+ uTruthRes[0] = uTruthPerm[0];
+ uTruthRes[1] = uTruthPerm[1];
+ nPhases = 0;
+ puPhases[nPhases++] = (unsigned char)m;
+ }
+ else if ( uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] == uTruthPerm[0] )
+ {
+ if ( nPhases < 4 ) // the max number of phases in Map_Super_t
+ puPhases[nPhases++] = (unsigned char)m;
+ }
+ }
+ }
+ assert( nPhases > 0 );
+// printf( "%d ", nPhases );
+ return nPhases;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs phase transformation for one function of less than 6 variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase )
+{
+ int v, Shift;
+ for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 )
+ if ( uPhase & Shift )
+ uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift));
+ return uTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs phase transformation for one function of 6 variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] )
+{
+ unsigned uTemp;
+ int v, Shift;
+
+ // initialize the result
+ uTruthRes[0] = uTruth[0];
+ uTruthRes[1] = uTruth[1];
+ if ( uPhase == 0 )
+ return;
+ // compute the phase
+ for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 )
+ if ( uPhase & Shift )
+ {
+ if ( Shift < 32 )
+ {
+ uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift));
+ uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift));
+ }
+ else
+ {
+ uTemp = uTruthRes[0];
+ uTruthRes[0] = uTruthRes[1];
+ uTruthRes[1] = uTemp;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperCore.c b/src/map/mapper/mapperCore.c
new file mode 100644
index 00000000..415e4974
--- /dev/null
+++ b/src/map/mapper/mapperCore.c
@@ -0,0 +1,167 @@
+/**CFile****************************************************************
+
+ FileName [mapperCore.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+//#include "resm.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs technology mapping for the given object graph.]
+
+ Description [The object graph is stored in the mapping manager.
+ First, the AND nodes that fanout into POs are collected in the DFS order.
+ Two preprocessing steps are performed: the k-feasible cuts are computed
+ for each node and the truth tables are computed for each cut. Next, the
+ delay-optimal matches are assigned for each node, followed by several
+ iterations of area recoveryd: using area flow (global optimization)
+ and using exact area at a node (local optimization).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_Mapping( Map_Man_t * p )
+{
+ int fUseAreaFlow = 1;
+ int fUseExactArea = 1;
+ int fUseExactAreaWithPhase = 1;
+ int clk;
+
+ //////////////////////////////////////////////////////////////////////
+ // perform pre-mapping computations
+ // collect the nodes reachable from POs in the DFS order (including the choices)
+ p->vAnds = Map_MappingDfs( p, 1 );
+ if ( p->fVerbose )
+ Map_MappingReportChoices( p );
+ Map_MappingSetChoiceLevels( p ); // should always be called before mapping!
+// return 1;
+
+ // compute the cuts of nodes in the DFS order
+ clk = clock();
+ Map_MappingCuts( p );
+ p->timeCuts = clock() - clk;
+ // derive the truth tables
+ clk = clock();
+ Map_MappingTruths( p );
+ p->timeTruth = clock() - clk;
+ //////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////
+ // compute the minimum-delay mapping
+ clk = clock();
+ p->fMappingMode = 0;
+ if ( !Map_MappingMatches( p ) )
+ return 0;
+ p->timeMatch = clock() - clk;
+ // compute the references and collect the nodes used in the mapping
+ Map_MappingSetRefs( p );
+ p->AreaBase = Map_MappingGetArea( p, p->vMapping );
+if ( p->fVerbose )
+{
+printf( "Delay : FanViols = %5d Flow = %11.1f Area = %11.1f %4.1f %% ",
+ 0, Map_MappingGetAreaFlow(p), p->AreaBase, 0.0 );
+PRT( "Time", p->timeMatch );
+}
+ //////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////
+ // perform area recovery using area flow
+ clk = clock();
+ if ( fUseAreaFlow )
+ {
+ // compute the required times and the fanouts
+ Map_TimeComputeRequiredGlobal( p );
+ // recover area flow
+ p->fMappingMode = 1;
+ Map_MappingMatches( p );
+ // compute the references and collect the nodes used in the mapping
+ Map_MappingSetRefs( p );
+ p->AreaFinal = Map_MappingGetArea( p, p->vMapping );
+if ( p->fVerbose )
+{
+printf( "AreaFlow : FanViols = %5d Flow = %11.1f Area = %11.1f %4.1f %% ",
+ 0, Map_MappingGetAreaFlow(p), p->AreaFinal,
+ 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase );
+PRT( "Time", clock() - clk );
+}
+ }
+ p->timeArea += clock() - clk;
+ //////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////
+ // perform area recovery using exact area
+ clk = clock();
+ if ( fUseExactArea )
+ {
+ // compute the required times and the fanouts
+ Map_TimeComputeRequiredGlobal( p );
+ // recover area flow
+ p->fMappingMode = 2;
+ Map_MappingMatches( p );
+ // compute the references and collect the nodes used in the mapping
+ Map_MappingSetRefs( p );
+ p->AreaFinal = Map_MappingGetArea( p, p->vMapping );
+if ( p->fVerbose )
+{
+printf( "Area : FanViols = %5d Flow = %11.1f Area = %11.1f %4.1f %% ",
+ 0, 0.0, p->AreaFinal,
+ 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase );
+PRT( "Time", clock() - clk );
+}
+ }
+ p->timeArea += clock() - clk;
+ //////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////
+ // perform area recovery using exact area
+ clk = clock();
+ if ( fUseExactAreaWithPhase )
+ {
+ // compute the required times and the fanouts
+ Map_TimeComputeRequiredGlobal( p );
+ // recover area flow
+ p->fMappingMode = 3;
+ Map_MappingMatches( p );
+ // compute the references and collect the nodes used in the mapping
+ Map_MappingSetRefs( p );
+ p->AreaFinal = Map_MappingGetArea( p, p->vMapping );
+if ( p->fVerbose )
+{
+printf( "Area : FanViols = %5d Flow = %11.1f Area = %11.1f %4.1f %% ",
+ 0, 0.0, p->AreaFinal,
+ 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase );
+PRT( "Time", clock() - clk );
+}
+ }
+ p->timeArea += clock() - clk;
+ //////////////////////////////////////////////////////////////////////
+
+ // print the arrival times of the latest outputs
+ if ( p->fVerbose )
+ Map_MappingPrintOutputArrivals( p );
+ return 1;
+}
diff --git a/src/map/mapper/mapperCreate.c b/src/map/mapper/mapperCreate.c
new file mode 100644
index 00000000..61c90d1c
--- /dev/null
+++ b/src/map/mapper/mapperCreate.c
@@ -0,0 +1,592 @@
+/**CFile****************************************************************
+
+ FileName [mapperCreate.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperCreate.c,v 1.15 2005/02/28 05:34:26 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Map_TableCreate( Map_Man_t * p );
+static void Map_TableResize( Map_Man_t * p );
+static Map_Node_t * Map_TableLookup( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 );
+
+// hash key for the structural hash table
+static inline unsigned Map_HashKey2( Map_Node_t * p0, Map_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters from the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_ManReadInputNum( Map_Man_t * p ) { return p->nInputs; }
+int Map_ManReadOutputNum( Map_Man_t * p ) { return p->nOutputs; }
+Map_Node_t ** Map_ManReadInputs ( Map_Man_t * p ) { return p->pInputs; }
+Map_Node_t ** Map_ManReadOutputs( Map_Man_t * p ) { return p->pOutputs; }
+Map_Node_t * Map_ManReadConst1 ( Map_Man_t * p ) { return p->pConst1; }
+Map_Time_t * Map_ManReadInputArrivals( Map_Man_t * p ) { return p->pInputArrivals;}
+Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p ) { return p->pSuperLib->pGenlib; }
+bool Map_ManReadVerbose( Map_Man_t * p ) { return p->fVerbose; }
+void Map_ManSetTimeToMap( Map_Man_t * p, int Time ) { p->timeToMap = Time; }
+void Map_ManSetTimeToNet( Map_Man_t * p, int Time ) { p->timeToNet = Time; }
+void Map_ManSetTimeSweep( Map_Man_t * p, int Time ) { p->timeSweep = Time; }
+void Map_ManSetTimeTotal( Map_Man_t * p, int Time ) { p->timeTotal = Time; }
+void Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; }
+void Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;}
+void Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget;}
+void Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals ) { p->pInputArrivals = pArrivals;}
+void Map_ManSetObeyFanoutLimits( Map_Man_t * p, bool fObeyFanoutLimits ) { p->fObeyFanoutLimits = fObeyFanoutLimits; }
+void Map_ManSetNumIterations( Map_Man_t * p, int nIterations ) { p->nIterations = nIterations; }
+int Map_ManReadFanoutViolations( Map_Man_t * p ) { return p->nFanoutViolations; }
+void Map_ManSetFanoutViolations( Map_Man_t * p, int nVio ) { p->nFanoutViolations = nVio; }
+void Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; }
+void Map_ManSetChoiceNum( Map_Man_t * p, int nChoices ) { p->nChoices = nChoices; }
+void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; }
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters from the mapping node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Man_t * Map_NodeReadMan( Map_Node_t * p ) { return p->p; }
+char * Map_NodeReadData( Map_Node_t * p, int fPhase ) { return fPhase? p->pData1 : p->pData0; }
+int Map_NodeReadNum( Map_Node_t * p ) { return p->Num; }
+int Map_NodeReadLevel( Map_Node_t * p ) { return Map_Regular(p)->Level; }
+Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ) { return p->pCuts; }
+Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ) { return p->pCutBest[fPhase]; }
+Map_Node_t * Map_NodeReadOne( Map_Node_t * p ) { return p->p1; }
+Map_Node_t * Map_NodeReadTwo( Map_Node_t * p ) { return p->p2; }
+void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ) { if (fPhase) p->pData1 = pData; else p->pData0 = pData; }
+void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ) { p->pNextE = pNextE; }
+void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ) { p->pRepr = pRepr; }
+
+/**Function*************************************************************
+
+ Synopsis [Checks the type of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_NodeIsConst( Map_Node_t * p ) { return (Map_Regular(p))->Num == -1; }
+int Map_NodeIsVar( Map_Node_t * p ) { return (Map_Regular(p))->p1 == NULL && (Map_Regular(p))->Num >= 0; }
+int Map_NodeIsAnd( Map_Node_t * p ) { return (Map_Regular(p))->p1 != NULL; }
+int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ) { assert( !Map_IsComplement(p1) ); assert( !Map_IsComplement(p2) ); return p1->fInv ^ p2->fInv; }
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters from the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Super_t * Map_CutReadSuperBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].pSuperBest;}
+Map_Super_t * Map_CutReadSuper0( Map_Cut_t * p ) { return p->M[0].pSuperBest;}
+Map_Super_t * Map_CutReadSuper1( Map_Cut_t * p ) { return p->M[1].pSuperBest;}
+int Map_CutReadLeavesNum( Map_Cut_t * p ) { return p->nLeaves; }
+Map_Node_t ** Map_CutReadLeaves( Map_Cut_t * p ) { return p->ppLeaves; }
+unsigned Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].uPhaseBest;}
+unsigned Map_CutReadPhase0( Map_Cut_t * p ) { return p->M[0].uPhaseBest;}
+unsigned Map_CutReadPhase1( Map_Cut_t * p ) { return p->M[1].uPhaseBest;}
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters from the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Map_SuperReadFormula( Map_Super_t * p ) { return p->pFormula; }
+Mio_Gate_t * Map_SuperReadRoot( Map_Super_t * p ) { return p->pRoot; }
+int Map_SuperReadNum( Map_Super_t * p ) { return p->Num; }
+Map_Super_t ** Map_SuperReadFanins( Map_Super_t * p ) { return p->pFanins; }
+int Map_SuperReadFaninNum( Map_Super_t * p ) { return p->nFanins; }
+Map_Super_t * Map_SuperReadNext( Map_Super_t * p ) { return p->pNext; }
+int Map_SuperReadNumPhases( Map_Super_t * p ) { return p->nPhases; }
+unsigned char * Map_SuperReadPhases( Map_Super_t * p ) { return p->uPhases; }
+int Map_SuperReadFanoutLimit( Map_Super_t * p ) { return p->nFanLimit;}
+
+Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p ) { return p->pGenlib; }
+float Map_SuperLibReadAreaInv( Map_SuperLib_t * p ) { return p->AreaInv; }
+Map_Time_t Map_SuperLibReadDelayInv( Map_SuperLib_t * p ) { return p->tDelayInv;}
+int Map_SuperLibReadVarsMax( Map_SuperLib_t * p ) { return p->nVarsMax; }
+
+
+/**Function*************************************************************
+
+ Synopsis [Create the mapping manager.]
+
+ Description [The number of inputs and outputs is assumed to be
+ known is advance. It is much simpler to have them fixed upfront.
+ When it comes to representing the object graph in the form of
+ AIG, the resulting manager is similar to the regular AIG manager,
+ except that it does not use reference counting (and therefore
+ does not have garbage collections). It does have table resizing.
+ The data structure is more flexible to represent additional
+ information needed for mapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose )
+{
+ Map_Man_t * p;
+ int i;
+
+ // derive the supergate library
+ if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL )
+ {
+ printf( "The supergate library is not specified. Use \"read_library\" or \"read_super\".\n" );
+ return NULL;
+ }
+
+ // start the manager
+ p = ALLOC( Map_Man_t, 1 );
+ memset( p, 0, sizeof(Map_Man_t) );
+ p->pSuperLib = Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame());
+ p->nVarsMax = p->pSuperLib->nVarsMax;
+ p->fVerbose = fVerbose;
+ p->fEpsilon = (float)0.00001;
+ assert( p->nVarsMax > 0 );
+
+ // start various data structures
+ Map_TableCreate( p );
+ Map_MappingSetupTruthTables( p->uTruths );
+ Map_MappingSetupTruthTablesLarge( p->uTruthsLarge );
+// printf( "Node = %d bytes. Cut = %d bytes. Super = %d bytes.\n", sizeof(Map_Node_t), sizeof(Map_Cut_t), sizeof(Map_Super_t) );
+ p->mmNodes = Extra_MmFixedStart( sizeof(Map_Node_t) );
+ p->mmCuts = Extra_MmFixedStart( sizeof(Map_Cut_t) );
+
+ // make sure the constant node will get index -1
+ p->nNodes = -1;
+ // create the constant node
+ p->pConst1 = Map_NodeCreate( p, NULL, NULL );
+ p->vNodesAll = Map_NodeVecAlloc( 100 );
+ p->vNodesTemp = Map_NodeVecAlloc( 100 );
+ p->vMapping = Map_NodeVecAlloc( 100 );
+ p->vInside = Map_NodeVecAlloc( 100 );
+ p->vFanins = Map_NodeVecAlloc( 100 );
+
+ // create the PI nodes
+ p->nInputs = nInputs;
+ p->pInputs = ALLOC( Map_Node_t *, nInputs );
+ for ( i = 0; i < nInputs; i++ )
+ p->pInputs[i] = Map_NodeCreate( p, NULL, NULL );
+
+ // create the place for the output nodes
+ p->nOutputs = nOutputs;
+ p->pOutputs = ALLOC( Map_Node_t *, nOutputs );
+ memset( p->pOutputs, 0, sizeof(Map_Node_t *) * nOutputs );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_ManFree( Map_Man_t * p )
+{
+// int i;
+// for ( i = 0; i < p->vNodesAll->nSize; i++ )
+// Map_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts );
+// Map_NodeVecFree( p->pConst1->vFanouts );
+ if ( p->vInside )
+ Map_NodeVecFree( p->vInside );
+ if ( p->vFanins )
+ Map_NodeVecFree( p->vFanins );
+ if ( p->vAnds )
+ Map_NodeVecFree( p->vAnds );
+ if ( p->vNodesAll )
+ Map_NodeVecFree( p->vNodesAll );
+ if ( p->vNodesTemp )
+ Map_NodeVecFree( p->vNodesTemp );
+ if ( p->vMapping )
+ Map_NodeVecFree( p->vMapping );
+ Extra_MmFixedStop( p->mmNodes, 0 );
+ Extra_MmFixedStop( p->mmCuts, 0 );
+ FREE( p->pInputArrivals );
+ FREE( p->pInputs );
+ FREE( p->pOutputs );
+ FREE( p->pBins );
+// FREE( p->ppOutputNames );
+ if ( p->pSimInfo ) FREE( p->pSimInfo[0] );
+ FREE( p->pSimInfo );
+ FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_ManPrintTimeStats( Map_Man_t * p )
+{
+ printf( "N-canonical = %d. Matchings = %d. Phases = %d. ", p->nCanons, p->nMatches, p->nPhases );
+ printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices );
+ PRT( "ToMap", p->timeToMap );
+ PRT( "Cuts ", p->timeCuts );
+ PRT( "Truth", p->timeTruth );
+ PRT( "Match", p->timeMatch );
+ PRT( "Area ", p->timeArea );
+ PRT( "Sweep", p->timeSweep );
+ PRT( "ToNet", p->timeToNet );
+ PRT( "TOTAL", p->timeTotal );
+ if ( p->time1 ) { PRT( "time1", p->time1 ); }
+ if ( p->time2 ) { PRT( "time2", p->time2 ); }
+ if ( p->time3 ) { PRT( "time3", p->time3 ); }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the mapping stats.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, int Time )
+{
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pName );
+ fprintf( pTable, "%4.2f ", Area );
+ fprintf( pTable, "%4.2f ", Delay );
+ fprintf( pTable, "%4.2f\n", (float)(Time)/(float)(CLOCKS_PER_SEC) );
+ fclose( pTable );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description [This procedure should be called to create the constant
+ node and the PI nodes first.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 )
+{
+ Map_Node_t * pNode;
+ // create the node
+ pNode = (Map_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes );
+ memset( pNode, 0, sizeof(Map_Node_t) );
+ pNode->tRequired[0].Rise = pNode->tRequired[0].Fall = pNode->tRequired[0].Worst = MAP_FLOAT_LARGE;
+ pNode->tRequired[1].Rise = pNode->tRequired[1].Fall = pNode->tRequired[1].Worst = MAP_FLOAT_LARGE;
+ pNode->p1 = p1;
+ pNode->p2 = p2;
+ pNode->p = p;
+ // set the number of this node
+ pNode->Num = p->nNodes++;
+ // place to store the fanouts
+// pNode->vFanouts = Map_NodeVecAlloc( 5 );
+ // store this node in the internal array
+ if ( pNode->Num >= 0 )
+ Map_NodeVecPush( p->vNodesAll, pNode );
+ else
+ pNode->fInv = 1;
+ // set the level of this node
+ if ( p1 )
+ {
+ // create the fanout info
+ Map_NodeAddFaninFanout( Map_Regular(p1), pNode );
+ Map_NodeAddFaninFanout( Map_Regular(p2), pNode );
+ pNode->Level = 1 + MAP_MAX(Map_Regular(pNode->p1)->Level, Map_Regular(pNode->p2)->Level);
+ pNode->fInv = Map_NodeIsSimComplement(p1) & Map_NodeIsSimComplement(p2);
+ }
+ // reference the inputs (will be used to compute the number of fanouts)
+ if ( p1 ) Map_NodeRef(p1);
+ if ( p2 ) Map_NodeRef(p2);
+
+ pNode->nRefEst[0] = pNode->nRefEst[1] = -1;
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the unique table of AND gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TableCreate( Map_Man_t * pMan )
+{
+ assert( pMan->pBins == NULL );
+ pMan->nBins = Cudd_Prime(5000);
+ pMan->pBins = ALLOC( Map_Node_t *, pMan->nBins );
+ memset( pMan->pBins, 0, sizeof(Map_Node_t *) * pMan->nBins );
+ pMan->nNodes = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the AND2 node in the unique table.]
+
+ Description [This procedure implements one-level hashing. All the nodes
+ are hashed by their children. If the node with the same children was already
+ created, it is returned by the call to this procedure. If it does not exist,
+ this procedure creates a new node with these children. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t * Map_TableLookup( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 )
+{
+ Map_Node_t * pEnt;
+ unsigned Key;
+
+ if ( p1 == p2 )
+ return p1;
+ if ( p1 == Map_Not(p2) )
+ return Map_Not(pMan->pConst1);
+ if ( Map_NodeIsConst(p1) )
+ {
+ if ( p1 == pMan->pConst1 )
+ return p2;
+ return Map_Not(pMan->pConst1);
+ }
+ if ( Map_NodeIsConst(p2) )
+ {
+ if ( p2 == pMan->pConst1 )
+ return p1;
+ return Map_Not(pMan->pConst1);
+ }
+
+ if ( Map_Regular(p1)->Num > Map_Regular(p2)->Num )
+ pEnt = p1, p1 = p2, p2 = pEnt;
+
+ Key = Map_HashKey2( p1, p2, pMan->nBins );
+ for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( pEnt->p1 == p1 && pEnt->p2 == p2 )
+ return pEnt;
+ // resize the table
+ if ( pMan->nNodes >= 2 * pMan->nBins )
+ {
+ Map_TableResize( pMan );
+ Key = Map_HashKey2( p1, p2, pMan->nBins );
+ }
+ // create the new node
+ pEnt = Map_NodeCreate( pMan, p1, p2 );
+ // add the node to the corresponding linked list in the table
+ pEnt->pNext = pMan->pBins[Key];
+ pMan->pBins[Key] = pEnt;
+ return pEnt;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TableResize( Map_Man_t * pMan )
+{
+ Map_Node_t ** pBinsNew;
+ Map_Node_t * pEnt, * pEnt2;
+ int nBinsNew, Counter, i, clk;
+ unsigned Key;
+
+clk = clock();
+ // get the new table size
+ nBinsNew = Cudd_Prime(2 * pMan->nBins);
+ // allocate a new array
+ pBinsNew = ALLOC( Map_Node_t *, nBinsNew );
+ memset( pBinsNew, 0, sizeof(Map_Node_t *) * nBinsNew );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( i = 0; i < pMan->nBins; i++ )
+ for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt;
+ pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL )
+ {
+ Key = Map_HashKey2( pEnt->p1, pEnt->p2, nBinsNew );
+ pEnt->pNext = pBinsNew[Key];
+ pBinsNew[Key] = pEnt;
+ Counter++;
+ }
+ assert( Counter == pMan->nNodes - pMan->nInputs );
+ if ( pMan->fVerbose )
+ {
+// printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew );
+// PRT( "Time", clock() - clk );
+ }
+ // replace the table and the parameters
+ free( pMan->pBins );
+ pMan->pBins = pBinsNew;
+ pMan->nBins = nBinsNew;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t * Map_NodeAnd( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 )
+{
+ Map_Node_t * pNode;
+ pNode = Map_TableLookup( p, p1, p2 );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t * Map_NodeOr( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 )
+{
+ Map_Node_t * pNode;
+ pNode = Map_Not( Map_TableLookup( p, Map_Not(p1), Map_Not(p2) ) );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t * Map_NodeExor( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 )
+{
+ return Map_NodeMux( p, p1, Map_Not(p2), p2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t * Map_NodeMux( Map_Man_t * p, Map_Node_t * pC, Map_Node_t * pT, Map_Node_t * pE )
+{
+ Map_Node_t * pAnd1, * pAnd2, * pRes;
+ pAnd1 = Map_TableLookup( p, pC, pT );
+ pAnd2 = Map_TableLookup( p, Map_Not(pC), pE );
+ pRes = Map_NodeOr( p, pAnd1, pAnd2 );
+ return pRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets the node to be equivalent to the given one.]
+
+ Description [This procedure is a work-around for the equivalence check.
+ Does not verify the equivalence. Use at the user's risk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew )
+{
+ pNodeNew->pNextE = pNodeOld->pNextE;
+ pNodeOld->pNextE = pNodeNew;
+ pNodeNew->pRepr = pNodeOld;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/mapper/mapperCut.c b/src/map/mapper/mapperCut.c
new file mode 100644
index 00000000..87592365
--- /dev/null
+++ b/src/map/mapper/mapperCut.c
@@ -0,0 +1,1072 @@
+/**CFile****************************************************************
+
+ FileName [mapperCut.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperCut.c,v 1.12 2005/02/28 05:34:27 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the largest number of cuts considered
+#define MAP_CUTS_MAX_COMPUTE 200
+// the largest number of cuts used
+#define MAP_CUTS_MAX_USE 50
+
+// temporary hash table to store the cuts
+typedef struct Map_CutTableStrutct_t Map_CutTable_t;
+struct Map_CutTableStrutct_t
+{
+ Map_Cut_t ** pBins; // the table used for linear probing
+ int nBins; // the size of the table
+ int * pCuts; // the array of cuts currently stored
+ int nCuts; // the number of cuts currently stored
+ Map_Cut_t ** pArray; // the temporary array of cuts
+ Map_Cut_t ** pCuts1; // the temporary array of cuts
+ Map_Cut_t ** pCuts2; // the temporary array of cuts
+};
+
+// primes used to compute the hash key
+static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 };
+
+static Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode );
+static void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode );
+static Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 );
+static int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax );
+static Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 );
+static int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes );
+
+static void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot );
+static void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot );
+static void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot );
+
+static Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan );
+static void Map_CutTableStop( Map_CutTable_t * p );
+static unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes );
+static int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes );
+static Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes );
+static void Map_CutTableRestart( Map_CutTable_t * p );
+
+static Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList );
+static int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList );
+static Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts );
+
+
+// iterator through all the cuts of the list
+#define Map_ListForEachCut( pList, pCut ) \
+ for ( pCut = pList; \
+ pCut; \
+ pCut = pCut->pNext )
+#define Map_ListForEachCutSafe( pList, pCut, pCut2 ) \
+ for ( pCut = pList, \
+ pCut2 = pCut? pCut->pNext: NULL; \
+ pCut; \
+ pCut = pCut2, \
+ pCut2 = pCut? pCut->pNext: NULL )
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for each node in the object graph.]
+
+ Description [The cuts are computed in one sweep over the mapping graph.
+ First, the elementary cuts, which include the node itself, are assigned
+ to the PI nodes. The internal nodes are considered in the DFS order.
+ Each node is two-input AND-gate. So to compute the cuts at a node, we
+ need to merge the sets of cuts of its two predecessors. The merged set
+ contains only unique cuts with the number of inputs equal to k or less.
+ Finally, the elementary cut, composed of the node itself, is added to
+ the set of cuts for the node.
+
+ This procedure is pretty fast for 5-feasible cuts, but it dramatically
+ slows down on some "dense" networks when computing 6-feasible cuts.
+ The problem is that there are too many cuts in this case. We should
+ think how to heuristically trim the number of cuts in such cases,
+ to have reasonable runtime.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingCuts( Map_Man_t * p )
+{
+ ProgressBar * pProgress;
+ Map_CutTable_t * pTable;
+ Map_Node_t * pNode;
+ Map_Cut_t * pCut;
+ int nCuts, nNodes, i;
+ // set the elementary cuts for the PI variables
+ assert( p->nVarsMax > 1 && p->nVarsMax < 7 );
+ for ( i = 0; i < p->nInputs; i++ )
+ {
+ pCut = Map_CutAlloc( p );
+ pCut->nLeaves = 1;
+ pCut->ppLeaves[0] = p->pInputs[i];
+// pCut->fLevel = (float)pCut->ppLeaves[0]->Level;
+ p->pInputs[i]->pCuts = pCut;
+ p->pInputs[i]->pCutBest[0] = NULL; // negative polarity is not mapped
+ p->pInputs[i]->pCutBest[1] = pCut; // positive polarity is a trivial cut
+ pCut->M[0].AreaFlow = 0.0;
+ pCut->M[1].AreaFlow = 0.0;
+ }
+
+ // compute the cuts for the internal nodes
+ nNodes = p->vAnds->nSize;
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ pTable = Map_CutTableStart( p );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+ if ( !Map_NodeIsAnd( pNode ) )
+ continue;
+ Map_CutCompute( p, pTable, pNode );
+ Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Map_CutTableStop( pTable );
+
+ // report the stats
+ if ( p->fVerbose )
+ {
+ nCuts = Map_MappingCountAllCuts(p);
+ printf( "Nodes = %6d. Total %d-feasible cuts = %d. Cuts per node = %.1f.\n",
+ p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes );
+ }
+
+ // print the cuts for the first primary output
+// Map_CutListPrint( p, Map_Regular(p->pOutputs[0]) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs technology mapping for variable-size-LUTs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingCreatePiCuts( Map_Man_t * p )
+{
+ Map_Cut_t * pCut;
+ int i;
+
+ // set the elementary cuts for the PI variables
+ for ( i = 0; i < p->nInputs; i++ )
+ {
+ pCut = Map_CutAlloc( p );
+ pCut->nLeaves = 1;
+ pCut->ppLeaves[0] = p->pInputs[i];
+// pCut->fLevel = (float)pCut->ppLeaves[0]->Level;
+ p->pInputs[i]->pCuts = pCut;
+ p->pInputs[i]->pCutBest[1] = pCut;
+ p->pInputs[i]->pCutBest[0] = pCut;
+ // set the input arrival times
+// p->pInputs[i]->pCut[1]->tArrival = p->pInputArrivals[i];
+
+ // set the input arrival times
+ pCut = p->pInputs[i]->pCutBest[1];
+ pCut->M[1].tArrive = p->pInputArrivals[i];
+ pCut->M[1].tArrive.Worst = MAP_MAX( pCut->M[1].tArrive.Rise, pCut->M[1].tArrive.Fall );
+ // set the arrival times of the negative phases of the PI nodes
+ pCut = p->pInputs[i]->pCutBest[0];
+ pCut->M[0].tArrive.Rise = p->pInputArrivals[i].Fall + p->pSuperLib->tDelayInv.Rise;
+ pCut->M[0].tArrive.Fall = p->pInputArrivals[i].Rise + p->pSuperLib->tDelayInv.Fall;
+ pCut->M[0].tArrive.Worst = MAP_MAX( pCut->M[0].tArrive.Rise, pCut->M[0].tArrive.Fall );
+
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode )
+{
+ Map_Node_t * pTemp;
+ Map_Cut_t * pList, * pList1, * pList2;
+ Map_Cut_t * pCut;
+
+ // if the cuts are computed return them
+ if ( pNode->pCuts )
+ return pNode->pCuts;
+
+ // compute the cuts for the children
+ pList1 = Map_Regular(pNode->p1)->pCuts;
+ pList2 = Map_Regular(pNode->p2)->pCuts;
+ // merge the lists
+ pList = Map_CutMergeLists( p, pTable, pList1, pList2,
+ Map_IsComplement(pNode->p1), Map_IsComplement(pNode->p2) );
+ // if there are functionally equivalent nodes, union them with this list
+ assert( pList );
+ // only add to the list of cuts if the node is a representative one
+ if ( pNode->pRepr == NULL )
+ {
+ for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+ {
+ assert( pTemp->pCuts );
+ pList = Map_CutUnionLists( pList, pTemp->pCuts );
+ assert( pTemp->pCuts );
+ pList = Map_CutSortCuts( p, pTable, pList );
+ }
+ }
+ // add the new cut
+ pCut = Map_CutAlloc( p );
+ pCut->nLeaves = 1;
+ pCut->ppLeaves[0] = pNode;
+// pCut->fLevel = (float)pCut->ppLeaves[0]->Level;
+ // append (it is important that the elementary cut is appended first)
+ pCut->pNext = pList;
+ // set at the node
+ pNode->pCuts = pCut;
+ // remove the dominated cuts
+// Map_CutFilter( p, pNode );
+ // set the phase correctly
+ if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) )
+ {
+ Map_ListForEachCut( pNode->pCuts, pCut )
+ pCut->Phase = 1;
+ }
+/*
+ {
+ int i, Counter = 0;;
+ for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ Counter += (pCut->ppLeaves[i]->Level >= pNode->Level);
+// if ( Counter )
+// printf( " %d", Counter );
+ }
+*/
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filter the cuts using dominance.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode )
+{
+ Map_Cut_t * pTemp, * pPrev, * pCut, * pCut2;
+ int i, k, Counter;
+
+ Counter = 0;
+ pPrev = pNode->pCuts;
+ Map_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 )
+ {
+ // go through all the previous cuts up to pCut
+ for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext )
+ {
+ // check if every node in pTemp is contained in pCut
+ for ( i = 0; i < pTemp->nLeaves; i++ )
+ {
+ for ( k = 0; k < pCut->nLeaves; k++ )
+ if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] )
+ break;
+ if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut
+ break;
+ }
+ if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut
+ {
+ Counter++;
+ break;
+ }
+ }
+ if ( pTemp != pCut ) // pTemp contain pCut
+ {
+ pPrev->pNext = pCut->pNext; // skip pCut
+ // recycle pCut
+ Map_CutFree( p, pCut );
+ }
+ else
+ pPrev = pCut;
+ }
+// printf( "Dominated = %3d. \n", Counter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two lists of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable,
+ Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 )
+{
+ Map_Node_t * ppNodes[6];
+ Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
+ Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
+ int nNodes, Counter, i;
+ Map_Cut_t ** ppArray1, ** ppArray2, ** ppArray3;
+ int nCuts1, nCuts2, nCuts3, k, fComp3;
+
+ ppArray1 = pTable->pCuts1;
+ ppArray2 = pTable->pCuts2;
+ nCuts1 = Map_CutList2Array( ppArray1, pList1 );
+ nCuts2 = Map_CutList2Array( ppArray2, pList2 );
+ // swap the lists based on their length
+ if ( nCuts1 > nCuts2 )
+ {
+ ppArray3 = ppArray1;
+ ppArray1 = ppArray2;
+ ppArray2 = ppArray3;
+
+ nCuts3 = nCuts1;
+ nCuts1 = nCuts2;
+ nCuts2 = nCuts3;
+
+ fComp3 = fComp1;
+ fComp1 = fComp2;
+ fComp2 = fComp3;
+ }
+ // pList1 is shorter or equal length compared to pList2
+
+ // prepare the manager for the cut computation
+ Map_CutTableRestart( pTable );
+ // go through the cut pairs
+ Counter = 0;
+// for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext )
+// for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext )
+ for ( i = 0; i < nCuts1; i++ )
+ {
+ for ( k = 0; k <= i; k++ )
+ {
+ pTemp1 = ppArray1[i];
+ pTemp2 = ppArray2[k];
+
+ // check if k-feasible cut exists
+ nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+ if ( nNodes == 0 )
+ continue;
+ // consider the cut for possible addition to the set of new cuts
+ pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
+ if ( pCut == NULL )
+ continue;
+ // add data to the cut
+ pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
+ pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
+ // add it to the corresponding list
+ pCut->pNext = pLists[pCut->nLeaves];
+ pLists[pCut->nLeaves] = pCut;
+ // count this cut and quit if limit is reached
+ Counter++;
+ if ( Counter == MAP_CUTS_MAX_COMPUTE )
+ goto QUITS;
+ }
+ for ( k = 0; k < i; k++ )
+ {
+ pTemp1 = ppArray1[k];
+ pTemp2 = ppArray2[i];
+
+ // check if k-feasible cut exists
+ nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+ if ( nNodes == 0 )
+ continue;
+ // consider the cut for possible addition to the set of new cuts
+ pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
+ if ( pCut == NULL )
+ continue;
+ // add data to the cut
+ pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
+ pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
+ // add it to the corresponding list
+ pCut->pNext = pLists[pCut->nLeaves];
+ pLists[pCut->nLeaves] = pCut;
+ // count this cut and quit if limit is reached
+ Counter++;
+ if ( Counter == MAP_CUTS_MAX_COMPUTE )
+ goto QUITS;
+ }
+ }
+ // consider the rest of them
+ for ( i = nCuts1; i < nCuts2; i++ )
+ for ( k = 0; k < nCuts1; k++ )
+ {
+ pTemp1 = ppArray1[k];
+ pTemp2 = ppArray2[i];
+
+ // check if k-feasible cut exists
+ nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+ if ( nNodes == 0 )
+ continue;
+ // consider the cut for possible addition to the set of new cuts
+ pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
+ if ( pCut == NULL )
+ continue;
+ // add data to the cut
+ pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
+ pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
+ // add it to the corresponding list
+ pCut->pNext = pLists[pCut->nLeaves];
+ pLists[pCut->nLeaves] = pCut;
+ // count this cut and quit if limit is reached
+ Counter++;
+ if ( Counter == MAP_CUTS_MAX_COMPUTE )
+ goto QUITS;
+ }
+QUITS :
+ // combine all the lists into one
+ pListNew = NULL;
+ ppListNew = &pListNew;
+ for ( i = 1; i <= p->nVarsMax; i++ )
+ {
+ if ( pLists[i] == NULL )
+ continue;
+ // find the last entry
+ for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut;
+ pPrev = pCut, pCut = pCut->pNext );
+ // connect these lists
+ *ppListNew = pLists[i];
+ ppListNew = &pPrev->pNext;
+ }
+ *ppListNew = NULL;
+ // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE
+ pListNew = Map_CutSortCuts( p, pTable, pListNew );
+ return pListNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Merges two lists of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutMergeLists2( Map_Man_t * p, Map_CutTable_t * pTable,
+ Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 )
+{
+ Map_Node_t * ppNodes[6];
+ Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL };
+ Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2;
+ int nNodes, Counter, i;
+
+ // prepare the manager for the cut computation
+ Map_CutTableRestart( pTable );
+ // go through the cut pairs
+ Counter = 0;
+ for ( pTemp1 = pList1; pTemp1; pTemp1 = pTemp1->pNext )
+ for ( pTemp2 = pList2; pTemp2; pTemp2 = pTemp2->pNext )
+ {
+ // check if k-feasible cut exists
+ nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax );
+ if ( nNodes == 0 )
+ continue;
+ // consider the cut for possible addition to the set of new cuts
+ pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes );
+ if ( pCut == NULL )
+ continue;
+ // add data to the cut
+ pCut->pOne = Map_CutNotCond( pTemp1, fComp1 );
+ pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 );
+ // add it to the corresponding list
+ pCut->pNext = pLists[pCut->nLeaves];
+ pLists[pCut->nLeaves] = pCut;
+ // count this cut and quit if limit is reached
+ Counter++;
+ if ( Counter == MAP_CUTS_MAX_COMPUTE )
+ goto QUITS;
+ }
+QUITS :
+ // combine all the lists into one
+ pListNew = NULL;
+ ppListNew = &pListNew;
+ for ( i = 1; i <= p->nVarsMax; i++ )
+ {
+ if ( pLists[i] == NULL )
+ continue;
+ // find the last entry
+ for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut;
+ pPrev = pCut, pCut = pCut->pNext );
+ // connect these lists
+ *ppListNew = pLists[i];
+ ppListNew = &pPrev->pNext;
+ }
+ *ppListNew = NULL;
+ // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE
+ pListNew = Map_CutSortCuts( p, pTable, pListNew );
+ return pListNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two cuts.]
+
+ Description [Returns the number of nodes in the resulting cut, or 0 if the
+ cut is infeasible. Returns the resulting nodes in the array ppNodes[].]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax )
+{
+ Map_Node_t * pNodeTemp;
+ int nTotal, i, k, min, fMismatch;
+
+ // check the special case when at least of the cuts is the largest
+ if ( pCut1->nLeaves == nNodesMax )
+ {
+ if ( pCut2->nLeaves == nNodesMax )
+ {
+ // return 0 if the cuts are different
+ for ( i = 0; i < nNodesMax; i++ )
+ if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] )
+ return 0;
+ // return nNodesMax if they are the same
+ for ( i = 0; i < nNodesMax; i++ )
+ ppNodes[i] = pCut1->ppLeaves[i];
+ return nNodesMax;
+ }
+ else if ( pCut2->nLeaves == nNodesMax - 1 )
+ {
+ // return 0 if the cuts are different
+ fMismatch = 0;
+ for ( i = 0; i < nNodesMax; i++ )
+ if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] )
+ {
+ if ( fMismatch == 1 )
+ return 0;
+ fMismatch = 1;
+ }
+ // return nNodesMax if they are the same
+ for ( i = 0; i < nNodesMax; i++ )
+ ppNodes[i] = pCut1->ppLeaves[i];
+ return nNodesMax;
+ }
+ }
+ else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax )
+ {
+ // return 0 if the cuts are different
+ fMismatch = 0;
+ for ( i = 0; i < nNodesMax; i++ )
+ if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] )
+ {
+ if ( fMismatch == 1 )
+ return 0;
+ fMismatch = 1;
+ }
+ // return nNodesMax if they are the same
+ for ( i = 0; i < nNodesMax; i++ )
+ ppNodes[i] = pCut2->ppLeaves[i];
+ return nNodesMax;
+ }
+
+ // count the number of unique entries in pCut2
+ nTotal = pCut1->nLeaves;
+ for ( i = 0; i < pCut2->nLeaves; i++ )
+ {
+ // try to find this entry among the leaves of pCut1
+ for ( k = 0; k < pCut1->nLeaves; k++ )
+ if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] )
+ break;
+ if ( k < pCut1->nLeaves ) // found
+ continue;
+ // we found a new entry to add
+ if ( nTotal == nNodesMax )
+ return 0;
+ ppNodes[nTotal++] = pCut2->ppLeaves[i];
+ }
+ // we know that the feasible cut exists
+
+ // add the starting entries
+ for ( k = 0; k < pCut1->nLeaves; k++ )
+ ppNodes[k] = pCut1->ppLeaves[k];
+
+ // selection-sort the entries
+ for ( i = 0; i < nTotal - 1; i++ )
+ {
+ min = i;
+ for ( k = i+1; k < nTotal; k++ )
+ if ( ppNodes[k] < ppNodes[min] )
+ min = k;
+ pNodeTemp = ppNodes[i];
+ ppNodes[i] = ppNodes[min];
+ ppNodes[min] = pNodeTemp;
+ }
+
+ return nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the union of the two lists of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 )
+{
+ Map_Cut_t * pTemp, * pRoot;
+ // find the last cut in the first list
+ pRoot = pList1;
+ Map_ListForEachCut( pList1, pTemp )
+ pRoot = pTemp;
+ // attach the non-trival part of the second cut to the end of the first
+ assert( pRoot->pNext == NULL );
+ pRoot->pNext = pList2->pNext;
+ pList2->pNext = NULL;
+ return pList1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks whether the given cut belongs to the list.]
+
+ Description [This procedure takes most of the runtime in the cut
+ computation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes )
+{
+ Map_Cut_t * pTemp;
+ int i;
+ for ( pTemp = pList; pTemp; pTemp = pTemp->pNext )
+ {
+ for ( i = 0; i < nNodes; i++ )
+ if ( pTemp->ppLeaves[i] != ppNodes[i] )
+ break;
+ if ( i == nNodes )
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts all the cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingCountAllCuts( Map_Man_t * pMan )
+{
+ Map_Node_t * pNode;
+ Map_Cut_t * pCut;
+ int i, nCuts;
+ nCuts = 0;
+ for ( i = 0; i < pMan->nBins; i++ )
+ for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext )
+ for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext )
+ if ( pCut->nLeaves > 1 ) // skip the elementary cuts
+ nCuts++;
+ return nCuts;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the cuts in the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot )
+{
+ Map_Cut_t * pTemp;
+ int Counter;
+ for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
+ {
+ printf( "%2d : ", Counter + 1 );
+ Map_CutPrint_( pMan, pTemp, pRoot );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the cuts in the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot )
+{
+ Map_Cut_t * pTemp;
+ int Counter;
+ for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ )
+ {
+ printf( "%2d : ", Counter + 1 );
+ Map_CutPrint_( pMan, pTemp, pRoot );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot )
+{
+ int i;
+ printf( "(%3d) {", pRoot->Num );
+ for ( i = 0; i < pMan->nVarsMax; i++ )
+ if ( pCut->ppLeaves[i] )
+ printf( " %3d", pCut->ppLeaves[i]->Num );
+ printf( " }\n" );
+}
+
+
+
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the hash table to canonicize cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan )
+{
+ Map_CutTable_t * p;
+ // allocate the table
+ p = ALLOC( Map_CutTable_t, 1 );
+ memset( p, 0, sizeof(Map_CutTable_t) );
+ p->nBins = Cudd_Prime( 10 * MAP_CUTS_MAX_COMPUTE );
+ p->pBins = ALLOC( Map_Cut_t *, p->nBins );
+ memset( p->pBins, 0, sizeof(Map_Cut_t *) * p->nBins );
+ p->pCuts = ALLOC( int, 2 * MAP_CUTS_MAX_COMPUTE );
+ p->pArray = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
+ p->pCuts1 = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
+ p->pCuts2 = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutTableStop( Map_CutTable_t * p )
+{
+ free( p->pCuts1 );
+ free( p->pCuts2 );
+ free( p->pArray );
+ free( p->pBins );
+ free( p->pCuts );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the hash value of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes )
+{
+ unsigned uRes;
+ int i;
+ uRes = 0;
+ for ( i = 0; i < nNodes; i++ )
+ uRes += s_HashPrimes[i] * ppNodes[i]->Num;
+ return uRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the table for the available cut.]
+
+ Description [Returns -1 if the same cut is found. Returns the index
+ of the cell where the cut should be added, if it does not exist.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes )
+{
+ Map_Cut_t * pCut;
+ unsigned Key;
+ int b, i;
+
+ Key = Map_CutTableHash(ppNodes, nNodes) % p->nBins;
+ for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins )
+ {
+ pCut = p->pBins[b];
+ if ( pCut->nLeaves != nNodes )
+ continue;
+ for ( i = 0; i < nNodes; i++ )
+ if ( pCut->ppLeaves[i] != ppNodes[i] )
+ break;
+ if ( i == nNodes )
+ return -1;
+ }
+ return b;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the hash table to canonicize cuts.]
+
+ Description [Considers addition of the cut to the hash table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes )
+{
+ Map_Cut_t * pCut;
+ int Place, i;
+// int clk;
+ // check the cut
+ Place = Map_CutTableLookup( p, ppNodes, nNodes );
+ if ( Place == -1 )
+ return NULL;
+ assert( nNodes > 0 );
+ // create the new cut
+//clk = clock();
+ pCut = Map_CutAlloc( pMan );
+//pMan->time1 += clock() - clk;
+ pCut->nLeaves = nNodes;
+// pCut->fLevel = 0;
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pCut->ppLeaves[i] = ppNodes[i];
+// pCut->fLevel += ppNodes[i]->Level;
+ }
+// pCut->fLevel /= nNodes;
+ // add the cut to the table
+ assert( p->pBins[Place] == NULL );
+ p->pBins[Place] = pCut;
+ // add the cut to the new list
+ p->pCuts[ p->nCuts++ ] = Place;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the table to be used with other cuts.]
+
+ Description [Restarts the table by cleaning the info about cuts stored
+ when the previous node was considered.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutTableRestart( Map_CutTable_t * p )
+{
+ int i;
+ for ( i = 0; i < p->nCuts; i++ )
+ {
+ assert( p->pBins[ p->pCuts[i] ] );
+ p->pBins[ p->pCuts[i] ] = NULL;
+ }
+ p->nCuts = 0;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares the cuts by the number of leaves and then by delay.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CutSortCutsCompare( Map_Cut_t ** pC1, Map_Cut_t ** pC2 )
+{
+ if ( (*pC1)->nLeaves < (*pC2)->nLeaves )
+ return -1;
+ if ( (*pC1)->nLeaves > (*pC2)->nLeaves )
+ return 1;
+/*
+ if ( (*pC1)->fLevel < (*pC2)->fLevel )
+ return -1;
+ if ( (*pC1)->fLevel > (*pC2)->fLevel )
+ return 1;
+*/
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorts the cuts by average arrival time.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList )
+{
+ Map_Cut_t * pListNew;
+ int nCuts, i;
+// int clk;
+ // move the cuts from the list into the array
+ nCuts = Map_CutList2Array( p->pCuts1, pList );
+ assert( nCuts <= MAP_CUTS_MAX_COMPUTE );
+ // sort the cuts
+//clk = clock();
+ qsort( (void *)p->pCuts1, nCuts, sizeof(Map_Cut_t *),
+ (int (*)(const void *, const void *)) Map_CutSortCutsCompare );
+//pMan->time2 += clock() - clk;
+ // move them back into the list
+ if ( nCuts > MAP_CUTS_MAX_USE - 1 )
+ {
+ // free the remaining cuts
+ for ( i = MAP_CUTS_MAX_USE - 1; i < nCuts; i++ )
+ Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] );
+ // update the number of cuts
+ nCuts = MAP_CUTS_MAX_USE - 1;
+ }
+ pListNew = Map_CutArray2List( p->pCuts1, nCuts );
+ return pListNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves the nodes from the list into the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList )
+{
+ int i;
+ for ( i = 0; pList; pList = pList->pNext, i++ )
+ pArray[i] = pList;
+ return i;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves the nodes from the array into the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts )
+{
+ Map_Cut_t * pListNew, ** ppListNew;
+ int i;
+ pListNew = NULL;
+ ppListNew = &pListNew;
+ for ( i = 0; i < nCuts; i++ )
+ {
+ // connect these lists
+ *ppListNew = pArray[i];
+ ppListNew = &pArray[i]->pNext;
+//printf( " %d(%.2f)", pArray[i]->nLeaves, pArray[i]->fLevel );
+ }
+//printf( "\n" );
+
+ *ppListNew = NULL;
+ return pListNew;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/mapper/mapperCutUtils.c b/src/map/mapper/mapperCutUtils.c
new file mode 100644
index 00000000..9f572e75
--- /dev/null
+++ b/src/map/mapper/mapperCutUtils.c
@@ -0,0 +1,273 @@
+/**CFile****************************************************************
+
+ FileName [mapperCutUtils.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutAlloc( Map_Man_t * p )
+{
+ Map_Cut_t * pCut;
+ Map_Match_t * pMatch;
+ pCut = (Map_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts );
+ memset( pCut, 0, sizeof(Map_Cut_t) );
+
+ pMatch = pCut->M;
+ pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned
+
+ pMatch = pCut->M + 1;
+ pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut )
+{
+ if ( pCut )
+ Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase )
+{
+ int i;
+ printf( "CUT: Delay = (%4.2f, %4.2f). Area = %4.2f. Nodes = %d -> {",
+ pCut->M[fPhase].tArrive.Rise, pCut->M[fPhase].tArrive.Fall, pCut->M[fPhase].AreaFlow, pRoot->Num );
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ printf( " %d", pCut->ppLeaves[i]->Num );
+ printf( " } \n" );
+}
+
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase )
+{
+ assert( pCut->M[fPhase].pSuperBest );
+ return pCut->M[fPhase].pSuperBest->Area;
+}
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf )
+{
+ assert( pCut->M[fPhase].pSuperBest );
+ return (( pCut->M[fPhase].uPhaseBest & (1<<iLeaf) ) == 0);
+}
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+int Map_NodeGetLeafPhase( Map_Node_t * pNode, int fPhase, int iLeaf )
+{
+ assert( pNode->pCutBest[fPhase]->M[fPhase].pSuperBest );
+ return (( pNode->pCutBest[fPhase]->M[fPhase].uPhaseBest & (1<<iLeaf) ) == 0);
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Cut_t * Map_CutListAppend( Map_Cut_t * pSetAll, Map_Cut_t * pSets )
+{
+ Map_Cut_t * pPrev, * pTemp;
+ if ( pSetAll == NULL )
+ return pSets;
+ if ( pSets == NULL )
+ return pSetAll;
+ // find the last one
+ for ( pTemp = pSets; pTemp; pTemp = pTemp->pNext )
+ pPrev = pTemp;
+ // append all the end of the current set
+ assert( pPrev->pNext == NULL );
+ pPrev->pNext = pSetAll;
+ return pSets;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave )
+{
+ Map_Cut_t * pNext, * pTemp;
+ for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL;
+ pTemp;
+ pTemp = pNext, pNext = pNext? pNext->pNext : NULL )
+ if ( pTemp != pSave )
+ Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CutListCount( Map_Cut_t * pSets )
+{
+ Map_Cut_t * pTemp;
+ int i;
+ for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ );
+ return i;
+}
+
+#if 0
+
+/**function*************************************************************
+
+ synopsis [Removes the fanouts of the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
+{
+ Map_NodeVec_t * vFanouts;
+ int i, k;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ vFanouts = pCut->ppLeaves[i]->vFanouts;
+ for ( k = 0; k < vFanouts->nSize; k++ )
+ if ( vFanouts->pArray[k] == pNode )
+ break;
+ assert( k != vFanouts->nSize );
+ for ( k++; k < vFanouts->nSize; k++ )
+ vFanouts->pArray[k-1] = vFanouts->pArray[k];
+ vFanouts->nSize--;
+ }
+}
+
+/**function*************************************************************
+
+ synopsis [Removes the fanouts of the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
+{
+ int i;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ Map_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode );
+}
+
+#endif
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperFanout.c b/src/map/mapper/mapperFanout.c
new file mode 100644
index 00000000..7bd92ed9
--- /dev/null
+++ b/src/map/mapper/mapperFanout.c
@@ -0,0 +1,139 @@
+/**CFile****************************************************************
+
+ FileName [mapperFanout.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperFanout.c,v 1.5 2005/01/23 06:59:43 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Add the fanout to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout )
+{
+ Map_Node_t * pPivot;
+
+ // pFanins is a fanin of pFanout
+ assert( !Map_IsComplement(pFanin) );
+ assert( !Map_IsComplement(pFanout) );
+ assert( Map_Regular(pFanout->p1) == pFanin || Map_Regular(pFanout->p2) == pFanin );
+
+ pPivot = pFanin->pFanPivot;
+ if ( pPivot == NULL )
+ {
+ pFanin->pFanPivot = pFanout;
+ return;
+ }
+
+ if ( Map_Regular(pPivot->p1) == pFanin )
+ {
+ if ( Map_Regular(pFanout->p1) == pFanin )
+ {
+ pFanout->pFanFanin1 = pPivot->pFanFanin1;
+ pPivot->pFanFanin1 = pFanout;
+ }
+ else // if ( Map_Regular(pFanout->p2) == pFanin )
+ {
+ pFanout->pFanFanin2 = pPivot->pFanFanin1;
+ pPivot->pFanFanin1 = pFanout;
+ }
+ }
+ else // if ( Map_Regular(pPivot->p2) == pFanin )
+ {
+ assert( Map_Regular(pPivot->p2) == pFanin );
+ if ( Map_Regular(pFanout->p1) == pFanin )
+ {
+ pFanout->pFanFanin1 = pPivot->pFanFanin2;
+ pPivot->pFanFanin2 = pFanout;
+ }
+ else // if ( Map_Regular(pFanout->p2) == pFanin )
+ {
+ pFanout->pFanFanin2 = pPivot->pFanFanin2;
+ pPivot->pFanFanin2 = pFanout;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the fanout to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove )
+{
+ Map_Node_t * pFanout, * pFanout2, ** ppFanList;
+ // start the linked list of fanouts
+ ppFanList = &pFanin->pFanPivot;
+ // go through the fanouts
+ Map_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 )
+ {
+ // skip the fanout-to-remove
+ if ( pFanout == pFanoutToRemove )
+ continue;
+ // add useful fanouts to the list
+ *ppFanList = pFanout;
+ ppFanList = Map_NodeReadNextFanoutPlace( pFanin, pFanout );
+ }
+ *ppFanList = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of fanouts of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_NodeGetFanoutNum( Map_Node_t * pNode )
+{
+ Map_Node_t * pFanout;
+ int Counter = 0;
+ Map_NodeForEachFanout( pNode, pFanout )
+ Counter++;
+ return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperGENERIC.c b/src/map/mapper/mapperGENERIC.c
new file mode 100644
index 00000000..4df5ee51
--- /dev/null
+++ b/src/map/mapper/mapperGENERIC.c
@@ -0,0 +1,46 @@
+/**CFile****************************************************************
+
+ FileName [mapper__.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: mapper__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperInt.h b/src/map/mapper/mapperInt.h
new file mode 100644
index 00000000..c5ecce73
--- /dev/null
+++ b/src/map/mapper/mapperInt.h
@@ -0,0 +1,475 @@
+/**CFile****************************************************************
+
+ FileName [mapperInt.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $]
+
+***********************************************************************/
+
+#ifndef __MAPPER_INT_H__
+#define __MAPPER_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+//#include "leaks.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include "cuddInt.h"
+#include "main.h"
+#include "mio.h"
+#include "mapper.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit masks
+#define MAP_MASK(n) ((~((unsigned)0)) >> (32-(n)))
+#define MAP_FULL (~((unsigned)0))
+#define MAP_NO_VAR (-9999.0)
+
+// maximum/minimum operators
+#define MAP_MIN(a,b) (((a) < (b))? (a) : (b))
+#define MAP_MAX(a,b) (((a) > (b))? (a) : (b))
+
+// the small and large numbers (min/max float are 1.17e-38/3.40e+38)
+#define MAP_FLOAT_LARGE ((float)(FLT_MAX/10))
+#define MAP_FLOAT_SMALL ((float)1.0e-03)
+
+// generating random unsigned (#define RAND_MAX 0x7fff)
+#define MAP_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+// internal macros to work with cuts
+#define Map_CutIsComplement(p) (((int)((long) (p) & 01)))
+#define Map_CutRegular(p) ((Map_Cut_t *)((unsigned)(p) & ~01))
+#define Map_CutNot(p) ((Map_Cut_t *)((long)(p) ^ 01))
+#define Map_CutNotCond(p,c) ((Map_Cut_t *)((long)(p) ^ (c)))
+
+// internal macros for referencing of nodes
+#define Map_NodeReadRef(p) ((Map_Regular(p))->nRefs)
+#define Map_NodeRef(p) ((Map_Regular(p))->nRefs++)
+
+// macros to get hold of the bits in the support info
+#define Map_InfoSetVar(p,i) (p[(i)>>5] |= (1<<((i) & 31)))
+#define Map_InfoRemVar(p,i) (p[(i)>>5] &= ~(1<<((i) & 31)))
+#define Map_InfoFlipVar(p,i) (p[(i)>>5] ^= (1<<((i) & 31)))
+#define Map_InfoReadVar(p,i) ((p[(i)>>5] & (1<<((i) & 31))) > 0)
+
+// returns the complemented attribute of the node
+#define Map_NodeIsSimComplement(p) (Map_IsComplement(p)? !(Map_Regular(p)->fInv) : (p)->fInv)
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the mapping manager
+struct Map_ManStruct_t_
+{
+ // the mapping graph
+ Map_Node_t ** pBins; // the table of nodes hashed by their children
+ int nBins; // the size of the table
+ Map_Node_t ** pInputs; // the array of inputs
+ int nInputs; // the number of inputs
+ Map_Node_t ** pOutputs; // the array of outputs
+ int nOutputs; // the number of outputs
+ int nNodes; // the total number of nodes
+ Map_Node_t * pConst1; // the constant 1 node
+ Map_NodeVec_t * vAnds; // the array of nodes in the DFS order
+ Map_NodeVec_t * vNodesAll; // the array of all nodes
+ Map_NodeVec_t * vNodesTemp; // the array of all nodes
+ Map_NodeVec_t * vMapping; // the array of internal nodes used in the mapping
+
+ // info about the original circuit
+ char ** ppOutputNames; // the primary output names
+ Map_Time_t * pInputArrivals;// the PI arrival times
+
+ // mapping parameters
+ int nVarsMax; // the max number of variables
+ int fAreaRecovery; // the flag to enable area recovery
+ int fVerbose; // the verbosiness flag
+ int fMappingMode; // set to 1 when doing area
+ float fRequiredGlo; // the global required times
+ float fEpsilon; // the epsilon used to compare floats
+ float AreaBase; // the area after delay-oriented mapping
+ float AreaFinal; // the area after delay-oriented mapping
+ int nIterations; // How many matching passes to do
+ bool fObeyFanoutLimits;// Should mapper try to obey fanout limits or not
+ float DelayTarget; // the required times set by the user
+ int nTravIds; // the traversal counter
+
+ // the supergate library
+ Map_SuperLib_t * pSuperLib; // the current supergate library
+ unsigned uTruths[6][2]; // the elementary truth tables
+ unsigned uTruthsLarge[10][32]; // the elementary truth tables
+ int nCounts[32]; // the counter of minterms
+ int nCountsBest[32];// the counter of minterms
+
+ // simulation info from the FRAIG manager
+ int nSimRounds; // the number of words in the simulation info
+ unsigned ** pSimInfo; // the simulation info for each PI
+
+ // don't-care computation
+ Map_NodeVec_t * vInside; // the array of nodes for SDC computation
+ Map_NodeVec_t * vFanins; // the array of nodes for SDC computation
+
+ // the memory managers
+ Extra_MmFixed_t * mmNodes; // the memory manager for nodes
+ Extra_MmFixed_t * mmCuts; // the memory manager for cuts
+
+ // various statistical variables
+ int nChoiceNodes; // the number of choice nodes
+ int nChoices; // the number of all choices
+ int nCanons; // the number of times N-canonical form was computed
+ int nMatches; // the number of times supergate matching was performed
+ int nPhases; // the number of phases considered during matching
+ int nFanoutViolations; // the number of nodes in mapped circuit violating fanout
+
+ // runtime statistics
+ int timeToMap; // time to transfer to the mapping structure
+ int timeCuts; // time to compute k-feasible cuts
+ int timeTruth; // time to compute the truth table for each cut
+ int timeMatch; // time to perform matching for each node
+ int timeArea; // time to recover area after delay oriented mapping
+ int timeSweep; // time to perform technology dependent sweep
+ int timeToNet; // time to transfer back to the network
+ int timeTotal; // the total mapping time
+ int time1; // time to transfer to the mapping structure
+ int time2; // time to transfer to the mapping structure
+ int time3; // time to transfer to the mapping structure
+};
+
+// the supergate library
+struct Map_SuperLibStruct_t_
+{
+ // general info
+ char * pName; // the name of the supergate library
+ Mio_Library_t * pGenlib; // the generic library
+
+ // other info
+ int nVarsMax; // the max number of variables
+ int nSupersAll; // the total number of supergates
+ int nSupersReal; // the total number of supergates
+ int nLines; // the total number of lines in the supergate file
+ bool fVerbose; // the verbosity flag
+
+ // hash tables
+ Map_Super_t ** ppSupers; // the array of supergates
+ Map_HashTable_t * tTableC; // the table mapping N-canonical forms into supergates
+ Map_HashTable_t * tTable; // the table mapping truth tables into supergates
+
+ // data structures for N-canonical form computation
+ unsigned uTruths[6][2]; // the elementary truth tables
+ unsigned uMask[2]; // the mask for the truth table
+
+ // the invertor
+ Mio_Gate_t * pGateInv; // the pointer to the intertor gate
+ Map_Time_t tDelayInv; // the delay of the inverter
+ float AreaInv; // the area of the inverter
+ Map_Super_t * pSuperInv; // the supergate representing the inverter
+
+ // the memory manager for the internal table
+ Extra_MmFixed_t * mmSupers; // the mamory manager for supergates
+ Extra_MmFixed_t * mmEntries; // the memory manager for the entries
+ Extra_MmFlex_t * mmForms; // the memory manager for formulas
+};
+
+// the mapping node
+struct Map_NodeStruct_t_
+{
+ // general information about the node
+ Map_Man_t * p; // the mapping manager
+ Map_Node_t * pNext; // the next node in the hash table
+ int Num; // the unique number of this node
+ int TravId; // the traversal ID (use to avoid cleaning marks)
+ int nRefs; // the number of references (fanouts) of the given node
+ unsigned fMark0 : 1; // the mark used for traversals
+ unsigned fMark1 : 1; // the mark used for traversals
+ unsigned fUsed : 1; // the mark to mark the node or its fanins
+ unsigned fInv : 1; // the complemented attribute for the equivalent nodes
+ unsigned fInvert: 1; // the flag to denote the use of interter
+ unsigned Level :16; // the level of the given node
+ unsigned NumTemp:10; // the level of the given node
+ int nRefAct[3]; // estimated fanout for current covering phase, neg and pos and sum
+ float nRefEst[3]; // actual fanout for previous covering phase, neg and pos and sum
+
+ // the successors of this node
+ Map_Node_t * p1; // the first child
+ Map_Node_t * p2; // the second child
+ Map_Node_t * pNextE; // the next functionally equivalent node
+ Map_Node_t * pRepr; // the representative of the functionally equivalent class
+// Map_NodeVec_t * vFanouts; // the array of fanouts of the node
+
+ // representation of node's fanouts
+ Map_Node_t * pFanPivot; // the first fanout of this node
+ Map_Node_t * pFanFanin1; // the next fanout of p1
+ Map_Node_t * pFanFanin2; // the next fanout of p2
+
+ unsigned * pSims; // the simulation info
+ float SwitchProb; // the switching probability
+
+ // the delay information
+ Map_Time_t tArrival[2]; // the best arrival time of the neg (0) and pos (1) phases
+ Map_Time_t tRequired[2]; // the required time of the neg (0) and pos (1) phases
+
+ // misc information
+ Map_Cut_t * pCutOld[2]; // the old mapping for neg and pos phase
+ Map_Cut_t * pCutBest[2]; // the best mapping for neg and pos phase
+ Map_Cut_t * pCuts; // mapping choices for the node (elementary comes first)
+ char * pData0; // temporary storage for the corresponding network node
+ char * pData1; // temporary storage for the corresponding network node
+};
+
+// the match of the cut
+struct Map_MatchStruct_t_
+{
+ // information used for matching
+ Map_Super_t * pSupers;
+ unsigned uPhase;
+ // information about the best selected match
+ unsigned uPhaseBest; // the best phase (the EXOR of match's phase and gate's phase)
+ Map_Super_t * pSuperBest; // the best supergate matched
+ // the parameters of the match
+ Map_Time_t tArrive; // the arrival time of this match
+ float AreaFlow; // the area flow or area of this match
+};
+
+// the cuts used for matching
+struct Map_CutStruct_t_
+{
+ Map_Cut_t * pNext; // the pointer to the next cut in the list
+ Map_Cut_t * pOne; // the father of this cut
+ Map_Cut_t * pTwo; // the mother of this cut
+ Map_Node_t * ppLeaves[6]; // the leaves of this cut
+ char nLeaves; // the number of leaves
+ char nVolume; // the volume of this cut
+ char fMark; // the mark to denote visited cut
+ char Phase; // the mark to denote complemented cut
+// float fLevel; // the average level of the fanins
+
+ unsigned uTruthTemp[2]; // the temporary truth table used to derive other cuts
+ unsigned uTruthZero[2]; // the temporary truth table used to derive other cuts
+ unsigned uTruthDc[2]; // the don't-cares (SDCs) computed for this cut
+
+ Map_Match_t M[2]; // the matches for the positive/negative phase
+};
+
+// the supergate internally represented
+struct Map_SuperStruct_t_
+{
+ int Num; // the ID of the supergate
+ unsigned fSuper : 1; // the flag to distinquish a real super from a fake one
+ unsigned fExclude: 1; // the flag if set causes gate to be excluded from being used for mapping
+ unsigned nFanins : 3; // the number of inputs
+ unsigned nGates : 3; // the number of gates inside this supergate
+ unsigned nFanLimit: 4; // the max number of fanout count
+ unsigned nSupers : 16; // the number of supergates in the list
+ unsigned nPhases : 4; // the number of phases for matching with canonical form
+ unsigned char uPhases[4]; // the maximum of 4 phases for matching with canonical form
+ int nUsed; // the number of times the supergate is used
+ Map_Super_t * pFanins[6]; // the fanins of the gate
+ Mio_Gate_t * pRoot; // the root gate
+ unsigned uTruth[2]; // the truth table
+ Map_Time_t tDelaysR[6]; // the pin-to-pin delay constraints for the rise of the output
+ Map_Time_t tDelaysF[6]; // the pin-to-pin delay constraints for the rise of the output
+ Map_Time_t tDelayMax; // the maximum delay
+ float Area; // the area
+ char * pFormula; // the symbolic formula
+ Map_Super_t * pNext; // the pointer to the next super in the list
+};
+
+// the vector of nodes
+struct Map_NodeVecStruct_t_
+{
+ Map_Node_t ** pArray; // the array of nodes
+ int nSize; // the number of entries in the array
+ int nCap; // the number of allocated entries
+};
+
+// the hash table
+struct Map_HashTableStruct_t_
+{
+ Map_HashEntry_t ** pBins; // the table bins
+ int nBins; // the size of the table
+ int nEntries; // the total number of entries in the table
+ Extra_MmFixed_t * mmMan; // the memory manager for entries
+};
+
+// the entry in the hash table
+struct Map_HashEntryStruct_t_
+{
+ unsigned uTruth[2]; // the truth table for 6-var function
+ unsigned uPhase; // the phase to tranform it into the canonical form
+ Map_Super_t * pGates; // the linked list of matching supergates
+ Map_HashEntry_t * pNext; // the next entry in the hash table
+};
+
+// getting hold of the next fanout of the node
+#define Map_NodeReadNextFanout( pNode, pFanout ) \
+ ( ( pFanout == NULL )? NULL : \
+ ((Map_Regular((pFanout)->p1) == (pNode))? \
+ (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) )
+
+// getting hold of the place where the next fanout will be attached
+#define Map_NodeReadNextFanoutPlace( pNode, pFanout ) \
+ ( (Map_Regular((pFanout)->p1) == (pNode))? \
+ &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 )
+
+// iterator through the fanouts of the node
+#define Map_NodeForEachFanout( pNode, pFanout ) \
+ for ( pFanout = (pNode)->pFanPivot; pFanout; \
+ pFanout = Map_NodeReadNextFanout(pNode, pFanout) )
+
+// safe iterator through the fanouts of the node
+#define Map_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \
+ for ( pFanout = (pNode)->pFanPivot, \
+ pFanout2 = Map_NodeReadNextFanout(pNode, pFanout); \
+ pFanout; \
+ pFanout = pFanout2, \
+ pFanout2 = Map_NodeReadNextFanout(pNode, pFanout) )
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mapperCanon.c =============================================================*/
+/*=== mapperCut.c ===============================================================*/
+extern void Map_MappingCuts( Map_Man_t * p );
+extern int Map_MappingCountAllCuts( Map_Man_t * p );
+/*=== mapperCutDcs.c ===============================================================*/
+extern void Map_ComputeDcs( Map_Man_t * p );
+extern unsigned Map_ComputeIsop_rec( Map_Man_t * p, unsigned uF, unsigned uFD, int iVar, int nVars, int fDir );
+/*=== mapperCutUtils.c ===============================================================*/
+extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p );
+extern void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut );
+extern void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase );
+extern float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase );
+extern int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf );
+extern int Map_NodeGetLeafPhase( Map_Node_t * pNode, int fPhase, int iLeaf );
+extern Map_Cut_t * Map_CutListAppend( Map_Cut_t * pSetAll, Map_Cut_t * pSets );
+extern void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave );
+extern int Map_CutListCount( Map_Cut_t * pSets );
+extern void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase );
+extern void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase );
+/*=== mapperFanout.c =============================================================*/
+extern void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout );
+extern void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove );
+extern int Map_NodeGetFanoutNum( Map_Node_t * pNode );
+/*=== mapperLib.c ============================================================*/
+extern Map_SuperLib_t * Map_SuperLibCreate( char * pFileName, char * pExcludeFile, bool fAlgorithm, bool fVerbose );
+extern void Map_SuperLibFree( Map_SuperLib_t * p );
+/*=== mapperMatch.c ===============================================================*/
+extern int Map_MappingMatches( Map_Man_t * p );
+extern float Map_MappingCombinePhases( Map_Man_t * p );
+extern void Map_MatchClean( Map_Match_t * pMatch );
+extern int Map_MatchCompare( Map_Man_t * pMan, Map_Match_t * pM1, Map_Match_t * pM2, int fDoingArea );
+/*=== mapperRefs.c =============================================================*/
+extern int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase );
+extern float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase );
+extern void Map_MappingEstimateRefsInit( Map_Man_t * p );
+extern void Map_MappingEstimateRefs( Map_Man_t * p );
+extern float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase );
+extern float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase );
+extern float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase );
+extern float Map_CutRef( Map_Cut_t * pCut, int fPhase );
+extern float Map_CutDeref( Map_Cut_t * pCut, int fPhase );
+extern void Map_MappingSetRefs( Map_Man_t * pMan );
+extern float Map_MappingGetArea( Map_Man_t * pMan, Map_NodeVec_t * vMapping );
+/*=== mapperShow.c =============================================================*/
+extern void Map_MappingShow( Map_Man_t * pMan, char * pFileName );
+/*=== mapperTree.c ===============================================================*/
+extern int Map_LibraryReadTree( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile );
+extern void Map_LibraryPrintTree( Map_SuperLib_t * pLib );
+/*=== mapperSuper.c ===============================================================*/
+extern int Map_LibraryRead( Map_SuperLib_t * p, char * pFileName );
+extern void Map_LibraryPrintSupergate( Map_Super_t * pGate );
+/*=== mapperTable.c ============================================================*/
+extern Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib );
+extern void Map_SuperTableFree( Map_HashTable_t * p );
+extern int Map_SuperTableInsertC( Map_HashTable_t * pLib, unsigned uTruthC[], Map_Super_t * pGate );
+extern int Map_SuperTableInsert( Map_HashTable_t * pLib, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase );
+extern Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase );
+extern void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax );
+extern void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax );
+/*=== mapperTime.c =============================================================*/
+extern float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstCaseLimit );
+extern void Map_TimeCutComputeArrival_rec( Map_Cut_t * pCut, int fPhase );
+extern float Map_TimeComputeArrivalMax( Map_Man_t * p );
+extern void Map_TimeComputeRequiredGlobal( Map_Man_t * p );
+extern void Map_TimeComputeRequired( Map_Man_t * p, float fRequired );
+extern float Map_TimeNodeFanoutDelay( Map_Node_t * pNode, int fPhase );
+extern float Map_TimeCutFanoutDelay( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase );
+extern float Map_TimeMatchWithInverter( Map_Man_t * p, Map_Match_t * pMatch );
+/*=== mapperTruth.c ===============================================================*/
+extern void Map_MappingTruths( Map_Man_t * pMan );
+extern int Map_TruthsCutDontCare( Map_Man_t * pMan, Map_Cut_t * pCut, unsigned * uTruthDc );
+extern int Map_TruthCountOnes( unsigned * uTruth, int nLeaves );
+extern int Map_TruthDetectTwoFirst( unsigned * uTruth, int nLeaves );
+/*=== mapperUtils.c ===============================================================*/
+extern Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv );
+extern Map_NodeVec_t * Map_MappingDfsNodes( Map_Man_t * pMan, Map_Node_t ** ppNodes, int nNodes, int fEquiv );
+
+extern void Map_MappingDfsMarked1_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fFirst );
+extern void Map_MappingDfsMarked2_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, Map_NodeVec_t * vBoundary, int fFirst );
+
+extern int Map_MappingCountLevels( Map_Man_t * pMan );
+extern void Map_MappingUnmark( Map_Man_t * pMan );
+extern void Map_MappingMark_rec( Map_Node_t * pNode );
+extern void Map_MappingUnmark_rec( Map_Node_t * pNode );
+extern void Map_MappingPrintOutputArrivals( Map_Man_t * p );
+extern void Map_MappingSetupMask( unsigned uMask[], int nVarsMax );
+extern int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol );
+extern float Map_MappingGetAreaFlow( Map_Man_t * p );
+extern void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes );
+extern int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes );
+extern void Map_MappingExpandTruth( unsigned uTruth[2], int nVars );
+extern float Map_MappingPrintSwitching( Map_Man_t * pMan );
+extern void Map_MappingSetPlacementInfo( Map_Man_t * p );
+extern float Map_MappingPrintWirelength( Map_Man_t * p );
+extern void Map_MappingWireReport( Map_Man_t * p );
+extern float Map_MappingComputeDelayWithFanouts( Map_Man_t * p );
+extern int Map_MappingGetMaxLevel( Map_Man_t * pMan );
+extern void Map_MappingSetChoiceLevels( Map_Man_t * pMan );
+extern void Map_MappingReportChoices( Map_Man_t * pMan );
+/*=== mapperVec.c =============================================================*/
+extern Map_NodeVec_t * Map_NodeVecAlloc( int nCap );
+extern void Map_NodeVecFree( Map_NodeVec_t * p );
+extern Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p );
+extern int Map_NodeVecReadSize( Map_NodeVec_t * p );
+extern void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin );
+extern void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew );
+extern void Map_NodeVecClear( Map_NodeVec_t * p );
+extern void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry );
+extern int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry );
+extern Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p );
+extern void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry );
+extern void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry );
+extern Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i );
+extern void Map_NodeVecSortByLevel( Map_NodeVec_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/map/mapper/mapperLib.c b/src/map/mapper/mapperLib.c
new file mode 100644
index 00000000..5530f8cb
--- /dev/null
+++ b/src/map/mapper/mapperLib.c
@@ -0,0 +1,233 @@
+/**CFile****************************************************************
+
+ FileName [mapperLib.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperLib.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads in the supergate library and prepares it for use.]
+
+ Description [The supergates library comes in a .super file. This file
+ contains descriptions of supergates along with some relevant information.
+ This procedure reads the supergate file, canonicizes the supergates,
+ and constructs an additional lookup table, which can be used to map
+ truth tables of the cuts into the pair (phase, supergate). The phase
+ indicates how the current truth table should be phase assigned to
+ match the canonical form of the supergate. The resulting phase is the
+ bitwise EXOR of the phase needed to canonicize the supergate and the
+ phase needed to transform the truth table into its canonical form.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_SuperLib_t * Map_SuperLibCreate( char * pFileName, char * pExcludeFile, bool fAlgorithm, bool fVerbose )
+{
+ Map_SuperLib_t * p;
+ int clk;
+
+ // start the supergate library
+ p = ALLOC( Map_SuperLib_t, 1 );
+ memset( p, 0, sizeof(Map_SuperLib_t) );
+ p->pName = pFileName;
+ p->fVerbose = fVerbose;
+ p->mmSupers = Extra_MmFixedStart( sizeof(Map_Super_t) );
+ p->mmEntries = Extra_MmFixedStart( sizeof(Map_HashEntry_t) );
+ p->mmForms = Extra_MmFlexStart();
+ Map_MappingSetupTruthTables( p->uTruths );
+
+ // start the hash table
+ p->tTableC = Map_SuperTableCreate( p );
+ p->tTable = Map_SuperTableCreate( p );
+
+ // read the supergate library from file
+clk = clock();
+ if ( fAlgorithm )
+ {
+ if ( !Map_LibraryReadTree( p, pFileName, pExcludeFile ) )
+ {
+ Map_SuperLibFree( p );
+ return NULL;
+ }
+ }
+ else
+ {
+ if ( pExcludeFile != 0 )
+ {
+ printf ("Error: Exclude file support not present for old format. Stop.\n");
+ return NULL;
+ }
+ if ( !Map_LibraryRead( p, pFileName ) )
+ {
+ Map_SuperLibFree( p );
+ return NULL;
+ }
+ }
+ assert( p->nVarsMax > 0 );
+
+ // report the stats
+if ( fVerbose ) {
+ printf( "Loaded %d unique %d-input supergates from \"%s\". ",
+ p->nSupersReal, p->nVarsMax, pFileName );
+ PRT( "Time", clock() - clk );
+}
+
+ // assign the interver parameters
+ p->pGateInv = Mio_LibraryReadInv( p->pGenlib );
+ p->tDelayInv.Rise = Mio_LibraryReadDelayInvRise( p->pGenlib );
+ p->tDelayInv.Fall = Mio_LibraryReadDelayInvFall( p->pGenlib );
+ p->tDelayInv.Worst = MAP_MAX( p->tDelayInv.Rise, p->tDelayInv.Fall );
+ p->AreaInv = Mio_LibraryReadAreaInv( p->pGenlib );
+
+ // assign the interver supergate
+ p->pSuperInv = (Map_Super_t *)Extra_MmFixedEntryFetch( p->mmSupers );
+ memset( p->pSuperInv, 0, sizeof(Map_Super_t) );
+ p->pSuperInv->Num = -1;
+ p->pSuperInv->nGates = 1;
+ p->pSuperInv->nFanins = 1;
+ p->pSuperInv->nFanLimit = 10;
+ p->pSuperInv->pFanins[0] = p->ppSupers[0];
+ p->pSuperInv->pRoot = p->pGateInv;
+ p->pSuperInv->Area = p->AreaInv;
+ p->pSuperInv->tDelayMax = p->tDelayInv;
+ p->pSuperInv->tDelaysR[0].Rise = MAP_NO_VAR;
+ p->pSuperInv->tDelaysR[0].Fall = p->tDelayInv.Rise;
+ p->pSuperInv->tDelaysF[0].Rise = p->tDelayInv.Fall;
+ p->pSuperInv->tDelaysF[0].Fall = MAP_NO_VAR;
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the supergate library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_SuperLibFree( Map_SuperLib_t * p )
+{
+ if ( p == NULL ) return;
+ if ( p->pGenlib )
+ {
+// if ( s_pLib == p->pGenlib )
+// s_pLib = NULL;
+ if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == p->pGenlib )
+ Abc_FrameSetLibGen(Abc_FrameGetGlobalFrame(), NULL);
+// Mio_LibraryDelete( p->pGenlib );
+ Mio_LibraryDelete( p->pGenlib );
+ }
+ if ( p->tTableC )
+ Map_SuperTableFree( p->tTableC );
+ if ( p->tTable )
+ Map_SuperTableFree( p->tTable );
+ Extra_MmFixedStop( p->mmSupers, 0 );
+ Extra_MmFixedStop( p->mmEntries, 0 );
+ Extra_MmFlexStop( p->mmForms, 0 );
+ FREE( p->ppSupers );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the library from the genlib library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib )
+{
+ Abc_Frame_t * pAbc = Abc_FrameGetGlobalFrame();
+ char * pNameGeneric;
+ char FileNameGenlib[100];
+ char FileNameSuper[100];
+ char CommandSuper[500];
+ char CommandRead[500];
+ FILE * pFile;
+
+ if ( pLib == NULL )
+ return 0;
+
+ // write the current library into the file
+ strcpy( FileNameGenlib, Mio_LibraryReadName(pLib) );
+ pFile = fopen( FileNameGenlib, "w" );
+ Mio_WriteLibrary( pFile, pLib, 0 );
+ fclose( pFile );
+
+ // get the file name with the library
+ pNameGeneric = Extra_FileNameGeneric( Mio_LibraryReadName(pLib) );
+ sprintf( FileNameSuper, "%s.super", pNameGeneric );
+ free( pNameGeneric );
+
+ sprintf( CommandSuper, "super -l 1 -i 5 -d 10000000 -a 10000000 -t 100 %s", FileNameGenlib );
+ if ( Cmd_CommandExecute( pAbc, CommandSuper ) )
+ {
+ fprintf( stdout, "Cannot execute command \"%s\".\n", CommandSuper );
+ return 0;
+ }
+//#ifdef WIN32
+// _unlink( FileNameGenlib );
+//#else
+// unlink( FileNameGenlib );
+//#endif
+
+ sprintf( CommandRead, "read_super %s", FileNameSuper );
+ if ( Cmd_CommandExecute( pAbc, CommandRead ) )
+ {
+#ifdef WIN32
+ _unlink( FileNameSuper );
+#else
+ unlink( FileNameSuper );
+#endif
+ fprintf( stdout, "Cannot execute command \"%s\".\n", CommandRead );
+ return 0;
+ }
+
+/* // don't remove the intermediate file
+#ifdef WIN32
+ _unlink( FileNameSuper );
+#else
+ unlink( FileNameSuper );
+#endif
+*/
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperMatch.c b/src/map/mapper/mapperMatch.c
new file mode 100644
index 00000000..5b72311c
--- /dev/null
+++ b/src/map/mapper/mapperMatch.c
@@ -0,0 +1,578 @@
+/**CFile****************************************************************
+
+ FileName [mapperMatch.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+/*
+ A potential improvement:
+ When an internal node is not used in the mapping, its required times
+ are set to be +infinity. So when we recover area, we try to find the
+ best match for area and completely disregard the delay for the nodes
+ that are not currently used in the mapping because any match whose
+ arrival times are less than the required times (+infinity) can be used.
+ It may be possible to develop a better approach to recover area for
+ the nodes that are not currently used in the mapping...
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase );
+static int Map_MatchNodeCut( Map_Man_t * p, Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float fWorstLimit );
+
+static void Map_MappingSetPiArrivalTimes( Map_Man_t * p );
+static void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode );
+static void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the best matches of the nodes.]
+
+ Description [Uses parameter p->fMappingMode to decide how to assign
+ the matches for both polarities of the node. While the matches are
+ being assigned, one of them may turn out to be better than the other
+ (in terms of delay, for example). In this case, the worse match can
+ be permanently dropped, and the corresponding pointer set to NULL.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingMatches( Map_Man_t * p )
+{
+ ProgressBar * pProgress;
+ Map_Node_t * pNode;
+ int i;
+
+ assert( p->fMappingMode >= 0 && p->fMappingMode <= 3 );
+
+ // use the externally given PI arrival times
+ if ( p->fMappingMode == 0 )
+ Map_MappingSetPiArrivalTimes( p );
+
+ // estimate the fanouts
+ if ( p->fMappingMode == 0 )
+ Map_MappingEstimateRefsInit( p );
+ else if ( p->fMappingMode == 1 )
+ Map_MappingEstimateRefs( p );
+
+ // the PI cuts are matched in the cut computation package
+ // in the loop below we match the internal nodes
+ pProgress = Extra_ProgressBarStart( stdout, p->vAnds->nSize );
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ // skip primary inputs and secondary nodes if mapping with choices
+ pNode = p->vAnds->pArray[i];
+ if ( !Map_NodeIsAnd( pNode ) || pNode->pRepr )
+ continue;
+
+ // make sure that at least one non-trival cut is present
+ if ( pNode->pCuts->pNext == NULL )
+ {
+ printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" );
+ return 0;
+ }
+
+ // match negative phase
+ if ( !Map_MatchNodePhase( p, pNode, 0 ) )
+ return 0;
+ // match positive phase
+ if ( !Map_MatchNodePhase( p, pNode, 1 ) )
+ return 0;
+
+ // make sure that at least one phase is mapped
+ if ( pNode->pCutBest[0] == NULL && pNode->pCutBest[1] == NULL )
+ {
+ printf( "\nError: Could not match both phases of AIG node %d.\n", pNode->Num );
+ printf( "Please make sure that the supergate library has equivalents of AND2 or NAND2.\n" );
+ printf( "If such supergates exist in the library, report a bug.\n" );
+ return 0;
+ }
+
+ // if both phases are assigned, check if one of them can be dropped
+ Map_NodeTryDroppingOnePhase( p, pNode );
+ // set the arrival times of the node using the best cuts
+ Map_NodeTransferArrivalTimes( p, pNode );
+
+ // update the progress bar
+ Extra_ProgressBarUpdate( pProgress, i, "Matches ..." );
+ }
+ Extra_ProgressBarStop( pProgress );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the matching of one polarity of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase )
+{
+ Map_Match_t MatchBest, * pMatch;
+ Map_Cut_t * pCut, * pCutBest;
+ float Area1, Area2, fWorstLimit;
+
+ // skip the cuts that have been unassigned during area recovery
+ pCutBest = pNode->pCutBest[fPhase];
+ if ( p->fMappingMode != 0 && pCutBest == NULL )
+ return 1;
+
+ // recompute the arrival times of the current best match
+ // because the arrival times of the fanins may have changed
+ // as a result of remapping fanins in the topological order
+ if ( p->fMappingMode != 0 )
+ {
+ Map_TimeCutComputeArrival( pNode, pCutBest, fPhase, MAP_FLOAT_LARGE );
+ // make sure that the required times are met
+ assert( pCutBest->M[fPhase].tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon );
+ assert( pCutBest->M[fPhase].tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon );
+ }
+
+ // recompute the exact area of the current best match
+ // because the exact area of the fanins may have changed
+ // as a result of remapping fanins in the topological order
+ if ( p->fMappingMode >= 2 )
+ {
+ pMatch = pCutBest->M + fPhase;
+ if ( pNode->nRefAct[fPhase] > 0 ||
+ (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) )
+ pMatch->AreaFlow = Area1 = Map_CutDeref( pCutBest, fPhase );
+ else
+ pMatch->AreaFlow = Area1 = Map_CutGetAreaDerefed( pCutBest, fPhase );
+ }
+
+ // save the old mapping
+ if ( pCutBest )
+ MatchBest = pCutBest->M[fPhase];
+ else
+ Map_MatchClean( &MatchBest );
+
+ // select the new best cut
+ fWorstLimit = pNode->tRequired[fPhase].Worst;
+ for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+ {
+ pMatch = pCut->M + fPhase;
+ if ( pMatch->pSupers == NULL )
+ continue;
+
+ // find the matches for the cut
+ Map_MatchNodeCut( p, pNode, pCut, fPhase, fWorstLimit );
+ if ( pMatch->pSuperBest == NULL || pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon )
+ continue;
+
+ // if the cut can be matched compare the matchings
+ if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) )
+ {
+ pCutBest = pCut;
+ MatchBest = *pMatch;
+ // if we are mapping for delay, the worst-case limit should be tightened
+ if ( p->fMappingMode == 0 )
+ fWorstLimit = MatchBest.tArrive.Worst;
+ }
+ }
+
+ if ( pCutBest == NULL )
+ return 1;
+
+ // set the new mapping
+ pNode->pCutBest[fPhase] = pCutBest;
+ pCutBest->M[fPhase] = MatchBest;
+
+ // reference the new cut if it used
+ if ( p->fMappingMode >= 2 &&
+ (pNode->nRefAct[fPhase] > 0 ||
+ (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0)) )
+ {
+ Area2 = Map_CutRef( pNode->pCutBest[fPhase], fPhase );
+ assert( Area2 < Area1 + p->fEpsilon );
+ }
+
+ // make sure that the requited times are met
+ assert( MatchBest.tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon );
+ assert( MatchBest.tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the best matching of the cut.]
+
+ Description [The parameters: the node (pNode), the cut (pCut), the phase to be matched
+ (fPhase), and the upper bound on the arrival times of the cut (fWorstLimit). This
+ procedure goes through the matching supergates up to the phase assignment, and selects the
+ best supergate, which will be used to map the cut. As a result of calling this procedure
+ the matching information is written into pMatch.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MatchNodeCut( Map_Man_t * p, Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float fWorstLimit )
+{
+ Map_Match_t MatchBest, * pMatch = pCut->M + fPhase;
+ Map_Super_t * pSuper;
+ int i, Counter;
+
+ // save the current match of the cut
+ MatchBest = *pMatch;
+ // go through the supergates
+ for ( pSuper = pMatch->pSupers, Counter = 0; pSuper; pSuper = pSuper->pNext, Counter++ )
+ {
+ p->nMatches++;
+ // this is an attempt to reduce the runtime of matching and area
+ // at the cost of rare and very minor increase in delay
+ // (the supergates are sorted by increasing area)
+ if ( Counter == 30 )
+ break;
+
+ // go through different phases of the given match and supergate
+ pMatch->pSuperBest = pSuper;
+ for ( i = 0; i < (int)pSuper->nPhases; i++ )
+ {
+ p->nPhases++;
+ // find the overall phase of this match
+ pMatch->uPhaseBest = pMatch->uPhase ^ pSuper->uPhases[i];
+ if ( p->fMappingMode == 0 )
+ {
+ // get the arrival time
+ Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit );
+ // skip the cut if the arrival times exceed the required times
+ if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon )
+ continue;
+ // get the area (area flow)
+ pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase );
+ }
+ else
+ {
+ // get the area (area flow)
+ if ( p->fMappingMode >= 2 )
+ pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase );
+ else
+ pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase );
+ // skip if the cut is too large
+ if ( pMatch->AreaFlow > MatchBest.AreaFlow + p->fEpsilon )
+ continue;
+ // get the arrival time
+ Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit );
+ // skip the cut if the arrival times exceed the required times
+ if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon )
+ continue;
+ }
+
+ // if the cut is non-trivial, compare it
+ if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) )
+ {
+ MatchBest = *pMatch;
+ // if we are mapping for delay, the worst-case limit should be reduced
+ if ( p->fMappingMode == 0 )
+ fWorstLimit = MatchBest.tArrive.Worst;
+ }
+ }
+ }
+ // set the best match
+ *pMatch = MatchBest;
+
+ // recompute the arrival time and area (area flow) of this cut
+ if ( pMatch->pSuperBest )
+ {
+ Map_TimeCutComputeArrival( pNode, pCut, fPhase, MAP_FLOAT_LARGE );
+ if ( p->fMappingMode >= 2 )
+ pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase );
+ else
+ pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the match.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MatchClean( Map_Match_t * pMatch )
+{
+ memset( pMatch, 0, sizeof(Map_Match_t) );
+ pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned
+ pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two matches.]
+
+ Description [Returns 1 if the second match is better. Otherwise returns 0.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MatchCompare( Map_Man_t * pMan, Map_Match_t * pM1, Map_Match_t * pM2, int fDoingArea )
+{
+ if ( !fDoingArea )
+ {
+ // compare the arrival times
+ if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon )
+ return 0;
+ if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon )
+ return 1;
+ // compare the areas or area flows
+ if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon )
+ return 0;
+ if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon )
+ return 1;
+ // compare the fanout limits
+ if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit )
+ return 0;
+ if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit )
+ return 1;
+ // compare the number of leaves
+ if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins )
+ return 0;
+ if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins )
+ return 1;
+ // otherwise prefer the old cut
+ return 0;
+ }
+ else
+ {
+ // compare the areas or area flows
+ if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon )
+ return 0;
+ if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon )
+ return 1;
+ // compare the arrival times
+ if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon )
+ return 0;
+ if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon )
+ return 1;
+ // compare the fanout limits
+ if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit )
+ return 0;
+ if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit )
+ return 1;
+ // compare the number of leaves
+ if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins )
+ return 0;
+ if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins )
+ return 1;
+ // otherwise prefer the old cut
+ return 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the PI arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingSetPiArrivalTimes( Map_Man_t * p )
+{
+ Map_Node_t * pNode;
+ int i;
+ for ( i = 0; i < p->nInputs; i++ )
+ {
+ pNode = p->pInputs[i];
+ // set the arrival time of the positive phase
+ pNode->tArrival[1] = p->pInputArrivals[i];
+ // set the arrival time of the negative phase
+ pNode->tArrival[0].Rise = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise;
+ pNode->tArrival[0].Fall = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall;
+ pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall);
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Attempts dropping one phase of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode )
+{
+ Map_Match_t * pMatchBest0, * pMatchBest1;
+ float tWorst0Using1, tWorst1Using0;
+ int fUsePhase1, fUsePhase0;
+
+ // nothing to do if one of the phases is already dropped
+ if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL )
+ return;
+
+ // do not drop while recovering area flow
+ if ( p->fMappingMode == 1 )//|| p->fMappingMode == 2 )
+ return;
+
+ // get the pointers to the matches of the best cuts
+ pMatchBest0 = pNode->pCutBest[0]->M + 0;
+ pMatchBest1 = pNode->pCutBest[1]->M + 1;
+
+ // get the worst arrival times of each phase
+ // implemented using the other phase with inverter added
+ tWorst0Using1 = Map_TimeMatchWithInverter( p, pMatchBest1 );
+ tWorst1Using0 = Map_TimeMatchWithInverter( p, pMatchBest0 );
+
+ // consider the case of mapping for delay
+ if ( p->fMappingMode == 0 )
+ {
+ // if the arrival time of a phase is larger than the arrival time
+ // of the opposite phase plus the inverter, drop this phase
+ if ( pMatchBest0->tArrive.Worst > tWorst0Using1 + p->fEpsilon )
+ pNode->pCutBest[0] = NULL;
+ else if ( pMatchBest1->tArrive.Worst > tWorst1Using0 + p->fEpsilon )
+ pNode->pCutBest[1] = NULL;
+ return;
+ }
+
+ // do not perform replacement if one of the phases is unused
+ if ( pNode->nRefAct[0] == 0 || pNode->nRefAct[1] == 0 )
+ return;
+
+ // check if replacement of each phase is possible using required times
+ fUsePhase0 = fUsePhase1 = 0;
+ if ( p->fMappingMode == 2 )
+ {
+ fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon);
+ fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon);
+ }
+ else if ( p->fMappingMode == 3 )
+ {
+ fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + p->fEpsilon);
+ fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + p->fEpsilon);
+ }
+ if ( !fUsePhase0 && !fUsePhase1 )
+ return;
+
+ // if replacement is possible both ways, use the one that works better
+ if ( fUsePhase0 && fUsePhase1 )
+ {
+ if ( pMatchBest0->AreaFlow < pMatchBest1->AreaFlow )
+ fUsePhase1 = 0;
+ else
+ fUsePhase0 = 0;
+ }
+ // only one phase should be used
+ assert( fUsePhase0 ^ fUsePhase1 );
+
+ // set the corresponding cut to NULL
+ if ( fUsePhase0 )
+ {
+ // deref phase 1 cut if necessary
+ if ( p->fMappingMode >= 2 && pNode->nRefAct[1] > 0 )
+ Map_CutDeref( pNode->pCutBest[1], 1 );
+ // get rid of the cut
+ pNode->pCutBest[1] = NULL;
+ // ref phase 0 cut if necessary
+ if ( p->fMappingMode >= 2 && pNode->nRefAct[0] == 0 )
+ Map_CutRef( pNode->pCutBest[0], 0 );
+ }
+ else
+ {
+ // deref phase 0 cut if necessary
+ if ( p->fMappingMode >= 2 && pNode->nRefAct[0] > 0 )
+ Map_CutDeref( pNode->pCutBest[0], 0 );
+ // get rid of the cut
+ pNode->pCutBest[0] = NULL;
+ // ref phase 1 cut if necessary
+ if ( p->fMappingMode >= 2 && pNode->nRefAct[1] == 0 )
+ Map_CutRef( pNode->pCutBest[1], 1 );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the arrival times from the best cuts to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode )
+{
+ // if both phases are available, set their arrival times
+ if ( pNode->pCutBest[0] && pNode->pCutBest[1] )
+ {
+ pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive;
+ pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive;
+ }
+ // if only one phase is available, compute the arrival time of other phase
+ else if ( pNode->pCutBest[0] )
+ {
+ pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive;
+ pNode->tArrival[1].Rise = pNode->tArrival[0].Fall + p->pSuperLib->tDelayInv.Rise;
+ pNode->tArrival[1].Fall = pNode->tArrival[0].Rise + p->pSuperLib->tDelayInv.Fall;
+ pNode->tArrival[1].Worst = MAP_MAX(pNode->tArrival[1].Rise, pNode->tArrival[1].Fall);
+ }
+ else if ( pNode->pCutBest[1] )
+ {
+ pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive;
+ pNode->tArrival[0].Rise = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise;
+ pNode->tArrival[0].Fall = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall;
+ pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall);
+ }
+ else
+ {
+ assert( 0 );
+ }
+
+ assert( pNode->tArrival[0].Rise < pNode->tRequired[0].Rise + p->fEpsilon );
+ assert( pNode->tArrival[0].Fall < pNode->tRequired[0].Fall + p->fEpsilon );
+
+ assert( pNode->tArrival[1].Rise < pNode->tRequired[1].Rise + p->fEpsilon );
+ assert( pNode->tArrival[1].Fall < pNode->tRequired[1].Fall + p->fEpsilon );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/map/mapper/mapperRefs.c b/src/map/mapper/mapperRefs.c
new file mode 100644
index 00000000..334e98c7
--- /dev/null
+++ b/src/map/mapper/mapperRefs.c
@@ -0,0 +1,541 @@
+/**CFile****************************************************************
+
+ FileName [mapperRefs.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperRefs.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase );
+static int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase );
+static float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference );
+static void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the actual reference counter of a phase.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned
+ return pNode->nRefAct[fPhase];
+ assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned
+ return pNode->nRefAct[2];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the estimated reference counter of a phase.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned
+ return pNode->nRefEst[fPhase];
+ assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned
+// return pNode->nRefEst[0] + pNode->nRefEst[1];
+ return pNode->nRefEst[2];
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Increments the actual reference counter of a phase.]
+
+ Description [Returns the old reference counter.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned
+ return pNode->nRefAct[fPhase]++;
+ assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned
+ return pNode->nRefAct[2]++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Decrements the actual reference counter of a phase.]
+
+ Description [Returns the new reference counter.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned
+ return --pNode->nRefAct[fPhase];
+ assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned
+ return --pNode->nRefAct[2];
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets the estimated reference counter for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingEstimateRefsInit( Map_Man_t * p )
+{
+ Map_Node_t * pNode;
+ int i;
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+// pNode->nRefEst[0] = pNode->nRefEst[1] = ((float)pNode->nRefs)*(float)2.0;
+ pNode->nRefEst[0] = pNode->nRefEst[1] = pNode->nRefEst[2] = ((float)pNode->nRefs);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the estimated reference counter.]
+
+ Description [When this procedure is called for the first time,
+ the reference counter is estimated from the AIG. Otherwise, it is
+ a linear combination of reference counters in the last two iterations.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingEstimateRefs( Map_Man_t * p )
+{
+ Map_Node_t * pNode;
+ int i;
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ pNode = p->vAnds->pArray[i];
+// pNode->nRefEst[0] = (float)((2.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 3.0);
+// pNode->nRefEst[1] = (float)((2.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 3.0);
+// pNode->nRefEst[2] = (float)((2.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 3.0);
+ pNode->nRefEst[0] = (float)((3.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 4.0);
+ pNode->nRefEst[1] = (float)((3.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 4.0);
+ pNode->nRefEst[2] = (float)((3.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 4.0);
+ }
+}
+
+
+
+
+
+/**function*************************************************************
+
+ synopsis [Computes the area flow of the cut.]
+
+ description [Computes the area flow of the cut if it is implemented using
+ the best supergate with the best phase.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase )
+{
+ Map_Match_t * pM = pCut->M + fPhase;
+ Map_Super_t * pSuper = pM->pSuperBest;
+ unsigned uPhaseTot = pM->uPhaseBest;
+ Map_Cut_t * pCutFanin;
+ float aFlowRes, aFlowFanin, nRefs;
+ int i, fPinPhasePos;
+
+ // start the resulting area flow
+ aFlowRes = pSuper->Area;
+ // iterate through the leaves
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ // get the phase of this fanin
+ fPinPhasePos = ((uPhaseTot & (1 << i)) == 0);
+ // get the cut implementing this phase of the fanin
+ pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos];
+ // if the cut is not available, we have to use the opposite phase
+ if ( pCutFanin == NULL )
+ {
+ fPinPhasePos = !fPinPhasePos;
+ pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos];
+ }
+ aFlowFanin = pCutFanin->M[fPinPhasePos].AreaFlow; // ignores the area of the interter
+ // get the fanout count of the cut in the given phase
+ nRefs = Map_NodeReadRefPhaseEst( pCut->ppLeaves[i], fPinPhasePos );
+ // if the node does no fanout, assume fanout count equal to 1
+ if ( nRefs == (float)0.0 )
+ nRefs = (float)1.0;
+ // add the area flow due to the fanin
+ aFlowRes += aFlowFanin / nRefs;
+ }
+ pM->AreaFlow = aFlowRes;
+ return aFlowRes;
+}
+
+
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description [Assumes that the cut is referenced.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase )
+{
+ float aResult, aResult2;
+ aResult2 = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference
+ aResult = Map_CutRefDeref( pCut, fPhase, 1 ); // reference
+ assert( aResult == aResult2 );
+ return aResult;
+}
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase )
+{
+ float aResult, aResult2;
+ aResult2 = Map_CutRefDeref( pCut, fPhase, 1 ); // reference
+ aResult = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference
+ assert( aResult == aResult2 );
+ return aResult;
+}
+
+/**function*************************************************************
+
+ synopsis [References the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Map_CutRef( Map_Cut_t * pCut, int fPhase )
+{
+ return Map_CutRefDeref( pCut, fPhase, 1 ); // reference
+}
+
+/**function*************************************************************
+
+ synopsis [References the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Map_CutDeref( Map_Cut_t * pCut, int fPhase )
+{
+ return Map_CutRefDeref( pCut, fPhase, 0 ); // dereference
+}
+
+/**function*************************************************************
+
+ synopsis [References or dereferences the cut.]
+
+ description [This reference part is similar to Cudd_NodeReclaim().
+ The dereference part is similar to Cudd_RecursiveDeref(). The
+ area of the inverter is not counted.]
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference )
+{
+ Map_Node_t * pNodeChild;
+ Map_Cut_t * pCutChild;
+ float aArea;
+ int i, fPhaseChild;
+// int nRefs;
+
+ // consider the elementary variable
+ if ( pCut->nLeaves == 1 )
+ return 0;
+ // start the area of this cut
+ aArea = Map_CutGetRootArea( pCut, fPhase );
+ // go through the children
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pNodeChild = pCut->ppLeaves[i];
+ fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i );
+ // get the reference counter of the child
+/*
+ // this code does not take inverters into account
+ // the quality of area recovery seems to always be a little worse
+ if ( fReference )
+ nRefs = Map_NodeIncRefPhaseAct( pNodeChild, fPhaseChild );
+ else
+ nRefs = Map_NodeDecRefPhaseAct( pNodeChild, fPhaseChild );
+ assert( nRefs >= 0 );
+ // skip if the child was already reference before
+ if ( nRefs > 0 )
+ continue;
+*/
+
+ if ( fReference )
+ {
+ if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present
+ {
+ // if this phase of the node is referenced, there is no recursive call
+ pNodeChild->nRefAct[2]++;
+ if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 )
+ continue;
+ }
+ else // only one phase is present
+ {
+ // inverter should be added if the phase
+ // (a) has no reference and (b) is implemented using other phase
+ if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL )
+ aArea += pNodeChild->p->pSuperLib->AreaInv;
+ // if the node is referenced, there is no recursive call
+ if ( pNodeChild->nRefAct[2]++ > 0 )
+ continue;
+ }
+ }
+ else
+ {
+ if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present
+ {
+ // if this phase of the node is referenced, there is no recursive call
+ --pNodeChild->nRefAct[2];
+ if ( --pNodeChild->nRefAct[fPhaseChild] > 0 )
+ continue;
+ }
+ else // only one phase is present
+ {
+ // inverter should be added if the phase
+ // (a) has no reference and (b) is implemented using other phase
+ if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL )
+ aArea += pNodeChild->p->pSuperLib->AreaInv;
+ // if the node is referenced, there is no recursive call
+ if ( --pNodeChild->nRefAct[2] > 0 )
+ continue;
+ }
+ assert( pNodeChild->nRefAct[fPhaseChild] >= 0 );
+ }
+
+ // get the child cut
+ pCutChild = pNodeChild->pCutBest[fPhaseChild];
+ // if the child does not have this phase mapped, take the opposite phase
+ if ( pCutChild == NULL )
+ {
+ fPhaseChild = !fPhaseChild;
+ pCutChild = pNodeChild->pCutBest[fPhaseChild];
+ }
+ // reference and compute area recursively
+ aArea += Map_CutRefDeref( pCutChild, fPhaseChild, fReference );
+ }
+ return aArea;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes actual reference counters.]
+
+ Description [Stores all the nodes used in the mapping in the array pMan->vMapping.
+ The nodes are stored in the random order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingSetRefs( Map_Man_t * pMan )
+{
+ Map_Node_t * pNode;
+ int i, fPhase;
+ // clean all references
+ for ( i = 0; i < pMan->vNodesAll->nSize; i++ )
+ {
+ pNode = pMan->vNodesAll->pArray[i];
+ pNode->nRefAct[0] = 0;
+ pNode->nRefAct[1] = 0;
+ pNode->nRefAct[2] = 0;
+ }
+ // visit nodes reachable from POs in the DFS order through the best cuts
+ pMan->vMapping->nSize = 0;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ pNode = pMan->pOutputs[i];
+ fPhase = !Map_IsComplement(pNode);
+ if ( !Map_NodeIsConst(pNode) )
+ Map_MappingSetRefs_rec( pMan, pNode );
+ // reference count the PO node
+// Map_Regular(pNode)->nRefAct[fPhase]++;
+// Map_Regular(pNode)->nRefAct[2]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode )
+{
+ Map_Cut_t * pCut;
+ Map_Node_t * pNodeR;
+ unsigned uPhase;
+ int i, fPhase, fInvPin;
+
+ // get the regular node and its phase
+ pNodeR = Map_Regular(pNode);
+ fPhase = !Map_IsComplement(pNode);
+
+ // add the node to the list of all visited nodes
+ if ( pNodeR->nRefAct[2]++ == 0 )
+ Map_NodeVecPush( pMan->vMapping, pNodeR );
+
+ // quit if the node was already visited in this phase
+ if ( pNodeR->nRefAct[fPhase]++ )
+ return;
+
+ // quit if this is a PI node
+ if ( Map_NodeIsVar(pNodeR) )
+ return;
+
+ // get the cut implementing this or opposite polarity
+ pCut = pNodeR->pCutBest[fPhase];
+ if ( pCut == NULL )
+ {
+ fPhase = !fPhase;
+ pCut = pNodeR->pCutBest[fPhase];
+ }
+
+ // visit the transitive fanin
+ uPhase = pCut->M[fPhase].uPhaseBest;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ fInvPin = ((uPhase & (1 << i)) > 0);
+ Map_MappingSetRefs_rec( pMan, Map_NotCond(pCut->ppLeaves[i], fInvPin) );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the array of mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Map_MappingGetArea( Map_Man_t * pMan, Map_NodeVec_t * vMapping )
+{
+ Map_Node_t * pNode;
+ float Area;
+ int i;
+ Area = 0.0;
+ for ( i = 0; i < vMapping->nSize; i++ )
+ {
+ pNode = vMapping->pArray[i];
+ // at least one phase has the best cut assigned
+ assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL );
+ // at least one phase is used in the mapping
+ assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 );
+ // compute the array due to the supergate
+ if ( Map_NodeIsAnd(pNode) )
+ {
+ // count area of the negative phase
+ if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) )
+ Area += pNode->pCutBest[0]->M[0].pSuperBest->Area;
+ // count area of the positive phase
+ if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) )
+ Area += pNode->pCutBest[1]->M[1].pSuperBest->Area;
+ }
+ // count area of the interver if we need to implement one phase with another phase
+ if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) ||
+ (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) )
+ Area += pMan->pSuperLib->AreaInv;
+ }
+ // add two inverters for each PO buffer
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) )
+ Area += 2 * pMan->pSuperLib->AreaInv;
+ return Area;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperSuper.c b/src/map/mapper/mapperSuper.c
new file mode 100644
index 00000000..34b1d8e6
--- /dev/null
+++ b/src/map/mapper/mapperSuper.c
@@ -0,0 +1,449 @@
+/**CFile****************************************************************
+
+ FileName [mapperSuper.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperSuper.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile );
+static Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars );
+static int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate );
+static void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] );
+static void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] );
+static void Map_LibraryPrintClasses( Map_SuperLib_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the supergate library from file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_LibraryRead( Map_SuperLib_t * pLib, char * pFileName )
+{
+ FILE * pFile;
+ int Status;
+ // read the beginning of the file
+ assert( pLib->pGenlib == NULL );
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ printf( "Cannot open input file \"%s\".\n", pFileName );
+ return 0;
+ }
+ Status = Map_LibraryReadFile( pLib, pFile );
+ fclose( pFile );
+// Map_LibraryPrintClasses( pLib );
+ return Status;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Reads the library file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile )
+{
+ ProgressBar * pProgress;
+ char pBuffer[2000];
+ FILE * pFileGen;
+ Map_Super_t * pGate;
+ char * pTemp, * pLibName;
+ int nCounter, nGatesTotal;
+ unsigned uCanon[2];
+
+ // skip empty and comment lines
+ while ( fgets( pBuffer, 5000, pFile ) != NULL )
+ {
+ // skip leading spaces
+ for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+ // skip comment lines and empty lines
+ if ( *pTemp != 0 && *pTemp != '#' )
+ break;
+ }
+
+ // get the genlib file name
+ pLibName = strtok( pTemp, " \t\r\n" );
+ if ( strcmp( pLibName, "GATE" ) == 0 )
+ {
+ printf( "The input file \"%s\" looks like a GENLIB file and not a supergate library file.\n", pLib->pName );
+ return 0;
+ }
+ pFileGen = fopen( pLibName, "r" );
+ if ( pFileGen == NULL )
+ {
+ printf( "Cannot open the GENLIB file \"%s\".\n", pLibName );
+ return 0;
+ }
+ fclose( pFileGen );
+
+ // read the genlib library
+ pLib->pGenlib = Mio_LibraryRead( Abc_FrameGetGlobalFrame(), pLibName, 0, 0 );
+ if ( pLib->pGenlib == NULL )
+ {
+ printf( "Cannot read GENLIB file \"%s\".\n", pLibName );
+ return 0;
+ }
+
+ // read the number of variables
+ fscanf( pFile, "%d\n", &pLib->nVarsMax );
+ if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 )
+ {
+ printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax );
+ return 0;
+ }
+
+ // read the number of gates
+ fscanf( pFile, "%d\n", &nGatesTotal );
+ if ( nGatesTotal < 1 || nGatesTotal > 10000000 )
+ {
+ printf( "Suspicious number of gates (%d).\n", nGatesTotal );
+ return 0;
+ }
+
+ // read the lines
+ nCounter = 0;
+ pProgress = Extra_ProgressBarStart( stdout, nGatesTotal );
+ while ( fgets( pBuffer, 5000, pFile ) != NULL )
+ {
+ for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+ if ( pTemp[0] == '\0' )
+ continue;
+ // get the gate
+ pGate = Map_LibraryReadGate( pLib, pTemp, pLib->nVarsMax );
+ assert( pGate->Num == nCounter + 1 );
+ // count the number of parantheses in the formula - this is the number of gates
+ for ( pTemp = pGate->pFormula; *pTemp; pTemp++ )
+ pGate->nGates += (*pTemp == '(');
+ // verify the truth table
+ assert( Map_LibraryTruthVerify(pLib, pGate) );
+
+ // find the N-canonical form of this supergate
+ pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, pLib->nVarsMax, pGate->uTruth, pGate->uPhases, uCanon );
+ // add the supergate into the table by its N-canonical table
+ Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate );
+ // update the progress bar
+ Extra_ProgressBarUpdate( pProgress, ++nCounter, NULL );
+ }
+ Extra_ProgressBarStop( pProgress );
+ pLib->nSupersAll = nCounter;
+ if ( nCounter != nGatesTotal )
+ printf( "The number of gates read (%d) is different what the file says (%d).\n", nGatesTotal, nCounter );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars )
+{
+ Map_Super_t * pGate;
+ char * pTemp;
+ int i;
+
+ // start and clean the gate
+ pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers );
+ memset( pGate, 0, sizeof(Map_Super_t) );
+
+ // read the number
+ pTemp = strtok( pBuffer, " " );
+ pGate->Num = atoi(pTemp);
+
+ // read the signature
+ pTemp = strtok( NULL, " " );
+ if ( pLib->nVarsMax < 6 )
+ {
+ pGate->uTruth[0] = Extra_ReadBinary(pTemp);
+ pGate->uTruth[1] = 0;
+ }
+ else
+ {
+ pGate->uTruth[0] = Extra_ReadBinary(pTemp+32);
+ pTemp[32] = 0;
+ pGate->uTruth[1] = Extra_ReadBinary(pTemp);
+ }
+
+ // read the max delay
+ pTemp = strtok( NULL, " " );
+ pGate->tDelayMax.Rise = (float)atof(pTemp);
+ pGate->tDelayMax.Fall = pGate->tDelayMax.Rise;
+
+ // read the pin-to-pin delay
+ for ( i = 0; i < nVars; i++ )
+ {
+ pTemp = strtok( NULL, " " );
+ pGate->tDelaysR[i].Rise = (float)atof(pTemp);
+ pGate->tDelaysF[i].Fall = pGate->tDelaysR[i].Rise;
+ }
+
+ // read the area
+ pTemp = strtok( NULL, " " );
+ pGate->Area = (float)atof(pTemp);
+
+ // the rest is the gate name
+ pTemp = strtok( NULL, " \r\n" );
+ if ( strlen(pTemp) == 0 )
+ printf( "A gate name is empty.\n" );
+
+ // save the gate name
+ pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp) + 1 );
+ strcpy( pGate->pFormula, pTemp );
+
+ // the rest is the gate name
+ pTemp = strtok( NULL, " \n\0" );
+ if ( pTemp != NULL )
+ printf( "The following trailing symbols found \"%s\".\n", pTemp );
+ return pGate;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one step of parsing the formula into parts.]
+
+ Description [This function will eventually be replaced when the
+ tree-supergate library representation will become standard.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings )
+{
+ char * pName, * pPar1, * pPar2, * pCur;
+ int nStrings, CountPars;
+
+ // skip leading spaces
+ for ( pName = pFormula; *pName && *pName == ' '; pName++ );
+ assert( *pName );
+ // find the first opening paranthesis
+ for ( pPar1 = pName; *pPar1 && *pPar1 != '('; pPar1++ );
+ if ( *pPar1 == 0 )
+ {
+ *pnStrings = 0;
+ return pName;
+ }
+ // overwrite it with space
+ assert( *pPar1 == '(' );
+ *pPar1 = 0;
+ // find the corresponding closing paranthesis
+ for ( CountPars = 1, pPar2 = pPar1 + 1; *pPar2 && CountPars; pPar2++ )
+ if ( *pPar2 == '(' )
+ CountPars++;
+ else if ( *pPar2 == ')' )
+ CountPars--;
+ pPar2--;
+ assert( CountPars == 0 );
+ // overwrite it with space
+ assert( *pPar2 == ')' );
+ *pPar2 = 0;
+ // save the intervals between the commas
+ nStrings = 0;
+ pCur = pPar1 + 1;
+ while ( 1 )
+ {
+ // save the current string
+ pStrings[ nStrings++ ] = pCur;
+ // find the beginning of the next string
+ for ( CountPars = 0; *pCur && (CountPars || *pCur != ','); pCur++ )
+ if ( *pCur == '(' )
+ CountPars++;
+ else if ( *pCur == ')' )
+ CountPars--;
+ if ( *pCur == 0 )
+ break;
+ assert( *pCur == ',' );
+ *pCur = 0;
+ pCur++;
+ }
+ // save the results and return
+ *pnStrings = nStrings;
+ return pName;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the truth table of the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate )
+{
+ unsigned uTruthRes[2];
+ Map_LibraryComputeTruth( pLib, pGate->pFormula, uTruthRes );
+ if ( uTruthRes[0] != pGate->uTruth[0] || uTruthRes[1] != pGate->uTruth[1] )
+ return 0;
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the functionality of the supergate.]
+
+ Description [This procedure is useful for verification the supergate
+ library. The truth table derived by this procedure should be the same
+ as the one contained in the original supergate file.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] )
+{
+ char Buffer[1000];
+ strcpy( Buffer, pFormula );
+ Map_LibraryComputeTruth_rec( pLib, Buffer, pLib->uTruths, uTruthRes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the functionality of the supergate.]
+
+ Description [This procedure is useful for verification the supergate
+ library. The truth table derived by this procedure should be the same
+ as the one contained in the original supergate file.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] )
+{
+ Mio_Gate_t * pMioGate;
+ char * pGateName, * pStrings[6];
+ unsigned uTruthsFanins[6][2];
+ int nStrings, i;
+
+ // perform one step parsing of the formula
+ // detect the root gate name, the next-step strings, and their number
+ pGateName = Map_LibraryReadFormulaStep( pFormula, pStrings, &nStrings );
+ if ( nStrings == 0 ) // elementary variable
+ {
+ assert( pGateName[0] - 'a' < pLib->nVarsMax );
+ uTruthRes[0] = uTruthsIn[pGateName[0] - 'a'][0];
+ uTruthRes[1] = uTruthsIn[pGateName[0] - 'a'][1];
+ return;
+ }
+ // derive the functionality of the fanins
+ for ( i = 0; i < nStrings; i++ )
+ Map_LibraryComputeTruth_rec( pLib, pStrings[i], uTruthsIn, uTruthsFanins[i] );
+ // get the root supergate
+ pMioGate = Mio_LibraryReadGateByName( pLib->pGenlib, pGateName );
+ if ( pMioGate == NULL )
+ printf( "A supergate contains gate \"%s\" that is not in \"%s\".\n", pGateName, Mio_LibraryReadName(pLib->pGenlib) );
+ // derive the functionality of the output of the supergate
+ Mio_DeriveTruthTable( pMioGate, uTruthsFanins, nStrings, pLib->nVarsMax, uTruthRes );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_LibraryPrintSupergate( Map_Super_t * pGate )
+{
+ printf( "%5d : ", pGate->nUsed );
+ printf( "%5d ", pGate->Num );
+ printf( "A = %5.2f ", pGate->Area );
+ printf( "D = %5.2f ", pGate->tDelayMax );
+ printf( "%s", pGate->pFormula );
+ printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints N-classes of supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_LibraryPrintClasses( Map_SuperLib_t * p )
+{
+/*
+ st_generator * gen;
+ Map_Super_t * pSuper, * pSuper2;
+ unsigned Key, uTruth;
+ int Counter = 0;
+ // copy all the supergates into one array
+ st_foreach_item( p->tSuplib, gen, (char **)&Key, (char **)&pSuper )
+ {
+ for ( pSuper2 = pSuper; pSuper2; pSuper2 = pSuper2->pNext )
+ {
+ uTruth = pSuper2->Phase;
+ Extra_PrintBinary( stdout, &uTruth, 5 );
+ printf( " %5d ", pSuper2->Num );
+ printf( "%s", pSuper2->pFormula );
+ printf( "\n" );
+ }
+ printf( "\n" );
+ if ( ++ Counter == 100 )
+ break;
+ }
+*/
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperTable.c b/src/map/mapper/mapperTable.c
new file mode 100644
index 00000000..747fe1c8
--- /dev/null
+++ b/src/map/mapper/mapperTable.c
@@ -0,0 +1,402 @@
+/**CFile****************************************************************
+
+ FileName [mapperTable.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperTable.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the table function for the tables
+#define MAP_TABLE_HASH(u1,u2,nSize) (((u1) + 2003 * (u2)) % nSize)
+
+static void Map_SuperTableResize( Map_HashTable_t * pLib );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the hash table for supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib )
+{
+ Map_HashTable_t * p;
+ // allocate the table
+ p = ALLOC( Map_HashTable_t, 1 );
+ memset( p, 0, sizeof(Map_HashTable_t) );
+ p->mmMan = pLib->mmEntries;
+ // allocate and clean the bins
+ p->nBins = Cudd_Prime(20000);
+ p->pBins = ALLOC( Map_HashEntry_t *, p->nBins );
+ memset( p->pBins, 0, sizeof(Map_HashEntry_t *) * p->nBins );
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the supergate hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_SuperTableFree( Map_HashTable_t * p )
+{
+ FREE( p->pBins );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts a new entry into the hash table.]
+
+ Description [This function inserts the new gate (pGate), which will be
+ accessible through its canonical form (uTruthC).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_SuperTableInsertC( Map_HashTable_t * p, unsigned uTruthC[], Map_Super_t * pGate )
+{
+ Map_HashEntry_t * pEnt;
+ unsigned Key;
+ // resize the table
+ if ( p->nEntries >= 2 * p->nBins )
+ Map_SuperTableResize( p );
+ // check if another supergate with the same canonical form exists
+ Key = MAP_TABLE_HASH( uTruthC[0], uTruthC[1], p->nBins );
+ for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( pEnt->uTruth[0] == uTruthC[0] && pEnt->uTruth[1] == uTruthC[1] )
+ break;
+ // create a new entry if it does not exist
+ if ( pEnt == NULL )
+ {
+ // add the new entry to the table
+ pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan );
+ memset( pEnt, 0, sizeof(Map_HashEntry_t) );
+ pEnt->uTruth[0] = uTruthC[0];
+ pEnt->uTruth[1] = uTruthC[1];
+ // add the hash table entry to the corresponding linked list in the table
+ pEnt->pNext = p->pBins[Key];
+ p->pBins[Key] = pEnt;
+ p->nEntries++;
+ }
+ // add the supergate to the entry
+ pGate->pNext = pEnt->pGates;
+ pEnt->pGates = pGate;
+ return 0;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Inserts a new entry into the library.]
+
+ Description [This function inserts the new gate (pGate), which will be
+ accessible through its unfolded function (uTruth).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_SuperTableInsert( Map_HashTable_t * p, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase )
+{
+ Map_HashEntry_t * pEnt;
+ unsigned Key;
+ // resize the table
+ if ( p->nEntries >= 2 * p->nBins )
+ Map_SuperTableResize( p );
+ // check if this entry already exists
+ Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins );
+ for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] )
+ return 1;
+ // add the new hash table entry to the table
+ pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan );
+ memset( pEnt, 0, sizeof(Map_HashEntry_t) );
+ pEnt->uTruth[0] = uTruth[0];
+ pEnt->uTruth[1] = uTruth[1];
+ pEnt->pGates = pGate;
+ pEnt->uPhase = uPhase;
+ // add the hash table to the corresponding linked list in the table
+ pEnt->pNext = p->pBins[Key];
+ p->pBins[Key] = pEnt;
+ p->nEntries++;
+/*
+printf( "Adding gate: %10u ", Key );
+Map_LibraryPrintSupergate( pGate );
+Extra_PrintBinary( stdout, uTruth, 32 );
+printf( "\n" );
+*/
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up an entry in the library.]
+
+ Description [This function looks up the function, given by its truth table,
+ and return two things: (1) the linked list of supergates, which can implement
+ the functions of this N-class; (2) the phase, which should be applied to the
+ given function, in order to derive the canonical form of this N-class.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * p, unsigned uTruth[] )
+{
+ Map_HashEntry_t * pEnt;
+ unsigned Key;
+ Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->tTableC->nBins );
+ for ( pEnt = p->tTableC->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] )
+ return pEnt->pGates;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up an entry in the library.]
+
+ Description [This function looks up the function, given by its truth table,
+ and return two things: (1) the linked list of supergates, which can implement
+ the functions of this N-class; (2) the phase, which should be applied to the
+ given function, in order to derive the canonical form of this N-class.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase )
+{
+ Map_HashEntry_t * pEnt;
+ unsigned Key;
+ Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins );
+ for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] )
+ {
+ *puPhase = pEnt->uPhase;
+ return pEnt->pGates;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_SuperTableResize( Map_HashTable_t * p )
+{
+ Map_HashEntry_t ** pBinsNew;
+ Map_HashEntry_t * pEnt, * pEnt2;
+ int nBinsNew, Counter, i, clk = clock();
+ unsigned Key;
+ // get the new table size
+ nBinsNew = Cudd_Prime(2 * p->nBins);
+ // allocate a new array
+ pBinsNew = ALLOC( Map_HashEntry_t *, nBinsNew );
+ memset( pBinsNew, 0, sizeof(Map_HashEntry_t *) * nBinsNew );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( i = 0; i < p->nBins; i++ )
+ for ( pEnt = p->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt;
+ pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL )
+ {
+ Key = MAP_TABLE_HASH( pEnt->uTruth[0], pEnt->uTruth[1], nBinsNew );
+ pEnt->pNext = pBinsNew[Key];
+ pBinsNew[Key] = pEnt;
+ Counter++;
+ }
+ assert( Counter == p->nEntries );
+ // replace the table and the parameters
+ free( p->pBins );
+ p->pBins = pBinsNew;
+ p->nBins = nBinsNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the supergates by the number of times they are used.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_SuperTableCompareSupergates( Map_Super_t ** ppS1, Map_Super_t ** ppS2 )
+{
+ if ( (*ppS1)->nUsed > (*ppS2)->nUsed )
+ return -1;
+ if ( (*ppS1)->nUsed < (*ppS2)->nUsed )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the supergates by the number of times they are used.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_SuperTableCompareGatesInList( Map_Super_t ** ppS1, Map_Super_t ** ppS2 )
+{
+// if ( (*ppS1)->tDelayMax.Rise > (*ppS2)->tDelayMax.Rise )
+ if ( (*ppS1)->Area > (*ppS2)->Area )
+ return -1;
+// if ( (*ppS1)->tDelayMax.Rise < (*ppS2)->tDelayMax.Rise )
+ if ( (*ppS1)->Area < (*ppS2)->Area )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorts supergates by usefulness and prints out most useful.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax )
+{
+ Map_HashEntry_t * pEnt;
+ Map_Super_t ** ppSupers;
+ Map_Super_t * pSuper;
+ int nSupers, i;
+
+ // copy all the supergates into one array
+ ppSupers = ALLOC( Map_Super_t *, nSupersMax );
+ nSupers = 0;
+ for ( i = 0; i < p->nBins; i++ )
+ for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext )
+ for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext )
+ ppSupers[nSupers++] = pSuper;
+
+ // sort by usage
+ qsort( (void *)ppSupers, nSupers, sizeof(int),
+ (int (*)(const void *, const void *)) Map_SuperTableCompareSupergates );
+ assert( Map_SuperTableCompareSupergates( ppSupers, ppSupers + nSupers - 1 ) <= 0 );
+
+ // print out the "top ten"
+// for ( i = 0; i < nSupers; i++ )
+ for ( i = 0; i < 10; i++ )
+ {
+ if ( ppSupers[i]->nUsed == 0 )
+ break;
+ printf( "%5d : ", ppSupers[i]->nUsed );
+ printf( "%5d ", ppSupers[i]->Num );
+ printf( "A = %5.2f ", ppSupers[i]->Area );
+ printf( "D = %5.2f ", ppSupers[i]->tDelayMax.Rise );
+ printf( "%s", ppSupers[i]->pFormula );
+ printf( "\n" );
+ }
+ free( ppSupers );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorts supergates by max delay for each truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax )
+{
+ Map_HashEntry_t * pEnt;
+ Map_Super_t ** ppSupers;
+ Map_Super_t * pSuper;
+ int nSupers, i, k;
+
+ ppSupers = ALLOC( Map_Super_t *, nSupersMax );
+ for ( i = 0; i < p->nBins; i++ )
+ for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext )
+ {
+ // collect the gates in this entry
+ nSupers = 0;
+ for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext )
+ {
+ // skip supergates, whose root is the AND gate
+// if ( strcmp( Mio_GateReadName(pSuper->pRoot), "and" ) == 0 )
+// continue;
+ ppSupers[nSupers++] = pSuper;
+ }
+ pEnt->pGates = NULL;
+ if ( nSupers == 0 )
+ continue;
+ // sort the gates by delay
+ qsort( (void *)ppSupers, nSupers, sizeof(int),
+ (int (*)(const void *, const void *)) Map_SuperTableCompareGatesInList );
+ assert( Map_SuperTableCompareGatesInList( ppSupers, ppSupers + nSupers - 1 ) <= 0 );
+ // link them in the reverse order
+ for ( k = 0; k < nSupers; k++ )
+ {
+ ppSupers[k]->pNext = pEnt->pGates;
+ pEnt->pGates = ppSupers[k];
+ }
+ // save the number of supergates in the list
+ pEnt->pGates->nSupers = nSupers;
+ }
+ FREE( ppSupers );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperTime.c b/src/map/mapper/mapperTime.c
new file mode 100644
index 00000000..0ff88b0e
--- /dev/null
+++ b/src/map/mapper/mapperTime.c
@@ -0,0 +1,508 @@
+/**CFile****************************************************************
+
+ FileName [mapperTime.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperTime.c,v 1.3 2005/03/02 02:35:54 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Map_TimePropagateRequired( Map_Man_t * p, Map_NodeVec_t * vNodes );
+static void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase );
+static float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**function*************************************************************
+
+ synopsis [Computes the exact area associated with the cut.]
+
+ description []
+
+ sideeffects []
+
+ seealso []
+
+***********************************************************************/
+float Map_TimeMatchWithInverter( Map_Man_t * p, Map_Match_t * pMatch )
+{
+ Map_Time_t tArrInv;
+ tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall;
+ tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise;
+ tArrInv.Worst = MAP_MAX( tArrInv.Rise, tArrInv.Fall );
+ return tArrInv.Worst;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the arrival times of the cut recursively.]
+
+ Description [When computing the arrival time for the previously unused
+ cuts, their arrival time may be incorrect because their fanins have
+ incorrect arrival time. This procedure is called to fix this problem.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TimeCutComputeArrival_rec( Map_Cut_t * pCut, int fPhase )
+{
+ int i, fPhaseLeaf;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ fPhaseLeaf = Map_CutGetLeafPhase( pCut, fPhase, i );
+ if ( pCut->ppLeaves[i]->nRefAct[fPhaseLeaf] > 0 )
+ continue;
+ Map_TimeCutComputeArrival_rec( pCut->ppLeaves[i]->pCutBest[fPhaseLeaf], fPhaseLeaf );
+ }
+ Map_TimeCutComputeArrival( NULL, pCut, fPhase, MAP_FLOAT_LARGE );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the arrival times of the cut.]
+
+ Description [Computes the arrival times of the cut if it is implemented using
+ the given supergate with the given phase. Uses the constraint-type specification
+ of rise/fall arrival times.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstLimit )
+{
+ Map_Match_t * pM = pCut->M + fPhase;
+ Map_Super_t * pSuper = pM->pSuperBest;
+ unsigned uPhaseTot = pM->uPhaseBest;
+ Map_Time_t * ptArrRes = &pM->tArrive;
+ Map_Time_t * ptArrIn;
+ bool fPinPhase;
+ float tDelay;
+ int i;
+
+ ptArrRes->Rise = ptArrRes->Fall = 0.0;
+ ptArrRes->Worst = MAP_FLOAT_LARGE;
+ for ( i = pCut->nLeaves - 1; i >= 0; i-- )
+ {
+ // get the phase of the given pin
+ fPinPhase = ((uPhaseTot & (1 << i)) == 0);
+ ptArrIn = pCut->ppLeaves[i]->tArrival + fPinPhase;
+
+ // get the rise of the output due to rise of the inputs
+ if ( pSuper->tDelaysR[i].Rise > 0 )
+ {
+ tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise;
+ if ( tDelay > tWorstLimit )
+ return MAP_FLOAT_LARGE;
+ if ( ptArrRes->Rise < tDelay )
+ ptArrRes->Rise = tDelay;
+ }
+
+ // get the rise of the output due to fall of the inputs
+ if ( pSuper->tDelaysR[i].Fall > 0 )
+ {
+ tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall;
+ if ( tDelay > tWorstLimit )
+ return MAP_FLOAT_LARGE;
+ if ( ptArrRes->Rise < tDelay )
+ ptArrRes->Rise = tDelay;
+ }
+
+ // get the fall of the output due to rise of the inputs
+ if ( pSuper->tDelaysF[i].Rise > 0 )
+ {
+ tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise;
+ if ( tDelay > tWorstLimit )
+ return MAP_FLOAT_LARGE;
+ if ( ptArrRes->Fall < tDelay )
+ ptArrRes->Fall = tDelay;
+ }
+
+ // get the fall of the output due to fall of the inputs
+ if ( pSuper->tDelaysF[i].Fall > 0 )
+ {
+ tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall;
+ if ( tDelay > tWorstLimit )
+ return MAP_FLOAT_LARGE;
+ if ( ptArrRes->Fall < tDelay )
+ ptArrRes->Fall = tDelay;
+ }
+ }
+ // return the worst-case of rise/fall arrival times
+ ptArrRes->Worst = MAP_MAX(ptArrRes->Rise, ptArrRes->Fall);
+ return ptArrRes->Worst;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the maximum arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Map_TimeComputeArrivalMax( Map_Man_t * p )
+{
+ float tReqMax, tReq;
+ int i, fPhase;
+ // get the critical PO arrival time
+ tReqMax = -MAP_FLOAT_LARGE;
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ if ( Map_NodeIsConst(p->pOutputs[i]) )
+ continue;
+ fPhase = !Map_IsComplement(p->pOutputs[i]);
+ tReq = Map_Regular(p->pOutputs[i])->tArrival[fPhase].Worst;
+ tReqMax = MAP_MAX( tReqMax, tReq );
+ }
+ return tReqMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TimeComputeRequiredGlobal( Map_Man_t * p )
+{
+ p->fRequiredGlo = Map_TimeComputeArrivalMax( p );
+ // update the required times according to the target
+ if ( p->DelayTarget != -1 )
+ {
+ if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon )
+ {
+ if ( p->fMappingMode == 1 )
+ printf( "Cannot meet the target required times (%4.2f). Continue anyway.\n", p->DelayTarget );
+ }
+ else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon )
+ {
+ if ( p->fMappingMode == 1 )
+ printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget );
+ p->fRequiredGlo = p->DelayTarget;
+ }
+ }
+ Map_TimeComputeRequired( p, p->fRequiredGlo );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times of all nodes.]
+
+ Description [This procedure assumes that the nodes used in the mapping
+ are collected in p->vMapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TimeComputeRequired( Map_Man_t * p, float fRequired )
+{
+ Map_Time_t * ptTime;
+ int fPhase, i;
+
+ // clean the required times
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ p->vAnds->pArray[i]->tRequired[0].Rise = MAP_FLOAT_LARGE;
+ p->vAnds->pArray[i]->tRequired[0].Fall = MAP_FLOAT_LARGE;
+ p->vAnds->pArray[i]->tRequired[0].Worst = MAP_FLOAT_LARGE;
+ p->vAnds->pArray[i]->tRequired[1].Rise = MAP_FLOAT_LARGE;
+ p->vAnds->pArray[i]->tRequired[1].Fall = MAP_FLOAT_LARGE;
+ p->vAnds->pArray[i]->tRequired[1].Worst = MAP_FLOAT_LARGE;
+ }
+
+ // set the required times for the POs
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ fPhase = !Map_IsComplement(p->pOutputs[i]);
+ ptTime = Map_Regular(p->pOutputs[i])->tRequired + fPhase;
+ ptTime->Rise = ptTime->Fall = ptTime->Worst = fRequired;
+ }
+
+ // sorts the nodes in the decreasing order of levels
+ // this puts the nodes in reverse topological order
+ Map_MappingSortByLevel( p, p->vMapping );
+ Map_TimePropagateRequired( p, p->vMapping );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times of the given nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TimePropagateRequired( Map_Man_t * p, Map_NodeVec_t * vNodes )
+{
+ Map_Node_t * pNode;
+ Map_Time_t tReqOutTest, * ptReqOutTest = &tReqOutTest;
+ Map_Time_t * ptReqIn, * ptReqOut;
+ int fPhase, k;
+
+ // go through the nodes in the reverse topological order
+ for ( k = 0; k < vNodes->nSize; k++ )
+ {
+ pNode = vNodes->pArray[k];
+
+ // this computation works for regular nodes only
+ assert( !Map_IsComplement(pNode) );
+ // at least one phase should be mapped
+ assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL );
+ // the node should be used in the currently assigned mapping
+ assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 );
+
+ // if one of the cuts is not given, project the required times from the other cut
+ if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL )
+ {
+// assert( 0 );
+ // get the missing phase
+ fPhase = (pNode->pCutBest[1] == NULL);
+ // check if the missing phase is needed in the mapping
+ if ( pNode->nRefAct[fPhase] > 0 )
+ {
+ // get the pointers to the required times of the missing phase
+ ptReqOut = pNode->tRequired + fPhase;
+// assert( ptReqOut->Fall < MAP_FLOAT_LARGE );
+ // get the pointers to the required times of the present phase
+ ptReqIn = pNode->tRequired + !fPhase;
+ // propagate the required times from the missing phase to the present phase
+ // tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall;
+ // tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise;
+ ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, ptReqOut->Rise - p->pSuperLib->tDelayInv.Rise );
+ ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, ptReqOut->Fall - p->pSuperLib->tDelayInv.Fall );
+ }
+ }
+
+ // finalize the worst case computation
+ pNode->tRequired[0].Worst = MAP_MIN( pNode->tRequired[0].Fall, pNode->tRequired[0].Rise );
+ pNode->tRequired[1].Worst = MAP_MIN( pNode->tRequired[1].Fall, pNode->tRequired[1].Rise );
+
+ // skip the PIs
+ if ( !Map_NodeIsAnd(pNode) )
+ continue;
+
+ // propagate required times of different phases of the node
+ // the ordering of phases does not matter since they are mapped independently
+ if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE )
+ Map_TimePropagateRequiredPhase( p, pNode, 0 );
+ if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE )
+ Map_TimePropagateRequiredPhase( p, pNode, 1 );
+ }
+
+ // in the end, we verify the required times
+ // for this, we compute the arrival times of the outputs of each phase
+ // of the supergates using the fanins' required times as the fanins' arrival times
+ // the resulting arrival time of the supergate should be less than the actual required time
+ for ( k = 0; k < vNodes->nSize; k++ )
+ {
+ pNode = vNodes->pArray[k];
+ if ( !Map_NodeIsAnd(pNode) )
+ continue;
+ // verify that the required times are propagated correctly
+// if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) )
+ if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE )
+ {
+ Map_MatchComputeReqTimes( pNode->pCutBest[0], 0, ptReqOutTest );
+ assert( ptReqOutTest->Rise < pNode->tRequired[0].Rise + p->fEpsilon );
+ assert( ptReqOutTest->Fall < pNode->tRequired[0].Fall + p->fEpsilon );
+ }
+// if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) )
+ if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE )
+ {
+ Map_MatchComputeReqTimes( pNode->pCutBest[1], 1, ptReqOutTest );
+ assert( ptReqOutTest->Rise < pNode->tRequired[1].Rise + p->fEpsilon );
+ assert( ptReqOutTest->Fall < pNode->tRequired[1].Fall + p->fEpsilon );
+ }
+ }
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the required times of the given nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase )
+{
+ Map_Time_t * ptReqIn, * ptReqOut;
+ Map_Cut_t * pCut;
+ Map_Super_t * pSuper;
+ float tNewReqTime;
+ unsigned uPhase;
+ int fPinPhase, i;
+
+ // get the cut to be propagated
+ pCut = pNode->pCutBest[fPhase];
+ assert( pCut != NULL );
+ // get the supergate and its polarity
+ pSuper = pCut->M[fPhase].pSuperBest;
+ uPhase = pCut->M[fPhase].uPhaseBest;
+ // get the required time of the output of the supergate
+ ptReqOut = pNode->tRequired + fPhase;
+ // set the required time of the children
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ // get the phase of the given pin of the supergate
+ fPinPhase = ((uPhase & (1 << i)) == 0);
+ ptReqIn = pCut->ppLeaves[i]->tRequired + fPinPhase;
+ assert( pCut->ppLeaves[i]->nRefAct[2] > 0 );
+
+ // get the rise of the output due to rise of the inputs
+// if ( ptArrOut->Rise < ptArrIn->Rise + pSuper->tDelaysR[i].Rise )
+// ptArrOut->Rise = ptArrIn->Rise + pSuper->tDelaysR[i].Rise;
+ if ( pSuper->tDelaysR[i].Rise > 0 )
+ {
+ tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Rise;
+ ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime );
+ }
+
+ // get the rise of the output due to fall of the inputs
+// if ( ptArrOut->Rise < ptArrIn->Fall + pSuper->tDelaysR[i].Fall )
+// ptArrOut->Rise = ptArrIn->Fall + pSuper->tDelaysR[i].Fall;
+ if ( pSuper->tDelaysR[i].Fall > 0 )
+ {
+ tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Fall;
+ ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime );
+ }
+
+ // get the fall of the output due to rise of the inputs
+// if ( ptArrOut->Fall < ptArrIn->Rise + pSuper->tDelaysF[i].Rise )
+// ptArrOut->Fall = ptArrIn->Rise + pSuper->tDelaysF[i].Rise;
+ if ( pSuper->tDelaysF[i].Rise > 0 )
+ {
+ tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Rise;
+ ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime );
+ }
+
+ // get the fall of the output due to fall of the inputs
+// if ( ptArrOut->Fall < ptArrIn->Fall + pSuper->tDelaysF[i].Fall )
+// ptArrOut->Fall = ptArrIn->Fall + pSuper->tDelaysF[i].Fall;
+ if ( pSuper->tDelaysF[i].Fall > 0 )
+ {
+ tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Fall;
+ ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime );
+ }
+ }
+
+ // compare the required times with the arrival times
+ assert( pNode->tArrival[fPhase].Rise < ptReqOut->Rise + p->fEpsilon );
+ assert( pNode->tArrival[fPhase].Fall < ptReqOut->Fall + p->fEpsilon );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the arrival times of the cut.]
+
+ Description [Computes the arrival times of the cut if it is implemented using
+ the given supergate with the given phase. Uses the constraint-type specification
+ of rise/fall arrival times.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes )
+{
+ Map_Time_t * ptArrIn;
+ Map_Super_t * pSuper;
+ unsigned uPhaseTot;
+ int fPinPhase, i;
+ float tDelay;
+
+ // get the supergate and the phase
+ pSuper = pCut->M[fPhase].pSuperBest;
+ uPhaseTot = pCut->M[fPhase].uPhaseBest;
+
+ // propagate the arrival times
+ ptArrRes->Rise = ptArrRes->Fall = -MAP_FLOAT_LARGE;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ // get the phase of the given pin
+ fPinPhase = ((uPhaseTot & (1 << i)) == 0);
+ ptArrIn = pCut->ppLeaves[i]->tRequired + fPinPhase;
+// assert( ptArrIn->Worst < MAP_FLOAT_LARGE );
+
+ // get the rise of the output due to rise of the inputs
+ if ( pSuper->tDelaysR[i].Rise > 0 )
+ {
+ tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise;
+ if ( ptArrRes->Rise < tDelay )
+ ptArrRes->Rise = tDelay;
+ }
+
+ // get the rise of the output due to fall of the inputs
+ if ( pSuper->tDelaysR[i].Fall > 0 )
+ {
+ tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall;
+ if ( ptArrRes->Rise < tDelay )
+ ptArrRes->Rise = tDelay;
+ }
+
+ // get the fall of the output due to rise of the inputs
+ if ( pSuper->tDelaysF[i].Rise > 0 )
+ {
+ tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise;
+ if ( ptArrRes->Fall < tDelay )
+ ptArrRes->Fall = tDelay;
+ }
+
+ // get the fall of the output due to fall of the inputs
+ if ( pSuper->tDelaysF[i].Fall > 0 )
+ {
+ tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall;
+ if ( ptArrRes->Fall < tDelay )
+ ptArrRes->Fall = tDelay;
+ }
+ }
+ // return the worst-case of rise/fall arrival times
+ return MAP_MAX(ptArrRes->Rise, ptArrRes->Fall);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperTree.c b/src/map/mapper/mapperTree.c
new file mode 100644
index 00000000..61e12748
--- /dev/null
+++ b/src/map/mapper/mapperTree.c
@@ -0,0 +1,804 @@
+/**CFile****************************************************************
+
+ FileName [mapperTree.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperTree.c,v 1.9 2005/01/23 06:59:45 alanmi Exp $]
+
+***********************************************************************/
+
+#ifdef __linux__
+#include <libgen.h>
+#endif
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName );
+static Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVars );
+static int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate );
+static void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin );
+static int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate );
+static unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate );
+
+// fanout limits
+extern const int s_MapFanoutLimits[10] = { 1/*0*/, 10/*1*/, 5/*2*/, 2/*3*/, 1/*4*/, 1/*5*/, 1/*6*/ };
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads the supergate library from file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_LibraryReadTree( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile )
+{
+ FILE * pFile;
+ int Status, num;
+ Abc_Frame_t * pAbc;
+ st_table * tExcludeGate = 0;
+
+ // read the beginning of the file
+ assert( pLib->pGenlib == NULL );
+// pFile = Io_FileOpen( pFileName, "open_path", "r" );
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ printf( "Cannot open input file \"%s\".\n", pFileName );
+ return 0;
+ }
+
+ if ( pExcludeFile )
+ {
+ pAbc = Abc_FrameGetGlobalFrame();
+
+ tExcludeGate = st_init_table(strcmp, st_strhash);
+ if ( (num = Mio_LibraryReadExclude( pAbc, pExcludeFile, tExcludeGate )) == -1 )
+ {
+ st_free_table( tExcludeGate );
+ tExcludeGate = 0;
+ return 0;
+ }
+
+ fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num );
+ }
+
+ Status = Map_LibraryReadFileTree( pLib, pFile, pFileName );
+ fclose( pFile );
+ if ( Status == 0 )
+ return 0;
+ // prepare the info about the library
+ return Map_LibraryDeriveGateInfo( pLib, tExcludeGate );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Reads the library file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName )
+{
+ ProgressBar * pProgress;
+ char pBuffer[5000], pLibFile[5000];
+ FILE * pFileGen;
+ Map_Super_t * pGate;
+ char * pTemp = 0, * pLibName;
+ int nCounter, k, i;
+
+ // skip empty and comment lines
+ while ( fgets( pBuffer, 5000, pFile ) != NULL )
+ {
+ // skip leading spaces
+ for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+ // skip comment lines and empty lines
+ if ( *pTemp != 0 && *pTemp != '#' )
+ break;
+ }
+
+ // get the genlib file name (base)
+ pLibName = strtok( pTemp, " \t\r\n" );
+
+ if ( strcmp( pLibName, "GATE" ) == 0 )
+ {
+ printf( "The input file \"%s\" looks like a GENLIB file and not a supergate library file.\n", pLib->pName );
+ return 0;
+ }
+
+
+ // now figure out the directory if any in the pFileName
+#ifdef __linux__
+ snprintf( pLibFile, 5000, "%s/%s", dirname(strdup(pFileName)), pLibName );
+#else
+ {
+ char * pStr;
+ strcpy( pLibFile, pFileName );
+ pStr = pLibFile + strlen(pBuffer) - 1;
+ while ( pStr > pLibFile && *pStr != '\\' && *pStr != '/' )
+ pStr--;
+ if ( pStr == pLibFile )
+ strcpy( pLibFile, pLibName );
+ else
+ sprintf( pStr, "/%s", pLibName );
+ }
+#endif
+
+// pFileGen = Io_FileOpen( pLibFile, "open_path", "r" );
+ pFileGen = fopen( pLibFile, "r" );
+ if ( pFileGen == NULL )
+ {
+ printf( "Cannot open the GENLIB file \"%s\".\n", pLibFile );
+ return 0;
+ }
+ fclose( pFileGen );
+
+ // read the genlib library
+ pLib->pGenlib = Mio_LibraryRead( Abc_FrameGetGlobalFrame(), pLibFile, 0, 0 );
+ if ( pLib->pGenlib == NULL )
+ {
+ printf( "Cannot read GENLIB file \"%s\".\n", pLibFile );
+ return 0;
+ }
+
+ // read the number of variables
+ fscanf( pFile, "%d\n", &pLib->nVarsMax );
+ if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 )
+ {
+ printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax );
+ return 0;
+ }
+
+ // read the number of gates
+ fscanf( pFile, "%d\n", &pLib->nSupersReal );
+ if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 )
+ {
+ printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal );
+ return 0;
+ }
+
+ // read the number of lines
+ fscanf( pFile, "%d\n", &pLib->nLines );
+ if ( pLib->nLines < 1 || pLib->nLines > 10000000 )
+ {
+ printf( "Suspicious number of lines (%d).\n", pLib->nLines );
+ return 0;
+ }
+
+ // allocate room for supergate pointers
+ pLib->ppSupers = ALLOC( Map_Super_t *, pLib->nLines + 10000 );
+
+ // create the elementary supergates
+ for ( i = 0; i < pLib->nVarsMax; i++ )
+ {
+ // get a new gate
+ pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers );
+ memset( pGate, 0, sizeof(Map_Super_t) );
+ // assign the elementary variable, the truth table, and the delays
+ pGate->Num = i;
+ // set the truth table
+ pGate->uTruth[0] = pLib->uTruths[i][0];
+ pGate->uTruth[1] = pLib->uTruths[i][1];
+ // set the arrival times of all input to non-existent delay
+ for ( k = 0; k < pLib->nVarsMax; k++ )
+ {
+ pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR;
+ pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR;
+ }
+ // set an existent arrival time for rise and fall
+ pGate->tDelaysR[i].Rise = 0.0;
+ pGate->tDelaysF[i].Fall = 0.0;
+ // set the gate
+ pLib->ppSupers[i] = pGate;
+ }
+
+ // read the lines
+ nCounter = pLib->nVarsMax;
+ pProgress = Extra_ProgressBarStart( stdout, pLib->nLines );
+ while ( fgets( pBuffer, 5000, pFile ) != NULL )
+ {
+ for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ );
+ if ( pTemp[0] == '\0' )
+ continue;
+// if ( pTemp[0] == 'a' || pTemp[2] == 'a' )
+// {
+// pLib->nLines--;
+// continue;
+// }
+
+ // get the gate
+ pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax );
+ if ( pGate == NULL )
+ {
+ Extra_ProgressBarStop( pProgress );
+ return 0;
+ }
+ pLib->ppSupers[nCounter++] = pGate;
+ // later we will derive: truth table, delays, area, number of component gates, etc
+
+ // update the progress bar
+ Extra_ProgressBarUpdate( pProgress, nCounter, NULL );
+ }
+ Extra_ProgressBarStop( pProgress );
+ if ( nCounter != pLib->nLines )
+ printf( "The number of lines read (%d) is different what the file says (%d).\n", nCounter, pLib->nLines );
+ pLib->nSupersAll = nCounter;
+ // count the number of real supergates
+ nCounter = 0;
+ for ( k = 0; k < pLib->nLines; k++ )
+ nCounter += pLib->ppSupers[k]->fSuper;
+ if ( nCounter != pLib->nSupersReal )
+ printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal );
+ pLib->nSupersReal = nCounter;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads one gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVarsMax )
+{
+ Map_Super_t * pGate;
+ char * pTemp;
+ int i, Num;
+
+ // start and clean the gate
+ pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers );
+ memset( pGate, 0, sizeof(Map_Super_t) );
+
+ // set the gate number
+ pGate->Num = Number;
+
+ // read the mark
+ pTemp = strtok( pBuffer, " " );
+ if ( pTemp[0] == '*' )
+ {
+ pGate->fSuper = 1;
+ pTemp = strtok( NULL, " " );
+ }
+
+ // read the root gate
+ pGate->pRoot = Mio_LibraryReadGateByName( pLib->pGenlib, pTemp );
+ if ( pGate->pRoot == NULL )
+ {
+ printf( "Cannot read the root gate names %s.\n", pTemp );
+ return NULL;
+ }
+ // set the max number of fanouts
+ pGate->nFanLimit = s_MapFanoutLimits[ Mio_GateReadInputs(pGate->pRoot) ];
+
+ // read the pin-to-pin delay
+ for ( i = 0; ( pTemp = strtok( NULL, " \n\0" ) ); i++ )
+ {
+ if ( pTemp[0] == '#' )
+ break;
+ if ( i == nVarsMax )
+ {
+ printf( "There are too many entries on the line.\n" );
+ return NULL;
+ }
+ Num = atoi(pTemp);
+ if ( Num < 0 )
+ {
+ printf( "The number of a child supergate is negative.\n" );
+ return NULL;
+ }
+ if ( Num > pLib->nLines )
+ {
+ printf( "The number of a child supergate (%d) exceeded the number of lines (%d).\n",
+ Num, pLib->nLines );
+ return NULL;
+ }
+ pGate->pFanins[i] = pLib->ppSupers[Num];
+ }
+ pGate->nFanins = i;
+ if ( pGate->nFanins != (unsigned)Mio_GateReadInputs(pGate->pRoot) )
+ {
+ printf( "The number of fanins of a root gate is wrong.\n" );
+ return NULL;
+ }
+
+ // save the gate name, just in case
+ if ( pTemp && pTemp[0] == '#' )
+ {
+ if ( pTemp[1] == 0 )
+ pTemp = strtok( NULL, " \n\0" );
+ else // skip spaces
+ for ( pTemp++; *pTemp == ' '; pTemp++ );
+ // save the formula
+ pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp)+1 );
+ strcpy( pGate->pFormula, pTemp );
+ }
+ // check the rest of the string
+ pTemp = strtok( NULL, " \n\0" );
+ if ( pTemp != NULL )
+ printf( "The following trailing symbols found \"%s\".\n", pTemp );
+ return pGate;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives information about the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate )
+{
+ Map_Super_t * pGate, * pFanin;
+ Mio_Pin_t * pPin;
+ unsigned uCanon[2];
+ unsigned uTruths[6][2];
+ int i, k, nRealVars;
+
+ // set all the derivable info related to the supergates
+ for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ )
+ {
+ pGate = pLib->ppSupers[i];
+
+ if ( tExcludeGate )
+ {
+ if ( st_is_member( tExcludeGate, Mio_GateReadName( pGate->pRoot ) ) )
+ pGate->fExclude = 1;
+ for ( k = 0; k < (int)pGate->nFanins; k++ )
+ {
+ pFanin = pGate->pFanins[k];
+ if ( pFanin->fExclude )
+ {
+ pGate->fExclude = 1;
+ continue;
+ }
+ }
+ }
+
+ // collect the truth tables of the fanins
+ for ( k = 0; k < (int)pGate->nFanins; k++ )
+ {
+ pFanin = pGate->pFanins[k];
+ uTruths[k][0] = pFanin->uTruth[0];
+ uTruths[k][1] = pFanin->uTruth[1];
+ }
+ // derive the new truth table
+ Mio_DeriveTruthTable( pGate->pRoot, uTruths, pGate->nFanins, 6, pGate->uTruth );
+
+ // set the initial delays of the supergate
+ for ( k = 0; k < pLib->nVarsMax; k++ )
+ {
+ pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR;
+ pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR;
+ }
+ // get the linked list of pins for the given root gate
+ pPin = Mio_GateReadPins( pGate->pRoot );
+ // update the initial delay of the supergate using info from the corresponding pin
+ for ( k = 0; k < (int)pGate->nFanins; k++, pPin = Mio_PinReadNext(pPin) )
+ {
+ // if there is no corresponding pin, this is a bug, return fail
+ if ( pPin == NULL )
+ {
+ printf( "There are less pins than gate inputs.\n" );
+ return 0;
+ }
+ // update the delay information of k-th fanins info from the corresponding pin
+ Map_LibraryAddFaninDelays( pLib, pGate, pGate->pFanins[k], pPin );
+ }
+ // if there are some pins left, this is a bug, return fail
+ if ( pPin != NULL )
+ {
+ printf( "There are more pins than gate inputs.\n" );
+ return 0;
+ }
+ // find the max delay
+ pGate->tDelayMax.Rise = pGate->tDelayMax.Fall = MAP_NO_VAR;
+ for ( k = 0; k < pLib->nVarsMax; k++ )
+ {
+ // the rise of the output depends on the rise and fall of the output
+ if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Rise )
+ pGate->tDelayMax.Rise = pGate->tDelaysR[k].Rise;
+ if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Fall )
+ pGate->tDelayMax.Rise = pGate->tDelaysR[k].Fall;
+ // the fall of the output depends on the rise and fall of the output
+ if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Rise )
+ pGate->tDelayMax.Fall = pGate->tDelaysF[k].Rise;
+ if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Fall )
+ pGate->tDelayMax.Fall = pGate->tDelaysF[k].Fall;
+ }
+
+ // count gates and area of the supergate
+ pGate->nGates = 1;
+ pGate->Area = (float)Mio_GateReadArea(pGate->pRoot);
+ for ( k = 0; k < (int)pGate->nFanins; k++ )
+ {
+ pGate->nGates += pGate->pFanins[k]->nGates;
+ pGate->Area += pGate->pFanins[k]->Area;
+ }
+ // do not add the gate to the table, if this gate is an internal gate
+ // of some supegate and does not correspond to a supergate output
+ if ( ( !pGate->fSuper ) || pGate->fExclude )
+ continue;
+
+ // find the maximum index of a variable in the support of the supergates
+ // this is important for two reasons:
+ // (1) to limit the number of permutations considered for canonicization
+ // (2) to get rid of equivalence phases to speed-up matching
+ nRealVars = Map_LibraryGetMaxSuperPi_rec( pGate ) + 1;
+ assert( nRealVars > 0 && nRealVars <= pLib->nVarsMax );
+ // if there are some problems with this code, try this instead
+// nRealVars = pLib->nVarsMax;
+
+ // find the N-canonical form of this supergate
+ pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon );
+ // add the supergate into the table by its N-canonical table
+ Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate );
+ }
+ // sort the gates in each line
+ Map_SuperTableSortSupergatesByDelay( pLib->tTableC, pLib->nSupersAll );
+
+ // let the glory be manifest
+// Map_LibraryPrintTree( pLib );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the largest PI number in the support of the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate )
+{
+ int i, VarCur, VarMax = 0;
+ if ( pGate->pRoot == NULL )
+ return pGate->Num;
+ for ( i = 0; i < (int)pGate->nFanins; i++ )
+ {
+ VarCur = Map_LibraryGetMaxSuperPi_rec( pGate->pFanins[i] );
+ if ( VarMax < VarCur )
+ VarMax = VarCur;
+ }
+ return VarMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the largest PI number in the support of the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate )
+{
+ unsigned uSupport;
+ int i;
+ if ( pGate->pRoot == NULL )
+ return (unsigned)(1 << (pGate->Num));
+ uSupport = 0;
+ for ( i = 0; i < (int)pGate->nFanins; i++ )
+ uSupport |= Map_LibraryGetGateSupp_rec( pGate->pFanins[i] );
+ return uSupport;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the pin-to-pin delay constraints for the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin )
+{
+ Mio_PinPhase_t PinPhase;
+ float tDelayBlockRise, tDelayBlockFall, tDelayPin;
+ bool fMaxDelay = 0;
+ int i;
+
+ // use this node to enable max-delay model
+ if ( fMaxDelay )
+ {
+ float tDelayBlockMax;
+ // get the maximum delay
+ tDelayBlockMax = (float)Mio_PinReadDelayBlockMax(pPin);
+ // go through the supergate inputs
+ for ( i = 0; i < pLib->nVarsMax; i++ )
+ {
+ if ( pFanin->tDelaysR[i].Rise < 0 )
+ continue;
+ tDelayPin = pFanin->tDelaysR[i].Rise + tDelayBlockMax;
+ if ( pGate->tDelaysR[i].Rise < tDelayPin )
+ pGate->tDelaysR[i].Rise = tDelayPin;
+ }
+ // go through the supergate inputs
+ for ( i = 0; i < pLib->nVarsMax; i++ )
+ {
+ if ( pFanin->tDelaysF[i].Fall < 0 )
+ continue;
+ tDelayPin = pFanin->tDelaysF[i].Fall + tDelayBlockMax;
+ if ( pGate->tDelaysF[i].Fall < tDelayPin )
+ pGate->tDelaysF[i].Fall = tDelayPin;
+ }
+ return;
+ }
+
+ // get the interesting parameters of this pin
+ PinPhase = Mio_PinReadPhase(pPin);
+ tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
+ tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );
+
+ // update the rise and fall of the output depending on the phase of the pin
+ if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present
+ {
+ // the rise of the gate is determined by the rise of the fanin
+ // the fall of the gate is determined by the fall of the fanin
+ for ( i = 0; i < pLib->nVarsMax; i++ )
+ {
+ ////////////////////////////////////////////////////////
+ // consider the rise of the gate
+ ////////////////////////////////////////////////////////
+ // check two types of constraints on the rise of the fanin:
+ // (1) the constraints related to the rise of the PIs
+ // (2) the constraints related to the fall of the PIs
+ if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1)
+ { // fanin's rise depends on the rise of i-th PI
+ // update the rise of the gate's output
+ if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockRise )
+ pGate->tDelaysR[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockRise;
+ }
+ if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2)
+ { // fanin's rise depends on the fall of i-th PI
+ // update the rise of the gate's output
+ if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockRise )
+ pGate->tDelaysR[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockRise;
+ }
+ ////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////////////////////
+ // consider the fall of the gate (similar)
+ ////////////////////////////////////////////////////////
+ // check two types of constraints on the fall of the fanin:
+ // (1) the constraints related to the rise of the PIs
+ // (2) the constraints related to the fall of the PIs
+ if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1)
+ {
+ if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockFall )
+ pGate->tDelaysF[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockFall;
+ }
+ if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2)
+ {
+ if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockFall )
+ pGate->tDelaysF[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockFall;
+ }
+ ////////////////////////////////////////////////////////
+ }
+ }
+ if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present
+ {
+ // the rise of the gate is determined by the fall of the fanin
+ // the fall of the gate is determined by the rise of the fanin
+ for ( i = 0; i < pLib->nVarsMax; i++ )
+ {
+ ////////////////////////////////////////////////////////
+ // consider the rise of the gate's output
+ ////////////////////////////////////////////////////////
+ // check two types of constraints on the fall of the fanin:
+ // (1) the constraints related to the rise of the PIs
+ // (2) the constraints related to the fall of the PIs
+ if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1)
+ { // fanin's rise depends on the rise of i-th PI
+ // update the rise of the gate
+ if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockRise )
+ pGate->tDelaysR[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockRise;
+ }
+ if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2)
+ { // fanin's rise depends on the fall of i-th PI
+ // update the rise of the gate
+ if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockRise )
+ pGate->tDelaysR[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockRise;
+ }
+ ////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////////////////////
+ // consider the fall of the gate (similar)
+ ////////////////////////////////////////////////////////
+ // check two types of constraints on the rise of the fanin:
+ // (1) the constraints related to the rise of the PIs
+ // (2) the constraints related to the fall of the PIs
+ if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1)
+ {
+ if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockFall )
+ pGate->tDelaysF[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockFall;
+ }
+ if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2)
+ {
+ if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockFall )
+ pGate->tDelaysF[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockFall;
+ }
+ ////////////////////////////////////////////////////////
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs phase transformation for one function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Map_CalculatePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase )
+{
+ int v, Shift;
+ for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 )
+ if ( uPhase & Shift )
+ uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift));
+ return uTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs phase transformation for one function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_CalculatePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] )
+{
+ unsigned uTemp;
+ int v, Shift;
+
+ // initialize the result
+ uTruthRes[0] = uTruth[0];
+ uTruthRes[1] = uTruth[1];
+ if ( uPhase == 0 )
+ return;
+ // compute the phase
+ for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 )
+ if ( uPhase & Shift )
+ {
+ if ( Shift < 32 )
+ {
+ uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift));
+ uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift));
+ }
+ else
+ {
+ uTemp = uTruthRes[0];
+ uTruthRes[0] = uTruthRes[1];
+ uTruthRes[1] = uTemp;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the supergate library after deriving parameters.]
+
+ Description [This procedure is very useful to see the library after
+ it has been read into the mapper by "read_super" and all the information
+ about the supergates derived.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_LibraryPrintTree( Map_SuperLib_t * pLib )
+{
+ Map_Super_t * pGate;
+ int i, k;
+
+ // print all the info related to the supergates
+// for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ )
+ for ( i = pLib->nVarsMax; i < 20; i++ )
+ {
+ pGate = pLib->ppSupers[i];
+
+ // write the gate's fanin info and formula
+ printf( "%6d ", pGate->Num );
+ printf( "%c ", pGate->fSuper? '*' : ' ' );
+ printf( "%6s", Mio_GateReadName(pGate->pRoot) );
+ for ( k = 0; k < (int)pGate->nFanins; k++ )
+ printf( " %6d", pGate->pFanins[k]->Num );
+ printf( " %s", pGate->pFormula );
+ printf( "\n" );
+
+ // write the gate's derived info
+ Extra_PrintBinary( stdout, pGate->uTruth, 64 );
+ printf( " %3d", pGate->nGates );
+ printf( " %6.2f", pGate->Area );
+ printf( " (%4.2f, %4.2f)", pGate->tDelayMax.Rise, pGate->tDelayMax.Fall );
+ printf( "\n" );
+ for ( k = 0; k < pLib->nVarsMax; k++ )
+ {
+ // print the constraint on the rise of the gate in the form (D1, D2),
+ // where D1 is the constraint related to the rise of the k-th PI
+ // where D2 is the constraint related to the fall of the k-th PI
+ if ( pGate->tDelaysR[k].Rise < 0 && pGate->tDelaysR[k].Fall < 0 )
+ printf( " (----, ----)" );
+ else if ( pGate->tDelaysR[k].Fall < 0 )
+ printf( " (%4.2f, ----)", pGate->tDelaysR[k].Rise );
+ else if ( pGate->tDelaysR[k].Rise < 0 )
+ printf( " (----, %4.2f)", pGate->tDelaysR[k].Fall );
+ else
+ printf( " (%4.2f, %4.2f)", pGate->tDelaysR[k].Rise, pGate->tDelaysR[k].Fall );
+
+ // print the constraint on the fall of the gate in the form (D1, D2),
+ // where D1 is the constraint related to the rise of the k-th PI
+ // where D2 is the constraint related to the fall of the k-th PI
+ if ( pGate->tDelaysF[k].Rise < 0 && pGate->tDelaysF[k].Fall < 0 )
+ printf( " (----, ----)" );
+ else if ( pGate->tDelaysF[k].Fall < 0 )
+ printf( " (%4.2f, ----)", pGate->tDelaysF[k].Rise );
+ else if ( pGate->tDelaysF[k].Rise < 0 )
+ printf( " (----, %4.2f)", pGate->tDelaysF[k].Fall );
+ else
+ printf( " (%4.2f, %4.2f)", pGate->tDelaysF[k].Rise, pGate->tDelaysF[k].Fall );
+ printf( "\n" );
+ }
+ printf( "\n" );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperTruth.c b/src/map/mapper/mapperTruth.c
new file mode 100644
index 00000000..9388b42f
--- /dev/null
+++ b/src/map/mapper/mapperTruth.c
@@ -0,0 +1,449 @@
+/**CFile****************************************************************
+
+ FileName [mapperTruth.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperTruth.c,v 1.8 2005/01/23 06:59:45 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+//static void Map_TruthsCutDcs( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] );
+static void Map_TruthsCut( Map_Man_t * pMan, Map_Cut_t * pCut );
+static void Map_TruthsCut_rec( Map_Cut_t * pCut, unsigned uTruth[] );
+static void Map_TruthsUnmark_rec( Map_Cut_t * pCut );
+
+/*
+static int s_Same = 0;
+static int s_Diff = 0;
+static int s_Same2 = 0;
+static int s_Diff2 = 0;
+static int s_Truth = 0;
+static int s_Isop1 = 0;
+static int s_Isop2 = 0;
+*/
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives truth tables for each cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingTruths( Map_Man_t * pMan )
+{
+ ProgressBar * pProgress;
+ Map_Node_t * pNode;
+ Map_Cut_t * pCut;
+ int nNodes, i;
+ // compute the cuts for the POs
+ nNodes = pMan->vAnds->nSize;
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = pMan->vAnds->pArray[i];
+ if ( !Map_NodeIsAnd( pNode ) )
+ continue;
+ assert( pNode->pCuts );
+ assert( pNode->pCuts->nLeaves == 1 );
+
+ // match the simple cut
+ pNode->pCuts->M[0].uPhase = 0;
+ pNode->pCuts->M[0].pSupers = pMan->pSuperLib->pSuperInv;
+ pNode->pCuts->M[0].uPhaseBest = 0;
+ pNode->pCuts->M[0].pSuperBest = pMan->pSuperLib->pSuperInv;
+
+ pNode->pCuts->M[1].uPhase = 0;
+ pNode->pCuts->M[1].pSupers = pMan->pSuperLib->pSuperInv;
+ pNode->pCuts->M[1].uPhaseBest = 1;
+ pNode->pCuts->M[1].pSuperBest = pMan->pSuperLib->pSuperInv;
+
+ // match the rest of the cuts
+ for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext )
+ Map_TruthsCut( pMan, pCut );
+ Extra_ProgressBarUpdate( pProgress, i, "Tables ..." );
+ }
+ Extra_ProgressBarStop( pProgress );
+
+// printf( "Same = %6d. Diff = %6d.\n", s_Same, s_Diff );
+// printf( "Same2 = %6d. Diff2 = %6d.\n", s_Same2, s_Diff2 );
+// printf( "Truth = %6d. Isop1 = %6d. Isop2 = %6d.\n", s_Truth, s_Isop1, s_Isop2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the truth table for one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut )
+{
+ unsigned uTruth[2], uCanon[2];
+ unsigned char uPhases[16];
+ int i;
+
+ // generally speaking, 1-input cut can be matched into a wire!
+ if ( pCut->nLeaves == 1 )
+ return;
+ // set the leaf truth tables
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pCut->ppLeaves[i]->pCuts->uTruthTemp[0] = p->uTruths[i][0];
+ pCut->ppLeaves[i]->pCuts->uTruthTemp[1] = p->uTruths[i][1];
+ }
+ // recursively compute the truth table
+ pCut->nVolume = 0;
+ Map_TruthsCut_rec( pCut, uTruth );
+ // recursively unmark the visited cuts
+ Map_TruthsUnmark_rec( pCut );
+
+ // compute the canonical form for the positive phase
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[1].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // compute the canonical form for the negative phase
+ uTruth[0] = ~uTruth[0];
+ uTruth[1] = ~uTruth[1];
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[0].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // restore the truth table
+ uTruth[0] = ~uTruth[0];
+ uTruth[1] = ~uTruth[1];
+ // enable don't-care computation
+// Map_TruthsCutDcs( p, pCut, uTruth );
+}
+
+#if 0
+
+/**Function*************************************************************
+
+ Synopsis [Adds several other choices using SDCs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TruthsCutDcs( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] )
+{
+ unsigned uIsop1[2], uIsop2[2], uCanon[2];
+ unsigned char uPhases[16];
+
+ // add several other supergate classes derived using don't-cares
+ if ( pCut->uTruthDc[0] )
+ {
+ int nOnes;
+ nOnes = Map_TruthCountOnes( pCut->uTruthDc, pCut->nLeaves );
+ if ( nOnes == 1 )
+ {
+ uTruth[0] ^= pCut->uTruthDc[0];
+ uTruth[1] ^= pCut->uTruthDc[1];
+
+ // compute the canonical form for the positive phase
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[1].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // compute the canonical form for the negative phase
+ uTruth[0] = ~uTruth[0];
+ uTruth[1] = ~uTruth[1];
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[0].uPhase = uPhases[0];
+ p->nCanons++;
+ }
+ else if ( nOnes == 2 )
+ {
+ int Num1, Num2, RetValue;
+ RetValue = Map_TruthDetectTwoFirst( pCut->uTruthDc, pCut->nLeaves );
+ Num1 = RetValue & 255;
+ Num2 = (RetValue >> 8) & 255;
+
+ // add the first bit
+ Map_InfoFlipVar( uTruth, Num1 );
+
+ // compute the canonical form for the positive phase
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[1].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // compute the canonical form for the negative phase
+ uTruth[0] = ~uTruth[0];
+ uTruth[1] = ~uTruth[1];
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[0].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // add the first bit
+ Map_InfoFlipVar( uTruth, Num2 );
+
+ // compute the canonical form for the positive phase
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[1].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // compute the canonical form for the negative phase
+ uTruth[0] = ~uTruth[0];
+ uTruth[1] = ~uTruth[1];
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[0].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // add the first bit
+ Map_InfoFlipVar( uTruth, Num1 );
+
+ // compute the canonical form for the positive phase
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[1].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // compute the canonical form for the negative phase
+ uTruth[0] = ~uTruth[0];
+ uTruth[1] = ~uTruth[1];
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
+ pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[0].uPhase = uPhases[0];
+ p->nCanons++;
+ }
+ else
+ {
+ // compute the ISOPs
+ uIsop1[0] = Map_ComputeIsop_rec( p, uTruth[0] & ~pCut->uTruthDc[0], uTruth[0] | pCut->uTruthDc[0], 0, pCut->nLeaves, 0 );
+ uIsop1[1] = uIsop1[0];
+ if ( uIsop1[0] != uTruth[0] )
+ {
+ // compute the canonical form for the positive phase
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uIsop1, uPhases, uCanon );
+ pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[1].uPhase = uPhases[0];
+ p->nCanons++;
+
+ // compute the canonical form for the negative phase
+ uIsop1[0] = ~uIsop1[0];
+ uIsop1[1] = ~uIsop1[1];
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uIsop1, uPhases, uCanon );
+ pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[0].uPhase = uPhases[0];
+ p->nCanons++;
+ }
+
+ uIsop2[0] = Map_ComputeIsop_rec( p, uTruth[0] & ~pCut->uTruthDc[0], uTruth[0] | pCut->uTruthDc[0], pCut->nLeaves-1, pCut->nLeaves, 1 );
+ uIsop2[1] = uIsop2[0];
+ if ( uIsop2[0] != uTruth[0] && uIsop2[0] != uIsop1[0] )
+ {
+ // compute the canonical form for the positive phase
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uIsop2, uPhases, uCanon );
+ pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ p->nCanons++;
+
+ // compute the canonical form for the negative phase
+ uIsop2[0] = ~uIsop2[0];
+ uIsop2[1] = ~uIsop2[1];
+ Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uIsop2, uPhases, uCanon );
+ pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
+ pCut->M[0].uPhase = uPhases[0];
+ p->nCanons++;
+ }
+ }
+ }
+}
+
+#endif
+
+/**Function*************************************************************
+
+ Synopsis [Recursively derives the truth table for the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TruthsCut_rec( Map_Cut_t * pCut, unsigned uTruthRes[] )
+{
+ unsigned uTruth1[2], uTruth2[2];
+ // if this is the elementary cut, its truth table is already available
+ if ( pCut->nLeaves == 1 )
+ {
+ uTruthRes[0] = pCut->uTruthTemp[0];
+ uTruthRes[1] = pCut->uTruthTemp[1];
+ return;
+ }
+ // if this node was already visited, return its computed truth table
+ if ( pCut->fMark )
+ {
+ uTruthRes[0] = pCut->uTruthTemp[0];
+ uTruthRes[1] = pCut->uTruthTemp[1];
+ return;
+ }
+ pCut->fMark = 1;
+ pCut->nVolume++;
+
+ assert( !Map_IsComplement(pCut) );
+ Map_TruthsCut_rec( Map_CutRegular(pCut->pOne), uTruth1 );
+ if ( Map_CutIsComplement(pCut->pOne) )
+ {
+ uTruth1[0] = ~uTruth1[0];
+ uTruth1[1] = ~uTruth1[1];
+ }
+ Map_TruthsCut_rec( Map_CutRegular(pCut->pTwo), uTruth2 );
+ if ( Map_CutIsComplement(pCut->pTwo) )
+ {
+ uTruth2[0] = ~uTruth2[0];
+ uTruth2[1] = ~uTruth2[1];
+ }
+ if ( !pCut->Phase )
+ {
+ uTruthRes[0] = pCut->uTruthTemp[0] = uTruth1[0] & uTruth2[0];
+ uTruthRes[1] = pCut->uTruthTemp[1] = uTruth1[1] & uTruth2[1];
+ }
+ else
+ {
+ uTruthRes[0] = pCut->uTruthTemp[0] = ~(uTruth1[0] & uTruth2[0]);
+ uTruthRes[1] = pCut->uTruthTemp[1] = ~(uTruth1[1] & uTruth2[1]);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively derives the truth table for the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_TruthsUnmark_rec( Map_Cut_t * pCut )
+{
+ if ( pCut->nLeaves == 1 )
+ return;
+ // if this node was already visited, return its computed truth table
+ if ( pCut->fMark == 0 )
+ return;
+ pCut->fMark = 0;
+ Map_TruthsUnmark_rec( Map_CutRegular(pCut->pOne) );
+ Map_TruthsUnmark_rec( Map_CutRegular(pCut->pTwo) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the truth table of the don't-care set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_TruthsCutDontCare( Map_Man_t * pMan, Map_Cut_t * pCut, unsigned * uTruthDc )
+{
+ if ( pCut->pOne || (pCut->uTruthZero[0] == 0 && pCut->uTruthZero[1] == 0) )
+ return 0;
+ assert( (pCut->uTruthTemp[0] & pCut->uTruthZero[0]) == 0 );
+ assert( (pCut->uTruthTemp[1] & pCut->uTruthZero[1]) == 0 );
+ uTruthDc[0] = ((~0) & (~pCut->uTruthTemp[0]) & (~pCut->uTruthZero[0]));
+ uTruthDc[1] = ((~0) & (~pCut->uTruthTemp[1]) & (~pCut->uTruthZero[1]));
+ if ( uTruthDc[0] == 0 && uTruthDc[1] == 0 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Expand the truth table]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_TruthCountOnes( unsigned * uTruth, int nLeaves )
+{
+ int i, nMints, Counter;
+ nMints = (1 << nLeaves);
+ Counter = 0;
+ for ( i = 0; i < nMints; i++ )
+ Counter += Map_InfoReadVar( uTruth, i );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Expand the truth table]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_TruthDetectTwoFirst( unsigned * uTruth, int nLeaves )
+{
+ int i, nMints, Num1 = -1, Num2 = -1;
+ nMints = (1 << nLeaves);
+ for ( i = 0; i < nMints; i++ )
+ if ( Map_InfoReadVar( uTruth, i ) )
+ {
+ if ( Num1 == -1 )
+ Num1 = i;
+ else if ( Num2 == -1 )
+ Num2 = i;
+ else
+ break;
+ }
+ assert( Num1 != -1 && Num2 != -1 );
+ return (Num1 << 8) | Num2;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperUtils.c b/src/map/mapper/mapperUtils.c
new file mode 100644
index 00000000..f8fd1a4c
--- /dev/null
+++ b/src/map/mapper/mapperUtils.c
@@ -0,0 +1,1254 @@
+/**CFile****************************************************************
+
+ FileName [mapperUtils.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperUtils.c,v 1.8 2004/11/03 22:41:45 satrajit Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv );
+static int Map_MappingCountLevels_rec( Map_Node_t * pNode );
+static float Map_MappingSetRefsAndArea_rec( Map_Man_t * pMan, Map_Node_t * pNode );
+static float Map_MappingSetRefsAndSwitch_rec( Map_Man_t * pMan, Map_Node_t * pNode );
+static float Map_MappingSetRefsAndWire_rec( Map_Man_t * pMan, Map_Node_t * pNode );
+static void Map_MappingDfsCuts_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes );
+static float Map_MappingArea_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_NodeVec_t * vNodes );
+static int Map_MappingCompareOutputDelay( int * pOut1, int * pOut2 );
+static unsigned Map_MappingExpandTruth_rec( unsigned uTruth, int nVars );
+static void Map_MappingGetChoiceLevels( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2, int * pMin, int * pMax );
+static float Map_MappingGetChoiceVolumes( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 );
+static int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices );
+static Map_Man_t * s_pMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv )
+{
+ Map_NodeVec_t * vNodes;
+ int i;
+ // perform the traversal
+ vNodes = Map_NodeVecAlloc( 100 );
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Map_MappingDfs_rec( Map_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ vNodes->pArray[i]->fMark0 = 0;
+// for ( i = 0; i < pMan->nOutputs; i++ )
+// Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_NodeVec_t * Map_MappingDfsNodes( Map_Man_t * pMan, Map_Node_t ** ppCuts, int nNodes, int fEquiv )
+{
+ Map_NodeVec_t * vNodes;
+ int i;
+ // perform the traversal
+ vNodes = Map_NodeVecAlloc( 200 );
+ for ( i = 0; i < nNodes; i++ )
+ Map_MappingDfs_rec( ppCuts[i], vNodes, fEquiv );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ vNodes->pArray[i]->fMark0 = 0;
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->fMark0 )
+ return;
+ // visit the transitive fanin
+ if ( Map_NodeIsAnd(pNode) )
+ {
+ Map_MappingDfs_rec( Map_Regular(pNode->p1), vNodes, fCollectEquiv );
+ Map_MappingDfs_rec( Map_Regular(pNode->p2), vNodes, fCollectEquiv );
+ }
+ // visit the equivalent nodes
+ if ( fCollectEquiv && pNode->pNextE )
+ Map_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv );
+ // make sure the node is not visited through the equivalent nodes
+ assert( pNode->fMark0 == 0 );
+ // mark the node as visited
+ pNode->fMark0 = 1;
+ // add the node to the list
+ Map_NodeVecPush( vNodes, pNode );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingDfsMarked1_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fFirst )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->fMark0 )
+ return;
+ // visit the transitive fanin
+ if ( Map_NodeIsAnd(pNode) )
+ {
+ Map_MappingDfsMarked1_rec( Map_Regular(pNode->p1), vNodes, 0 );
+ Map_MappingDfsMarked1_rec( Map_Regular(pNode->p2), vNodes, 0 );
+ }
+ // visit the equivalent nodes
+ if ( !fFirst && pNode->pNextE )
+ Map_MappingDfsMarked1_rec( pNode->pNextE, vNodes, 0 );
+ // make sure the node is not visited through the equivalent nodes
+ assert( pNode->fMark0 == 0 );
+ // mark the node as visited
+ pNode->fMark0 = 1;
+ // add the node to the list
+ Map_NodeVecPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingDfsMarked2_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, Map_NodeVec_t * vBoundary, int fFirst )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->fMark1 )
+ return;
+ if ( pNode->fMark0 || Map_NodeIsVar(pNode) )
+ {
+ pNode->fMark1 = 1;
+ Map_NodeVecPush(vBoundary, pNode);
+ return;
+ }
+ // visit the transitive fanin
+ if ( Map_NodeIsAnd(pNode) )
+ {
+ Map_MappingDfsMarked2_rec( Map_Regular(pNode->p1), vNodes, vBoundary, 0 );
+ Map_MappingDfsMarked2_rec( Map_Regular(pNode->p2), vNodes, vBoundary, 0 );
+ }
+ // visit the equivalent nodes
+ if ( !fFirst && pNode->pNextE )
+ Map_MappingDfsMarked2_rec( pNode->pNextE, vNodes, vBoundary, 0 );
+ // make sure the node is not visited through the equivalent nodes
+ assert( pNode->fMark1 == 0 );
+ // mark the node as visited
+ pNode->fMark1 = 1;
+ // add the node to the list
+ Map_NodeVecPush( vNodes, pNode );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingDfsMarked3_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->fMark0 )
+ return;
+ // visit the transitive fanin
+ if ( Map_NodeIsAnd(pNode) )
+ {
+ Map_MappingDfsMarked3_rec( Map_Regular(pNode->p1), vNodes );
+ Map_MappingDfsMarked3_rec( Map_Regular(pNode->p2), vNodes );
+ }
+ // make sure the node is not visited through the equivalent nodes
+ assert( pNode->fMark0 == 0 );
+ // mark the node as visited
+ pNode->fMark0 = 1;
+ // add the node to the list
+ Map_NodeVecPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingDfsMarked4_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->fMark1 )
+ return;
+ // visit the transitive fanin
+ if ( Map_NodeIsAnd(pNode) )
+ {
+ Map_MappingDfsMarked4_rec( Map_Regular(pNode->p1), vNodes );
+ Map_MappingDfsMarked4_rec( Map_Regular(pNode->p2), vNodes );
+ }
+ // make sure the node is not visited through the equivalent nodes
+ assert( pNode->fMark1 == 0 );
+ // mark the node as visited
+ pNode->fMark1 = 1;
+ // add the node to the list
+ Map_NodeVecPush( vNodes, pNode );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the number of logic levels not counting PIs/POs.]
+
+ Description []
+
+ SideEffects [Note that this procedure will reassign the levels assigned
+ originally by NodeCreate() because it counts the number of levels with
+ choices differently!]
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingCountLevels( Map_Man_t * pMan )
+{
+ int i, LevelsMax, LevelsCur;
+ // perform the traversal
+ LevelsMax = -1;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ LevelsCur = Map_MappingCountLevels_rec( Map_Regular(pMan->pOutputs[i]) );
+ if ( LevelsMax < LevelsCur )
+ LevelsMax = LevelsCur;
+ }
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) );
+ return LevelsMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the number of logic levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingCountLevels_rec( Map_Node_t * pNode )
+{
+ int Level1, Level2;
+ assert( !Map_IsComplement(pNode) );
+ if ( !Map_NodeIsAnd(pNode) )
+ {
+ pNode->Level = 0;
+ return 0;
+ }
+ if ( pNode->fMark0 )
+ return pNode->Level;
+ pNode->fMark0 = 1;
+ // visit the transitive fanin
+ Level1 = Map_MappingCountLevels_rec( Map_Regular(pNode->p1) );
+ Level2 = Map_MappingCountLevels_rec( Map_Regular(pNode->p2) );
+ // set the number of levels
+ pNode->Level = 1 + ((Level1>Level2)? Level1: Level2);
+ return pNode->Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Unmarks the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingUnmark( Map_Man_t * pMan )
+{
+ int i;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively unmarks the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingUnmark_rec( Map_Node_t * pNode )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->fMark0 == 0 )
+ return;
+ pNode->fMark0 = 0;
+ if ( !Map_NodeIsAnd(pNode) )
+ return;
+ Map_MappingUnmark_rec( Map_Regular(pNode->p1) );
+ Map_MappingUnmark_rec( Map_Regular(pNode->p2) );
+ // visit the equivalent nodes
+ if ( pNode->pNextE )
+ Map_MappingUnmark_rec( pNode->pNextE );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingMark_rec( Map_Node_t * pNode )
+{
+ assert( !Map_IsComplement(pNode) );
+ if ( pNode->fMark0 == 1 )
+ return;
+ pNode->fMark0 = 1;
+ if ( !Map_NodeIsAnd(pNode) )
+ return;
+ // visit the transitive fanin of the selected cut
+ Map_MappingMark_rec( Map_Regular(pNode->p1) );
+ Map_MappingMark_rec( Map_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints a bunch of latest arriving outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingPrintOutputArrivals( Map_Man_t * p )
+{
+ Map_Time_t * pTimes;
+ Map_Node_t * pNode;
+ int fPhase, Limit, i;
+ int nOutputs;
+ int * pSorted;
+
+ // sort outputs by arrival time
+ s_pMan = p;
+ pSorted = ALLOC( int, p->nOutputs );
+ nOutputs = 0;
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ if ( Map_NodeIsConst(p->pOutputs[i]) )
+ continue;
+ pSorted[nOutputs++] = i;
+ }
+ qsort( (void *)pSorted, nOutputs, sizeof(int),
+ (int (*)(const void *, const void *)) Map_MappingCompareOutputDelay );
+ assert( Map_MappingCompareOutputDelay( pSorted, pSorted + nOutputs - 1 ) <= 0 );
+ s_pMan = NULL;
+
+ // print the latest outputs
+ Limit = (nOutputs > 5)? 5 : nOutputs;
+ for ( i = 0; i < Limit; i++ )
+ {
+ // get the i-th latest output
+ pNode = Map_Regular(p->pOutputs[pSorted[i]]);
+ fPhase =!Map_IsComplement(p->pOutputs[pSorted[i]]);
+ pTimes = pNode->tArrival + fPhase;
+ // print out the best arrival time
+ printf( "Out %20s : ", p->ppOutputNames[pSorted[i]] );
+ printf( "Delay = (%5.2f, %5.2f) ", (double)pTimes->Rise, (double)pTimes->Fall );
+ printf( "%s", fPhase? "POS" : "NEG" );
+ printf( "\n" );
+ }
+ free( pSorted );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the outputs by their arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingCompareOutputDelay( int * pOut1, int * pOut2 )
+{
+ Map_Node_t * pNode1 = Map_Regular(s_pMan->pOutputs[*pOut1]);
+ Map_Node_t * pNode2 = Map_Regular(s_pMan->pOutputs[*pOut2]);
+ int fPhase1 = (pNode1 == s_pMan->pOutputs[*pOut1]);
+ int fPhase2 = (pNode2 == s_pMan->pOutputs[*pOut2]);
+ float Arrival1 = pNode1->tArrival[fPhase1].Worst;
+ float Arrival2 = pNode2->tArrival[fPhase2].Worst;
+ if ( Arrival1 > Arrival2 )
+ return -1;
+ if ( Arrival1 < Arrival2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingSetupTruthTables( unsigned uTruths[][2] )
+{
+ int m, v;
+ // set up the truth tables
+ for ( m = 0; m < 32; m++ )
+ for ( v = 0; v < 5; v++ )
+ if ( m & (1 << v) )
+ uTruths[v][0] |= (1 << m);
+ // make adjustments for the case of 6 variables
+ for ( v = 0; v < 5; v++ )
+ uTruths[v][1] = uTruths[v][0];
+ uTruths[5][0] = 0;
+ uTruths[5][1] = MAP_FULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the truth tables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] )
+{
+ int m, v;
+ // clean everything
+ for ( m = 0; m < 32; m++ )
+ for ( v = 0; v < 10; v++ )
+ uTruths[v][m] = 0;
+ // set up the truth tables
+ for ( m = 0; m < 32; m++ )
+ for ( v = 0; v < 5; v++ )
+ if ( m & (1 << v) )
+ {
+ uTruths[v][0] |= (1 << m);
+ uTruths[v+5][m] = MAP_FULL;
+ }
+ // extend this info for the rest of the first 5 variables
+ for ( m = 0; m < 32; m++ )
+ for ( v = 0; v < 5; v++ )
+ uTruths[v][m] = uTruths[v][0];
+/*
+ // verify
+ for ( m = 0; m < 1024; m++, printf("\n") )
+ for ( v = 0; v < 10; v++ )
+ if ( Map_InfoReadVar( uTruths[v], m ) )
+ printf( "1" );
+ else
+ printf( "0" );
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingSetupMask( unsigned uMask[], int nVarsMax )
+{
+ if ( nVarsMax == 6 )
+ uMask[0] = uMask[1] = MAP_FULL;
+ else
+ {
+ uMask[0] = MAP_MASK(1 << nVarsMax);
+ uMask[1] = 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify one useful property.]
+
+ Description [This procedure verifies one useful property. After
+ the FRAIG construction with choice nodes is over, each primary node
+ should have fanins that are primary nodes. The primary nodes is the
+ one that does not have pNode->pRepr set to point to another node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_ManCheckConsistency( Map_Man_t * p )
+{
+ Map_Node_t * pNode;
+ Map_NodeVec_t * pVec;
+ int i;
+ pVec = Map_MappingDfs( p, 0 );
+ for ( i = 0; i < pVec->nSize; i++ )
+ {
+ pNode = pVec->pArray[i];
+ if ( Map_NodeIsVar(pNode) )
+ {
+ if ( pNode->pRepr )
+ printf( "Primary input %d is a secondary node.\n", pNode->Num );
+ }
+ else if ( Map_NodeIsConst(pNode) )
+ {
+ if ( pNode->pRepr )
+ printf( "Constant 1 %d is a secondary node.\n", pNode->Num );
+ }
+ else
+ {
+ if ( pNode->pRepr )
+ printf( "Internal node %d is a secondary node.\n", pNode->Num );
+ if ( Map_Regular(pNode->p1)->pRepr )
+ printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num );
+ if ( Map_Regular(pNode->p2)->pRepr )
+ printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num );
+ }
+ }
+ Map_NodeVecFree( pVec );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if current mapping of the node violates fanout limits.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol )
+{
+ return pNode->nRefAct[fPosPol] > (int)pCut->M[fPosPol].pSuperBest->nFanLimit;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the total are flow of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Map_MappingGetAreaFlow( Map_Man_t * p )
+{
+ Map_Node_t * pNode;
+ Map_Cut_t * pCut;
+ float aFlowFlowTotal = 0;
+ int fPosPol, i;
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ pNode = Map_Regular(p->pOutputs[i]);
+ if ( !Map_NodeIsAnd(pNode) )
+ continue;
+ fPosPol = !Map_IsComplement(p->pOutputs[i]);
+ pCut = pNode->pCutBest[fPosPol];
+ if ( pCut == NULL )
+ {
+ fPosPol = !fPosPol;
+ pCut = pNode->pCutBest[fPosPol];
+ }
+ aFlowFlowTotal += pNode->pCutBest[fPosPol]->M[fPosPol].AreaFlow;
+ }
+ return aFlowFlowTotal;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares the supergates by their level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CompareNodesByLevel( Map_Node_t ** ppS1, Map_Node_t ** ppS2 )
+{
+ Map_Node_t * pN1 = Map_Regular(*ppS1);
+ Map_Node_t * pN2 = Map_Regular(*ppS2);
+ if ( pN1->Level > pN2->Level )
+ return -1;
+ if ( pN1->Level < pN2->Level )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Orders the nodes in the decreasing order of levels.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes )
+{
+ qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Map_Node_t *),
+ (int (*)(const void *, const void *)) Map_CompareNodesByLevel );
+// assert( Map_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares the supergates by their pointer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_CompareNodesByPointer( Map_Node_t ** ppS1, Map_Node_t ** ppS2 )
+{
+ if ( *ppS1 < *ppS2 )
+ return -1;
+ if ( *ppS1 > *ppS2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts how many AIG nodes are mapped in both polarities.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes )
+{
+ Map_Node_t * pNode;
+ int Counter, i;
+ // count the number of equal adjacent nodes
+ Counter = 0;
+ for ( i = 0; i < vNodes->nSize; i++ )
+ {
+ pNode = vNodes->pArray[i];
+ if ( !Map_NodeIsAnd(pNode) )
+ continue;
+ if ( (pNode->nRefAct[0] && pNode->pCutBest[0]) &&
+ (pNode->nRefAct[1] && pNode->pCutBest[1]) )
+ Counter++;
+ }
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+st_table * Map_CreateTableGate2Super( Map_Man_t * pMan )
+{
+ Map_Super_t * pSuper;
+ st_table * tTable;
+ int i, nInputs, v;
+ tTable = st_init_table(strcmp, st_strhash);
+ for ( i = 0; i < pMan->pSuperLib->nSupersAll; i++ )
+ {
+ pSuper = pMan->pSuperLib->ppSupers[i];
+ if ( pSuper->nGates == 1 )
+ {
+ // skip different versions of the same root gate
+ nInputs = Mio_GateReadInputs(pSuper->pRoot);
+ for ( v = 0; v < nInputs; v++ )
+ if ( pSuper->pFanins[v]->Num != nInputs - 1 - v )
+ break;
+ if ( v != nInputs )
+ continue;
+// printf( "%s\n", Mio_GateReadName(pSuper->pRoot) );
+ if ( st_insert( tTable, (char *)pSuper->pRoot, (char *)pSuper ) )
+ {
+ assert( 0 );
+ }
+ }
+ }
+ return tTable;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Get the FRAIG node with phase.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_ManCleanData( Map_Man_t * p )
+{
+ int i;
+ for ( i = 0; i < p->vNodesAll->nSize; i++ )
+ p->vNodesAll->pArray[i]->pData0 = p->vNodesAll->pArray[i]->pData1 = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Expand the truth table]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingExpandTruth( unsigned uTruth[2], int nVars )
+{
+ assert( nVars < 7 );
+ if ( nVars == 6 )
+ return;
+ if ( nVars < 5 )
+ {
+ uTruth[0] &= MAP_MASK( (1<<nVars) );
+ uTruth[0] = Map_MappingExpandTruth_rec( uTruth[0], nVars );
+ }
+ uTruth[1] = uTruth[0];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Expand the truth table]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Map_MappingExpandTruth_rec( unsigned uTruth, int nVars )
+{
+ assert( nVars < 6 );
+ if ( nVars == 5 )
+ return uTruth;
+ return Map_MappingExpandTruth_rec( uTruth | (uTruth << (1 << nVars)), nVars + 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Map_MappingComputeDelayWithFanouts( Map_Man_t * p )
+{
+ Map_Node_t * pNode;
+ float Result;
+ int i;
+ for ( i = 0; i < p->vAnds->nSize; i++ )
+ {
+ // skip primary inputs
+ pNode = p->vAnds->pArray[i];
+ if ( !Map_NodeIsAnd( pNode ) )
+ continue;
+ // skip a secondary node
+ if ( pNode->pRepr )
+ continue;
+ // count the switching nodes
+ if ( pNode->nRefAct[0] > 0 )
+ Map_TimeCutComputeArrival( pNode, pNode->pCutBest[0], 0, MAP_FLOAT_LARGE );
+ if ( pNode->nRefAct[1] > 0 )
+ Map_TimeCutComputeArrival( pNode, pNode->pCutBest[1], 1, MAP_FLOAT_LARGE );
+ }
+ Result = Map_TimeComputeArrivalMax(p);
+ printf( "Max arrival times with fanouts = %10.2f.\n", Result );
+ return Result;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingGetMaxLevel( Map_Man_t * pMan )
+{
+ int nLevelMax, i;
+ nLevelMax = 0;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ nLevelMax = ((unsigned)nLevelMax) > Map_Regular(pMan->pOutputs[i])->Level?
+ nLevelMax : Map_Regular(pMan->pOutputs[i])->Level;
+ return nLevelMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Analyses choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingUpdateLevel_rec( Map_Man_t * pMan, Map_Node_t * pNode, int fMaximum )
+{
+ Map_Node_t * pTemp;
+ int Level1, Level2, LevelE;
+ assert( !Map_IsComplement(pNode) );
+ if ( !Map_NodeIsAnd(pNode) )
+ return pNode->Level;
+ // skip the visited node
+ if ( pNode->TravId == pMan->nTravIds )
+ return pNode->Level;
+ pNode->TravId = pMan->nTravIds;
+ // compute levels of the children nodes
+ Level1 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p1), fMaximum );
+ Level2 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p2), fMaximum );
+ pNode->Level = 1 + MAP_MAX( Level1, Level2 );
+ if ( pNode->pNextE )
+ {
+ LevelE = Map_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum );
+ if ( fMaximum )
+ {
+ if ( pNode->Level < (unsigned)LevelE )
+ pNode->Level = LevelE;
+ }
+ else
+ {
+ if ( pNode->Level > (unsigned)LevelE )
+ pNode->Level = LevelE;
+ }
+ // set the level of all equivalent nodes to be the same minimum
+ if ( pNode->pRepr == NULL ) // the primary node
+ for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+ pTemp->Level = pNode->Level;
+ }
+ return pNode->Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resets the levels of the nodes in the choice graph.]
+
+ Description [Makes the level of the choice nodes to be equal to the
+ maximum of the level of the nodes in the equivalence class. This way
+ sorting by level leads to the reverse topological order, which is
+ needed for the required time computation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingSetChoiceLevels( Map_Man_t * pMan )
+{
+ int i;
+ pMan->nTravIds++;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports statistics on choice nodes.]
+
+ Description [The number of choice nodes is the number of primary nodes,
+ which has pNextE set to a pointer. The number of choices is the number
+ of entries in the equivalent-node lists of the primary nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingReportChoices( Map_Man_t * pMan )
+{
+ Map_Node_t * pNode, * pTemp;
+ int nChoiceNodes, nChoices;
+ int i, LevelMax1, LevelMax2;
+
+ // report the number of levels
+ LevelMax1 = Map_MappingGetMaxLevel( pMan );
+ pMan->nTravIds++;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 );
+ LevelMax2 = Map_MappingGetMaxLevel( pMan );
+
+ // report statistics about choices
+ nChoiceNodes = nChoices = 0;
+ for ( i = 0; i < pMan->vAnds->nSize; i++ )
+ {
+ pNode = pMan->vAnds->pArray[i];
+ if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
+ { // this is a choice node = the primary node that has equivalent nodes
+ nChoiceNodes++;
+ for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
+ nChoices++;
+ }
+ }
+ printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
+ printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
+}
+
+/*
+void Map_MappingReportChoices( Map_Man_t * pMan )
+{
+ Map_Node_t * pNode, * pTemp;
+ int nChoiceNodes, nChoices;
+ int i, LevelMax1, LevelMax2;
+ int DiffMaxTotal, DiffMinTotal, Min, Max;
+ int CounterByMin[300]={0}, CounterByMax[300]={0};
+
+ // report the number of levels
+ LevelMax1 = Map_MappingGetMaxLevel( pMan );
+ pMan->nTravIds++;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+// Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 );
+ Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 );
+ LevelMax2 = Map_MappingGetMaxLevel( pMan );
+
+ // report statistics about choices
+ nChoiceNodes = nChoices = 0;
+ DiffMaxTotal = DiffMinTotal = 0;
+ for ( i = 0; i < pMan->vAnds->nSize; i++ )
+ {
+ pNode = pMan->vAnds->pArray[i];
+ if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
+ { // this is a choice node = the primary node that has equivalent nodes
+ nChoiceNodes++;
+ for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
+ nChoices++;
+ // call to compare the levels
+ Map_MappingGetChoiceLevels( pMan, pNode, pNode->pNextE, &Min, &Max );
+ assert( Min < (int)pNode->Level );
+ assert( Max < (int)pNode->Level );
+ DiffMinTotal += pNode->Level - Max;
+ DiffMaxTotal += pNode->Level - Min;
+
+ CounterByMin[pNode->Level - Max]++;
+ CounterByMax[pNode->Level - Min]++;
+
+ }
+ }
+ printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
+ printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
+ printf( "Choice depth: Minimum = %4.2f. Maximum = %4.2f.\n",
+ ((float)DiffMinTotal)/nChoiceNodes, ((float)DiffMaxTotal)/nChoiceNodes );
+
+ {
+ FILE * pTable;
+ pTable = fopen( "statsc.txt", "a+" );
+ fprintf( pTable, "%6d ", pMan->vAnds->nSize );
+ fprintf( pTable, "%5d ", LevelMax2 );
+ fprintf( pTable, "%5d ", nChoiceNodes );
+ fprintf( pTable, "%5d ", nChoices );
+ fprintf( pTable, "%5.2f ", ((float)DiffMinTotal)/nChoiceNodes );
+ fprintf( pTable, "%5.2f ", ((float)DiffMaxTotal)/nChoiceNodes );
+// fprintf( pTable, "%4.2f\n", (float)(Time)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+
+
+ printf( "Distribution by min/max levels:\n" );
+ for ( i = 0; i < LevelMax2; i++ )
+ printf( "%3d : %5d %5d\n", i, CounterByMin[i], CounterByMax[i] );
+ printf( "\n" );
+}
+*/
+
+/*
+void Map_MappingReportChoices( Map_Man_t * pMan )
+{
+ Map_Node_t * pNode, * pTemp;
+ int nChoiceNodes, nChoices;
+ int i, LevelMax1, LevelMax2;
+ int CounterByVol[1000]={0};
+ float VolumeAve, Volume;
+
+ // report the number of levels
+ LevelMax1 = Map_MappingGetMaxLevel( pMan );
+ pMan->nTravIds++;
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 );
+// Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 );
+ LevelMax2 = Map_MappingGetMaxLevel( pMan );
+
+ // report statistics about choices
+ nChoiceNodes = nChoices = 0;
+ VolumeAve = 0.0;
+ for ( i = 0; i < pMan->vAnds->nSize; i++ )
+ {
+ pNode = pMan->vAnds->pArray[i];
+ if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
+ { // this is a choice node = the primary node that has equivalent nodes
+ nChoiceNodes++;
+ for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
+ nChoices++;
+ Volume = Map_MappingGetChoiceVolumes( pMan, pNode, pNode->pNextE );
+ VolumeAve += Volume;
+ assert( Volume < 1000 );
+ CounterByVol[(int)Volume]++;
+ }
+ }
+ printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
+ printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
+ printf( "Average volume = %5.4f.\n", VolumeAve/nChoiceNodes );
+*/
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "statsv.txt", "a+" );
+ fprintf( pTable, "%6d ", Map_MappingCountUsedNodes(pMan,1) );
+ fprintf( pTable, "%6d ", Map_MappingCountUsedNodes(pMan,0) );
+ fprintf( pTable, "%5d ", LevelMax1 );
+ fprintf( pTable, " " );
+ fprintf( pTable, "%5d ", nChoiceNodes );
+ fprintf( pTable, "%5d ", nChoices );
+ fprintf( pTable, " " );
+ fprintf( pTable, "%5.4f ", VolumeAve/nChoiceNodes );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+ printf( "Distribution by volume:\n" );
+ for ( i = 0; i < 1000; i++ )
+ if ( CounterByVol[i] > 0 )
+ printf( "%3d : %5d\n", i, CounterByVol[i] );
+ printf( "\n" );
+*/
+/*
+}
+*/
+
+/**Function*************************************************************
+
+ Synopsis [Computes the maximum and minimum levels of the choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_MappingGetChoiceLevels( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2, int * pMin, int * pMax )
+{
+ Map_NodeVec_t * vNodes;
+ Map_NodeVec_t * vBoundary;
+ Map_Node_t * pNode;
+ int i, Min, Max;
+
+ vNodes = Map_NodeVecAlloc( 100 );
+ vBoundary = Map_NodeVecAlloc( 100 );
+ Map_MappingDfsMarked1_rec( p1, vNodes, 1 );
+ Map_MappingDfsMarked2_rec( p2, vNodes, vBoundary, 1 );
+ // clean the marks
+ Min = 100000;
+ Max = -100000;
+ for ( i = 0; i < vBoundary->nSize; i++ )
+ {
+ pNode = vBoundary->pArray[i];
+ if ( Min > (int)pNode->Level )
+ Min = pNode->Level;
+ if ( Max < (int)pNode->Level )
+ Max = pNode->Level;
+ }
+ Map_NodeVecFree( vBoundary );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ {
+ pNode = vNodes->pArray[i];
+ pNode->fMark0 = pNode->fMark1 = 0;
+ }
+ Map_NodeVecFree( vNodes );
+ *pMin = Min;
+ *pMax = Max;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Map_MappingGetChoiceVolumes( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 )
+{
+ Map_NodeVec_t * vNodes;
+ Map_Node_t * pNode;
+ int i, nVolumeTotal, nVolumeUnique;
+
+ vNodes = Map_NodeVecAlloc( 100 );
+ Map_MappingDfsMarked3_rec( p1, vNodes );
+ Map_MappingDfsMarked4_rec( p2, vNodes );
+ // clean the marks
+ nVolumeTotal = nVolumeUnique = 0;
+ for ( i = 0; i < vNodes->nSize; i++ )
+ {
+ pNode = vNodes->pArray[i];
+ if ( !Map_NodeIsAnd(pNode) )
+ continue;
+ nVolumeTotal++;
+ if ( pNode->fMark0 ^ pNode->fMark1 )
+ nVolumeUnique++;
+ pNode->fMark0 = pNode->fMark1 = 0;
+ }
+ Map_NodeVecFree( vNodes );
+// return ((float)nVolumeUnique)/nVolumeTotal;
+ return (float)nVolumeUnique;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the maximum and minimum levels of the choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices )
+{
+ Map_NodeVec_t * vNodes;
+ int Result;
+ vNodes = Map_MappingDfs( pMan, fChoices );
+ Result = vNodes->nSize;
+ Map_NodeVecFree( vNodes );
+ return Result;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mapper/mapperVec.c b/src/map/mapper/mapperVec.c
new file mode 100644
index 00000000..e3ab4b7f
--- /dev/null
+++ b/src/map/mapper/mapperVec.c
@@ -0,0 +1,318 @@
+/**CFile****************************************************************
+
+ FileName [mapperVec.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Generic technology mapping engine.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - June 1, 2004.]
+
+ Revision [$Id: mapperVec.c,v 1.3 2005/01/23 06:59:45 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mapperInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_NodeVec_t * Map_NodeVecAlloc( int nCap )
+{
+ Map_NodeVec_t * p;
+ p = ALLOC( Map_NodeVec_t, 1 );
+ if ( nCap > 0 && nCap < 16 )
+ nCap = 16;
+ p->nSize = 0;
+ p->nCap = nCap;
+ p->pArray = p->nCap? ALLOC( Map_Node_t *, p->nCap ) : NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeVecFree( Map_NodeVec_t * p )
+{
+ FREE( p->pArray );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p )
+{
+ return p->pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_NodeVecReadSize( Map_NodeVec_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the vector to the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin )
+{
+ if ( p->nCap >= nCapMin )
+ return;
+ p->pArray = REALLOC( Map_Node_t *, p->pArray, nCapMin );
+ p->nCap = nCapMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew )
+{
+ assert( p->nSize >= nSizeNew );
+ p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeVecClear( Map_NodeVec_t * p )
+{
+ p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry )
+{
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Map_NodeVecGrow( p, 16 );
+ else
+ Map_NodeVecGrow( p, 2 * p->nCap );
+ }
+ p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the element while ensuring uniqueness.]
+
+ Description [Returns 1 if the element was found, and 0 if it was new. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return 1;
+ Map_NodeVecPush( p, Entry );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p )
+{
+ return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ break;
+ assert( i < p->nSize );
+ for ( i++; i < p->nSize; i++ )
+ p->pArray[i-1] = p->pArray[i];
+ p->nSize--;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Map_NodeVecSortByLevel( Map_NodeVec_t * p )
+{
+ qsort( (void *)p->pArray, p->nSize, sizeof(Map_Node_t *),
+ (int (*)(const void *, const void *)) Map_NodeVecCompareLevels );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 )
+{
+ int Level1 = Map_Regular(*pp1)->Level;
+ int Level2 = Map_Regular(*pp2)->Level;
+ if ( Level1 < Level2 )
+ return -1;
+ if ( Level1 > Level2 )
+ return 1;
+ if ( Map_Regular(*pp1)->Num < Map_Regular(*pp2)->Num )
+ return -1;
+ if ( Map_Regular(*pp1)->Num > Map_Regular(*pp2)->Num )
+ return 1;
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/mapper/module.make b/src/map/mapper/module.make
new file mode 100644
index 00000000..1d3b8867
--- /dev/null
+++ b/src/map/mapper/module.make
@@ -0,0 +1,17 @@
+SRC += src/map/mapper/mapper.c \
+ src/map/mapper/mapperCanon.c \
+ src/map/mapper/mapperCore.c \
+ src/map/mapper/mapperCreate.c \
+ src/map/mapper/mapperCut.c \
+ src/map/mapper/mapperCutUtils.c \
+ src/map/mapper/mapperFanout.c \
+ src/map/mapper/mapperLib.c \
+ src/map/mapper/mapperMatch.c \
+ src/map/mapper/mapperRefs.c \
+ src/map/mapper/mapperSuper.c \
+ src/map/mapper/mapperTable.c \
+ src/map/mapper/mapperTime.c \
+ src/map/mapper/mapperTree.c \
+ src/map/mapper/mapperTruth.c \
+ src/map/mapper/mapperUtils.c \
+ src/map/mapper/mapperVec.c
diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c
new file mode 100644
index 00000000..a01aeaa9
--- /dev/null
+++ b/src/map/mio/mio.c
@@ -0,0 +1,269 @@
+/**CFile****************************************************************
+
+ FileName [mio.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [File reading/writing for technology mapping.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 18, 2003.]
+
+ Revision [$Id: mio.c,v 1.4 2004/08/05 18:34:51 satrajit Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "mvc.h"
+#include "mainInt.h"
+#include "mioInt.h"
+#include "mapper.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv );
+
+// internal version of GENLIB library
+static char * pMcncGenlib[25] = {
+ "GATE inv1 1 O=!a; PIN * INV 1 999 0.9 0.0 0.9 0.0\n",
+ "GATE inv2 2 O=!a; PIN * INV 2 999 1.0 0.0 1.0 0.0\n",
+ "GATE inv3 3 O=!a; PIN * INV 3 999 1.1 0.0 1.1 0.0\n",
+ "GATE inv4 4 O=!a; PIN * INV 4 999 1.2 0.0 1.2 0.0\n",
+ "GATE nand2 2 O=!(a*b); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
+ "GATE nand3 3 O=!(a*b*c); PIN * INV 1 999 1.1 0.0 1.1 0.0\n",
+ "GATE nand4 4 O=!(a*b*c*d); PIN * INV 1 999 1.4 0.0 1.4 0.0\n",
+ "GATE nor2 2 O=!(a+b); PIN * INV 1 999 1.4 0.0 1.4 0.0\n",
+ "GATE nor3 3 O=!(a+b+c); PIN * INV 1 999 2.4 0.0 2.4 0.0\n",
+ "GATE nor4 4 O=!(a+b+c+d); PIN * INV 1 999 3.8 0.0 3.8 0.0\n",
+ "GATE xora 5 O=a*!b+!a*b; PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n",
+ "GATE xorb 5 O=!(a*b+!a*!b); PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n",
+ "GATE xnora 5 O=a*b+!a*!b; PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n",
+ "GATE xnorb 5 O=!(!a*b+a*!b); PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n",
+ "GATE aoi21 3 O=!(a*b+c); PIN * INV 1 999 1.6 0.0 1.6 0.0\n",
+ "GATE aoi22 4 O=!(a*b+c*d); PIN * INV 1 999 2.0 0.0 2.0 0.0\n",
+ "GATE oai21 3 O=!((a+b)*c); PIN * INV 1 999 1.6 0.0 1.6 0.0\n",
+ "GATE oai22 4 O=!((a+b)*(c+d)); PIN * INV 1 999 2.0 0.0 2.0 0.0\n",
+ "GATE buf 1 O=a; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
+ "GATE zero 0 O=CONST0;\n",
+ "GATE one 0 O=CONST1;\n"
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_Init( Abc_Frame_t * pAbc )
+{
+ char * pFileTemp = "mcnc_temp.genlib";
+ Mio_Library_t * pLibGen;
+ FILE * pFile;
+ int i;
+
+ // write genlib into file
+ pFile = fopen( pFileTemp, "w" );
+ for ( i = 0; pMcncGenlib[i]; i++ )
+ fputs( pMcncGenlib[i], pFile );
+ fclose( pFile );
+ // read genlib from file
+ pLibGen = Mio_LibraryRead( pAbc, pFileTemp, NULL, 0 );
+ Abc_FrameSetLibGen( pAbc, pLibGen );
+#ifdef WIN32
+ _unlink( pFileTemp );
+#else
+ unlink( pFileTemp );
+#endif
+
+ Cmd_CommandAdd( pAbc, "SC mapping", "read_library", Mio_CommandReadLibrary, 0 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "print_library", Mio_CommandPrintLibrary, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_End()
+{
+// Mio_LibraryDelete( s_pLib );
+ Mio_LibraryDelete( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pFile;
+ FILE * pOut, * pErr;
+ Mio_Library_t * pLib;
+ Abc_Ntk_t * pNet;
+ char * FileName;
+ int fVerbose;
+ int c;
+
+ pNet = Abc_FrameReadNet(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fVerbose = 1;
+ util_getopt_reset();
+ while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+
+ if ( argc != util_optind + 1 )
+ {
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[util_optind];
+ if ( (pFile = fopen( FileName, "r" )) == NULL )
+ {
+ fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+ if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
+ fprintf( pErr, "Did you mean \"%s\"?", FileName );
+ fprintf( pErr, "\n" );
+ return 1;
+ }
+ fclose( pFile );
+
+ // set the new network
+ pLib = Mio_LibraryRead( pAbc, FileName, 0, fVerbose );
+ if ( pLib == NULL )
+ {
+ fprintf( pErr, "Reading GENLIB library has failed.\n" );
+ return 1;
+ }
+ // free the current superlib because it depends on the old Mio library
+ if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) )
+ {
+ extern void Map_SuperLibFree( Map_SuperLib_t * p );
+// Map_SuperLibFree( s_pSuperLib );
+// s_pSuperLib = NULL;
+ Map_SuperLibFree( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) );
+ Abc_FrameSetLibSuper(Abc_FrameGetGlobalFrame(), NULL);
+ }
+
+ // replace the current library
+// Mio_LibraryDelete( s_pLib );
+// s_pLib = pLib;
+ Mio_LibraryDelete( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
+ Abc_FrameSetLibGen( Abc_FrameGetGlobalFrame(), pLib );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: read_library [-vh]\n");
+ fprintf( pErr, "\t read the library from a genlib file\n" );
+ fprintf( pErr, "\t-h : enable verbose output\n");
+ return 1; /* error exit */
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Command procedure to read LUT libraries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNet;
+ int fVerbose;
+ int c;
+
+ pNet = Abc_FrameReadNet(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fVerbose = 1;
+ util_getopt_reset();
+ while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+
+ if ( argc != util_optind )
+ {
+ goto usage;
+ }
+
+ // set the new network
+ Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()), 0 );
+ return 0;
+
+usage:
+ fprintf( pErr, "\nusage: print_library [-vh]\n");
+ fprintf( pErr, "\t print the current genlib library\n" );
+ fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1; /* error exit */
+}
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h
new file mode 100644
index 00000000..3347bba8
--- /dev/null
+++ b/src/map/mio/mio.h
@@ -0,0 +1,136 @@
+/**CFile****************************************************************
+
+ FileName [mio.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [File reading/writing for technology mapping.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: mio.h,v 1.6 2004/08/09 22:16:31 satrajit Exp $]
+
+***********************************************************************/
+
+#ifndef __MIO_H__
+#define __MIO_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef enum { MIO_PHASE_UNKNOWN, MIO_PHASE_INV, MIO_PHASE_NONINV } Mio_PinPhase_t;
+
+typedef struct Mio_LibraryStruct_t_ Mio_Library_t;
+typedef struct Mio_GateStruct_t_ Mio_Gate_t;
+typedef struct Mio_PinStruct_t_ Mio_Pin_t;
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Mio_LibraryForEachGate( Lib, Gate ) \
+ for ( Gate = Mio_LibraryReadGates(Lib); \
+ Gate; \
+ Gate = Mio_GateReadNext(Gate) )
+#define Mio_LibraryForEachGateSafe( Lib, Gate, Gate2 ) \
+ for ( Gate = Mio_LibraryReadGates(Lib), \
+ Gate2 = (Gate? Mio_GateReadNext(Gate): NULL); \
+ Gate; \
+ Gate = Gate2, \
+ Gate2 = (Gate? Mio_GateReadNext(Gate): NULL) )
+
+#define Mio_GateForEachPin( Gate, Pin ) \
+ for ( Pin = Mio_GateReadPins(Gate); \
+ Pin; \
+ Pin = Mio_PinReadNext(Pin) )
+#define Mio_GateForEachPinSafe( Gate, Pin, Pin2 ) \
+ for ( Pin = Mio_GateReadPins(Gate), \
+ Pin2 = (Pin? Mio_PinReadNext(Pin): NULL); \
+ Pin; \
+ Pin = Pin2, \
+ Pin2 = (Pin? Mio_PinReadNext(Pin): NULL) )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mioApi.c =============================================================*/
+extern char * Mio_LibraryReadName ( Mio_Library_t * pLib );
+extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib );
+extern Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib );
+extern DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib );
+extern Mio_Gate_t * Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName );
+extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char * pName );
+extern Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib );
+extern Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib );
+extern Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib );
+extern Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib );
+extern Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib );
+extern float Mio_LibraryReadDelayInvRise( Mio_Library_t * pLib );
+extern float Mio_LibraryReadDelayInvFall( Mio_Library_t * pLib );
+extern float Mio_LibraryReadDelayInvMax( Mio_Library_t * pLib );
+extern float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib );
+extern float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib );
+extern float Mio_LibraryReadDelayNand2Max( Mio_Library_t * pLib );
+extern float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib );
+extern float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib );
+extern char * Mio_GateReadName ( Mio_Gate_t * pGate );
+extern char * Mio_GateReadOutName ( Mio_Gate_t * pGate );
+extern double Mio_GateReadArea ( Mio_Gate_t * pGate );
+extern char * Mio_GateReadForm ( Mio_Gate_t * pGate );
+extern Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate );
+extern Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate );
+extern Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate );
+extern int Mio_GateReadInputs ( Mio_Gate_t * pGate );
+extern double Mio_GateReadDelayMax ( Mio_Gate_t * pGate );
+extern char * Mio_GateReadSop ( Mio_Gate_t * pGate );
+extern DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate );
+extern char * Mio_PinReadName ( Mio_Pin_t * pPin );
+extern Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin );
+extern double Mio_PinReadInputLoad ( Mio_Pin_t * pPin );
+extern double Mio_PinReadMaxLoad ( Mio_Pin_t * pPin );
+extern double Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin );
+extern double Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin );
+extern double Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin );
+extern double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin );
+extern double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin );
+extern Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin );
+/*=== mioRead.c =============================================================*/
+extern Mio_Library_t * Mio_LibraryRead( Abc_Frame_t * pAbc, char * FileName, char * ExcludeFile, int fVerbose );
+extern int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * tExcludeGate );
+/*=== mioFunc.c =============================================================*/
+extern int Mio_LibraryParseFormulas( Mio_Library_t * pLib );
+/*=== mioUtils.c =============================================================*/
+extern void Mio_LibraryDelete( Mio_Library_t * pLib );
+extern void Mio_GateDelete( Mio_Gate_t * pGate );
+extern void Mio_PinDelete( Mio_Pin_t * pPin );
+extern Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin );
+extern void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops );
+extern Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, bool fSkipInv, int * pnGates );
+extern void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] );
+extern void Mio_DeriveGateDelays( Mio_Gate_t * pGate,
+ float ** ptPinDelays, int nPins, int nInputs, float tDelayZero,
+ float * ptDelaysRes, float * ptPinDelayMax );
+extern Mio_Gate_t * Mio_GateCreatePseudo( int nInputs );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/src/map/mio/mioApi.c b/src/map/mio/mioApi.c
new file mode 100644
index 00000000..50d60fe9
--- /dev/null
+++ b/src/map/mio/mioApi.c
@@ -0,0 +1,145 @@
+/**CFile****************************************************************
+
+ FileName [mioApi.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [File reading/writing for technology mapping.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: mioApi.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Mio_LibraryReadName ( Mio_Library_t * pLib ) { return pLib->pName; }
+int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ) { return pLib->nGates; }
+Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { return pLib->pGates; }
+DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ) { return pLib->dd; }
+Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ) { return pLib->pGateBuf; }
+Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ) { return pLib->pGateInv; }
+Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ) { return pLib->pGate0; }
+Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ) { return pLib->pGate1; }
+Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib ) { return pLib->pGateNand2; }
+float Mio_LibraryReadDelayInvRise ( Mio_Library_t * pLib ) { return (float)pLib->pGateInv->pPins->dDelayBlockRise; }
+float Mio_LibraryReadDelayInvFall ( Mio_Library_t * pLib ) { return (float)pLib->pGateInv->pPins->dDelayBlockFall; }
+float Mio_LibraryReadDelayInvMax ( Mio_Library_t * pLib ) { return (float)pLib->pGateInv->pPins->dDelayBlockMax; }
+float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ) { return (float)pLib->pGateNand2->pPins->dDelayBlockRise; }
+float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ) { return (float)pLib->pGateNand2->pPins->dDelayBlockFall; }
+float Mio_LibraryReadDelayNand2Max ( Mio_Library_t * pLib ) { return (float)pLib->pGateNand2->pPins->dDelayBlockMax; }
+float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ) { return (float)pLib->pGateInv->dArea; }
+float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ) { return (float)pLib->pGateNand2->dArea; }
+
+/**Function*************************************************************
+
+ Synopsis [Read Mvc of the gate by name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Gate_t * Mio_LibraryReadGateByName( Mio_Library_t * pLib, char * pName )
+{
+ Mio_Gate_t * pGate;
+ if ( st_lookup( pLib->tName2Gate, pName, (char **)&pGate ) )
+ return pGate;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Read Mvc of the gate by name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Mio_LibraryReadSopByName( Mio_Library_t * pLib, char * pName )
+{
+ Mio_Gate_t * pGate;
+ if ( st_lookup( pLib->tName2Gate, pName, (char **)&pGate ) )
+ return pGate->pSop;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Mio_GateReadName ( Mio_Gate_t * pGate ) { return pGate->pName; }
+char * Mio_GateReadOutName ( Mio_Gate_t * pGate ) { return pGate->pOutName; }
+double Mio_GateReadArea ( Mio_Gate_t * pGate ) { return pGate->dArea; }
+char * Mio_GateReadForm ( Mio_Gate_t * pGate ) { return pGate->pForm; }
+Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ) { return pGate->pPins; }
+Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ) { return pGate->pLib; }
+Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ) { return pGate->pNext; }
+int Mio_GateReadInputs ( Mio_Gate_t * pGate ) { return pGate->nInputs; }
+double Mio_GateReadDelayMax( Mio_Gate_t * pGate ) { return pGate->dDelayMax; }
+char * Mio_GateReadSop ( Mio_Gate_t * pGate ) { return pGate->pSop; }
+DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ) { return pGate->bFunc; }
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Mio_PinReadName ( Mio_Pin_t * pPin ) { return pPin->pName; }
+Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin ) { return pPin->Phase; }
+double Mio_PinReadInputLoad ( Mio_Pin_t * pPin ) { return pPin->dLoadInput; }
+double Mio_PinReadMaxLoad ( Mio_Pin_t * pPin ) { return pPin->dLoadMax; }
+double Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockRise; }
+double Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin ) { return pPin->dDelayFanoutRise;}
+double Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockFall; }
+double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin ) { return pPin->dDelayFanoutFall;}
+double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockMax; }
+Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin ) { return pPin->pNext; }
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mio/mioFunc.c b/src/map/mio/mioFunc.c
new file mode 100644
index 00000000..88a7c89c
--- /dev/null
+++ b/src/map/mio/mioFunc.c
@@ -0,0 +1,268 @@
+/**CFile****************************************************************
+
+ FileName [mioFunc.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [File reading/writing for technology mapping.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: mioFunc.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+#include "parse.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// these symbols (and no other) can appear in the formulas
+#define MIO_SYMB_AND '*'
+#define MIO_SYMB_OR '+'
+#define MIO_SYMB_NOT '!'
+#define MIO_SYMB_AFTNOT '\''
+#define MIO_SYMB_OPEN '('
+#define MIO_SYMB_CLOSE ')'
+
+static int Mio_GateParseFormula( Mio_Gate_t * pGate );
+static int Mio_GateCollectNames( char * pFormula, char * pPinNames[] );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Deriving the functionality of the gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_LibraryParseFormulas( Mio_Library_t * pLib )
+{
+ Mio_Gate_t * pGate;
+
+ // count the gates
+ pLib->nGates = 0;
+ Mio_LibraryForEachGate( pLib, pGate )
+ pLib->nGates++;
+
+ // start a temporary BDD manager
+ pLib->dd = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ // introduce ZDD variables
+ Cudd_zddVarsFromBddVars( pLib->dd, 2 );
+
+ // for each gate, derive its function
+ Mio_LibraryForEachGate( pLib, pGate )
+ if ( Mio_GateParseFormula( pGate ) )
+ return 1;
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Deriving the functionality of the gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_GateParseFormula( Mio_Gate_t * pGate )
+{
+ DdManager * dd = pGate->pLib->dd;
+ char * pPinNames[100];
+ char * pPinNamesCopy[100];
+ Mio_Pin_t * pPin, ** ppPin;
+ int nPins, iPin, i;
+
+ // set the maximum delay of the gate; count pins
+ pGate->dDelayMax = 0.0;
+ nPins = 0;
+ Mio_GateForEachPin( pGate, pPin )
+ {
+ // set the maximum delay of the gate
+ if ( pGate->dDelayMax < pPin->dDelayBlockMax )
+ pGate->dDelayMax = pPin->dDelayBlockMax;
+ // count the pin
+ nPins++;
+ }
+
+ // check for the gate with const function
+ if ( nPins == 0 )
+ {
+ if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 )
+ {
+ pGate->bFunc = b0;
+ pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 0\n" );
+ pGate->pLib->pGate0 = pGate;
+ }
+ else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 )
+ {
+ pGate->bFunc = b1;
+ pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 1\n" );
+ pGate->pLib->pGate1 = pGate;
+ }
+ else
+ {
+ printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName );
+ return 1;
+ }
+ Cudd_Ref( pGate->bFunc );
+ return 0;
+ }
+
+ // collect the names as they appear in the formula
+ nPins = Mio_GateCollectNames( pGate->pForm, pPinNames );
+ if ( nPins == 0 )
+ {
+ printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName );
+ return 1;
+ }
+
+ // set the number of inputs
+ pGate->nInputs = nPins;
+
+ // consider the case when all the pins have identical pin info
+ if ( strcmp( pGate->pPins->pName, "*" ) == 0 )
+ {
+ // get the topmost (generic) pin
+ pPin = pGate->pPins;
+ FREE( pPin->pName );
+
+ // create individual pins from the generic pin
+ ppPin = &pPin->pNext;
+ for ( i = 1; i < nPins; i++ )
+ {
+ // get the new pin
+ *ppPin = Mio_PinDup( pPin );
+ // set its name
+ (*ppPin)->pName = pPinNames[i];
+ // prepare the next place in the list
+ ppPin = &((*ppPin)->pNext);
+ }
+ *ppPin = NULL;
+
+ // set the name of the topmost pin
+ pPin->pName = pPinNames[0];
+ }
+ else
+ {
+ // reorder the variable names to appear the save way as the pins
+ iPin = 0;
+ Mio_GateForEachPin( pGate, pPin )
+ {
+ // find the pin with the name pPin->pName
+ for ( i = 0; i < nPins; i++ )
+ {
+ if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 )
+ {
+ // free pPinNames[i] because it is already available as pPin->pName
+ // setting pPinNames[i] to NULL is useful to make sure that
+ // this name is not assigned to two pins in the list
+ FREE( pPinNames[i] );
+ pPinNamesCopy[iPin++] = pPin->pName;
+ break;
+ }
+ if ( i == nPins )
+ {
+ printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n",
+ pPin->pName, pGate->pForm, pGate->pName );
+ return 1;
+ }
+ }
+ }
+
+ // check for the remaining names
+ for ( i = 0; i < nPins; i++ )
+ if ( pPinNames[i] )
+ {
+ printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n",
+ pPinNames[i], pGate->pForm, pGate->pName );
+ return 1;
+ }
+
+ // copy the names back
+ memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) );
+ }
+
+ // expand the manager if necessary
+ if ( dd->size < nPins )
+ {
+ Cudd_Quit( dd );
+ dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_zddVarsFromBddVars( dd, 2 );
+ }
+
+ // derive the formula as the BDD
+ pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars );
+ Cudd_Ref( pGate->bFunc );
+
+ // derive the cover (SOP)
+ pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, nPins, pGate->pLib->vCube, -1 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect the pin names in the formula.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_GateCollectNames( char * pFormula, char * pPinNames[] )
+{
+ char Buffer[1000];
+ char * pTemp;
+ int nPins, i;
+
+ // save the formula as it was
+ strcpy( Buffer, pFormula );
+
+ // remove the non-name symbols
+ for ( pTemp = Buffer; *pTemp; pTemp++ )
+ if ( *pTemp == MIO_SYMB_AND || *pTemp == MIO_SYMB_OR || *pTemp == MIO_SYMB_NOT
+ || *pTemp == MIO_SYMB_OPEN || *pTemp == MIO_SYMB_CLOSE || *pTemp == MIO_SYMB_AFTNOT )
+ *pTemp = ' ';
+
+ // save the names
+ nPins = 0;
+ pTemp = strtok( Buffer, " " );
+ while ( pTemp )
+ {
+ for ( i = 0; i < nPins; i++ )
+ if ( strcmp( pTemp, pPinNames[i] ) == 0 )
+ break;
+ if ( i == nPins )
+ { // cannot find this name; save it
+ pPinNames[nPins++] = util_strsav(pTemp);
+ }
+ // get the next name
+ pTemp = strtok( NULL, " " );
+ }
+ return nPins;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mio/mioGENERIC.c b/src/map/mio/mioGENERIC.c
new file mode 100644
index 00000000..6a40bc52
--- /dev/null
+++ b/src/map/mio/mioGENERIC.c
@@ -0,0 +1,46 @@
+/**CFile****************************************************************
+
+ FileName [mio___.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [File reading/writing for technology mapping.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: mio___.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mio/mioInt.h b/src/map/mio/mioInt.h
new file mode 100644
index 00000000..105e3d8d
--- /dev/null
+++ b/src/map/mio/mioInt.h
@@ -0,0 +1,124 @@
+/**CFile****************************************************************
+
+ FileName [mioInt.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [File reading/writing for technology mapping.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: mioInt.h,v 1.4 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __MIO_INT_H__
+#define __MIO_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abc.h"
+#include "mvc.h"
+#include "main.h"
+#include "mio.h"
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+#define MIO_STRING_GATE "GATE"
+#define MIO_STRING_PIN "PIN"
+#define MIO_STRING_NONINV "NONINV"
+#define MIO_STRING_INV "INV"
+#define MIO_STRING_UNKNOWN "UNKNOWN"
+
+#define MIO_STRING_CONST0 "CONST0"
+#define MIO_STRING_CONST1 "CONST1"
+
+// the bit masks
+#define MIO_MASK(n) ((~((unsigned)0)) >> (32-(n)))
+#define MIO_FULL (~((unsigned)0))
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Mio_LibraryStruct_t_
+{
+ char * pName; // the name of the library
+ int nGates; // the number of the gates
+ Mio_Gate_t * pGates; // the linked list of all gates in no particular order
+ Mio_Gate_t * pGate0; // the constant zero gate
+ Mio_Gate_t * pGate1; // the constant one gate
+ Mio_Gate_t * pGateBuf; // the buffer
+ Mio_Gate_t * pGateInv; // the inverter
+ Mio_Gate_t * pGateNand2; // the NAND2 gate
+ st_table * tName2Gate; // the mapping of gate names into their pointer
+ DdManager * dd; // the nanager storing functions of gates
+ Extra_MmFlex_t * pMmFlex; // the memory manaqer for SOPs
+ Vec_Str_t * vCube; // temporary cube
+};
+
+struct Mio_GateStruct_t_
+{
+ // information derived from the genlib file
+ char * pName; // the name of the gate
+ double dArea; // the area of the gate
+ char * pForm; // the formula describing functionality of the gate
+ Mio_Pin_t * pPins; // the linked list of all pins (one pin if info is the same)
+ char * pOutName; // the name of the output pin
+ // the library to which this gate belongs
+ Mio_Library_t * pLib;
+ // the next gate in the list
+ Mio_Gate_t * pNext;
+
+ // the derived information
+ int nInputs; // the number of inputs
+ double dDelayMax; // the maximum delay
+ DdNode * bFunc; // the functionality
+ char * pSop;
+};
+
+struct Mio_PinStruct_t_
+{
+ char * pName;
+ Mio_PinPhase_t Phase;
+ double dLoadInput;
+ double dLoadMax;
+ double dDelayBlockRise;
+ double dDelayFanoutRise;
+ double dDelayBlockFall;
+ double dDelayFanoutFall;
+ double dDelayBlockMax;
+ Mio_Pin_t * pNext;
+};
+
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== mio.c =============================================================*/
+/*=== mioRead.c =============================================================*/
+/*=== mioUtils.c =============================================================*/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c
new file mode 100644
index 00000000..098cdb50
--- /dev/null
+++ b/src/map/mio/mioRead.c
@@ -0,0 +1,572 @@
+/**CFile****************************************************************
+
+ FileName [mioRead.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [File reading/writing for technology mapping.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: mioRead.c,v 1.9 2004/10/19 06:40:16 satrajit Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+#include "ioInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose );
+static int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose );
+static Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat );
+static Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat );
+static char * chomp( char *s );
+static void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib );
+static void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines );
+
+#ifdef WIN32
+extern int isspace( int c ); // to silence the warning in VS
+#endif
+
+/**Function*************************************************************
+
+ Synopsis [Read the genlib type of library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Library_t * Mio_LibraryRead( Abc_Frame_t * pAbc, char * FileName, char * ExcludeFile, int fVerbose )
+{
+ Mio_Library_t * pLib;
+ int num;
+
+ st_table * tExcludeGate = 0;
+
+ if ( ExcludeFile )
+ {
+ tExcludeGate = st_init_table(strcmp, st_strhash);
+ if ( (num = Mio_LibraryReadExclude( pAbc, ExcludeFile, tExcludeGate )) == -1 )
+ {
+ st_free_table( tExcludeGate );
+ tExcludeGate = 0;
+ return 0;
+ }
+
+ fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num );
+ }
+
+ pLib = Mio_LibraryReadOne( pAbc, FileName, 0, tExcludeGate, fVerbose ); // try normal format first ..
+ if ( pLib == NULL )
+ {
+ pLib = Mio_LibraryReadOne( pAbc, FileName, 1, tExcludeGate, fVerbose ); // .. otherwise try extended format
+ if ( pLib != NULL )
+ printf ( "Warning: Read extended GENLIB format but ignoring extensions\n" );
+ }
+
+ return pLib;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Read the genlib type of library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose )
+{
+ Mio_Library_t * pLib;
+ char * pBuffer = 0;
+
+ // allocate the genlib structure
+ pLib = ALLOC( Mio_Library_t, 1 );
+ memset( pLib, 0, sizeof(Mio_Library_t) );
+ pLib->pName = util_strsav( FileName );
+ pLib->tName2Gate = st_init_table(strcmp, st_strhash);
+ pLib->pMmFlex = Extra_MmFlexStart();
+ pLib->vCube = Vec_StrAlloc( 100 );
+
+ // read the file and clean comments
+ // pBuffer = Io_ReadFileFileContents( FileName, NULL );
+ // we don't use above function but actually do the same thing explicitly
+ // to handle open_path expansion correctly
+
+ {
+ FILE * pFile;
+ int nFileSize;
+
+ // open the BLIF file for binary reading
+// pFile = Io_FileOpen( FileName, "open_path", "rb" );
+ pFile = fopen( FileName, "rb" );
+ // if we got this far, file should be okay otherwise would
+ // have been detected by caller
+ assert ( pFile != NULL );
+ // get the file size, in bytes
+ fseek( pFile, 0, SEEK_END );
+ nFileSize = ftell( pFile );
+ // move the file current reading position to the beginning
+ rewind( pFile );
+ // load the contents of the file into memory
+ pBuffer = ALLOC( char, nFileSize + 10 );
+ fread( pBuffer, nFileSize, 1, pFile );
+ // terminate the string with '\0'
+ pBuffer[ nFileSize ] = '\0';
+ strcat( pBuffer, "\n.end\n" );
+ // close file
+ fclose( pFile );
+ }
+
+ Io_ReadFileRemoveComments( pBuffer, NULL, NULL );
+
+ // parse the contents of the file
+ if ( Mio_LibraryReadInternal( pLib, pBuffer, fExtendedFormat, tExcludeGate, fVerbose ) )
+ {
+ Mio_LibraryDelete( pLib );
+ free( pBuffer );
+ return NULL;
+ }
+ free( pBuffer );
+
+ // derive the functinality of gates
+ if ( Mio_LibraryParseFormulas( pLib ) )
+ {
+ printf( "Mio_LibraryRead: Had problems parsing formulas.\n" );
+ Mio_LibraryDelete( pLib );
+ return NULL;
+ }
+
+ // detect INV and NAND2
+ Mio_LibraryDetectSpecialGates( pLib );
+//Mio_WriteLibrary( stdout, pLib );
+ return pLib;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Read the genlib type of library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose )
+{
+ Mio_Gate_t * pGate, ** ppGate;
+ char * pToken;
+ int nGates = 0;
+ int nDel = 0;
+
+ // start the linked list of gates
+ pLib->pGates = NULL;
+ ppGate = &pLib->pGates;
+
+ // read gates one by one
+ pToken = strtok( pBuffer, " \t\r\n" );
+ while ( pToken && strcmp( pToken, MIO_STRING_GATE ) == 0 )
+ {
+ // derive the next gate
+ pGate = Mio_LibraryReadGate( &pToken, fExtendedFormat );
+ if ( pGate == NULL )
+ return 1;
+
+ // set the library
+ pGate->pLib = pLib;
+
+ // printf ("Processing: '%s'\n", pGate->pName);
+
+ if ( tExcludeGate && st_is_member( tExcludeGate, pGate->pName ) )
+ {
+ //printf ("Excluding: '%s'\n", pGate->pName);
+ Mio_GateDelete( pGate );
+ nDel++;
+ }
+ else
+ {
+ // add this gate to the list
+ *ppGate = pGate;
+ ppGate = &pGate->pNext;
+ nGates++;
+
+ // remember this gate by name
+ if ( !st_is_member( pLib->tName2Gate, pGate->pName ) )
+ st_insert( pLib->tName2Gate, pGate->pName, (char *)pGate );
+ else
+ printf( "The gate with name \"%s\" appears more than once.\n", pGate->pName );
+ }
+ }
+ if ( fVerbose )
+ printf( "The number of gates read = %d.\n", nGates );
+
+ // check what is the last word read
+ if ( pToken && strcmp( pToken, ".end" ) != 0 )
+ return 1;
+
+ if ( nDel != 0 )
+ printf( "Actually excluded %d cells\n", nDel );
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Read the genlib type of gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat )
+{
+ Mio_Gate_t * pGate;
+ Mio_Pin_t * pPin, ** ppPin;
+ char * pToken = *ppToken;
+
+ // allocate the gate structure
+ pGate = ALLOC( Mio_Gate_t, 1 );
+ memset( pGate, 0, sizeof(Mio_Gate_t) );
+
+ // read the name
+ pToken = strtok( NULL, " \t\r\n" );
+ pGate->pName = util_strsav( pToken );
+
+ // read the area
+ pToken = strtok( NULL, " \t\r\n" );
+ pGate->dArea = atof( pToken );
+
+ // read the formula
+
+ // first the output name
+ pToken = strtok( NULL, "=" );
+ pGate->pOutName = chomp( pToken );
+
+ // then rest of the expression
+ pToken = strtok( NULL, ";" );
+ pGate->pForm = util_strsav( pToken );
+
+ // read the pin info
+ // start the linked list of pins
+ pGate->pPins = NULL;
+ ppPin = &pGate->pPins;
+
+ // read gates one by one
+ pToken = strtok( NULL, " \t\r\n" );
+ while ( pToken && strcmp( pToken, MIO_STRING_PIN ) == 0 )
+ {
+ // derive the next gate
+ pPin = Mio_LibraryReadPin( &pToken, fExtendedFormat );
+ if ( pPin == NULL )
+ {
+ Mio_GateDelete( pGate );
+ *ppToken = pToken;
+ return NULL;
+ }
+ // add this pin to the list
+ *ppPin = pPin;
+ ppPin = &pPin->pNext;
+ // get the next token
+ pToken = strtok( NULL, " \t\r\n" );
+ }
+
+ *ppToken = pToken;
+ return pGate;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Read the genlib type of pin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat )
+{
+ Mio_Pin_t * pPin;
+ char * pToken = *ppToken;
+
+ // allocate the gate structure
+ pPin = ALLOC( Mio_Pin_t, 1 );
+ memset( pPin, 0, sizeof(Mio_Pin_t) );
+
+ // read the name
+ pToken = strtok( NULL, " \t\r\n" );
+ pPin->pName = util_strsav( pToken );
+
+ // read the pin phase
+ pToken = strtok( NULL, " \t\r\n" );
+ if ( strcmp( pToken, MIO_STRING_UNKNOWN ) == 0 )
+ pPin->Phase = MIO_PHASE_UNKNOWN;
+ else if ( strcmp( pToken, MIO_STRING_INV ) == 0 )
+ pPin->Phase = MIO_PHASE_INV;
+ else if ( strcmp( pToken, MIO_STRING_NONINV ) == 0 )
+ pPin->Phase = MIO_PHASE_NONINV;
+ else
+ {
+ printf( "Cannot read pin phase specification\n" );
+ Mio_PinDelete( pPin );
+ *ppToken = pToken;
+ return NULL;
+ }
+
+ pToken = strtok( NULL, " \t\r\n" );
+ pPin->dLoadInput = atof( pToken );
+
+ pToken = strtok( NULL, " \t\r\n" );
+ pPin->dLoadMax = atof( pToken );
+
+ pToken = strtok( NULL, " \t\r\n" );
+ pPin->dDelayBlockRise = atof( pToken );
+
+ pToken = strtok( NULL, " \t\r\n" );
+ pPin->dDelayFanoutRise = atof( pToken );
+
+ pToken = strtok( NULL, " \t\r\n" );
+ pPin->dDelayBlockFall = atof( pToken );
+
+ pToken = strtok( NULL, " \t\r\n" );
+ pPin->dDelayFanoutFall = atof( pToken );
+
+ if ( fExtendedFormat )
+ {
+ /* In extended format, the field after dDelayFanoutRise
+ * is to be ignored
+ **/
+
+ pPin->dDelayBlockFall = pPin->dDelayFanoutFall;
+
+ pToken = strtok( NULL, " \t" );
+ pPin->dDelayFanoutFall = atof( pToken );
+
+ /* last field is ignored */
+ pToken = strtok( NULL, " \t\r\n" );
+ }
+
+ if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall )
+ pPin->dDelayBlockMax = pPin->dDelayBlockRise;
+ else
+ pPin->dDelayBlockMax = pPin->dDelayBlockFall;
+
+ *ppToken = pToken;
+ return pPin;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates string and returns it with leading and
+ trailing spaces removed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char *chomp( char *s )
+{
+ char *b = ALLOC(char, strlen(s)+1), *c = b;
+ while (*s && isspace(*s))
+ ++s;
+ while (*s && !isspace(*s))
+ *c++ = *s++;
+ *c = 0;
+ return b;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates string and returns it with leading and
+ trailing spaces removed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
+{
+ Mio_Gate_t * pGate;
+ DdNode * bFuncBuf, * bFuncInv, * bFuncNand2;
+
+ bFuncBuf = pLib->dd->vars[0]; Cudd_Ref( bFuncBuf );
+ bFuncInv = Cudd_Not( pLib->dd->vars[0] ); Cudd_Ref( bFuncInv );
+ bFuncNand2 = Cudd_bddNand( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncNand2 );
+
+ Mio_LibraryForEachGate( pLib, pGate )
+ if ( pLib->pGateBuf == NULL && pGate->bFunc == bFuncBuf )
+ {
+ pLib->pGateBuf = pGate;
+ break;
+ }
+ if ( pLib->pGateBuf == NULL )
+ {
+ printf( "Warnings: GENLIB library reader cannot detect the buffer gate.\n" );
+ printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
+ }
+
+ Mio_LibraryForEachGate( pLib, pGate )
+ if ( pLib->pGateInv == NULL && pGate->bFunc == bFuncInv )
+ {
+ pLib->pGateInv = pGate;
+ break;
+ }
+ if ( pLib->pGateInv == NULL )
+ {
+ printf( "Warnings: GENLIB library reader cannot detect the invertor gate.\n" );
+ printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
+ }
+
+ Mio_LibraryForEachGate( pLib, pGate )
+ if ( pLib->pGateNand2 == NULL && pGate->bFunc == bFuncNand2 )
+ {
+ pLib->pGateNand2 = pGate;
+ break;
+ }
+ if ( pLib->pGateNand2 == NULL )
+ {
+ printf( "Warnings: GENLIB library reader cannot detect the NAND2 gate.\n" );
+ printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" );
+ }
+
+ Cudd_RecursiveDeref( pLib->dd, bFuncInv );
+ Cudd_RecursiveDeref( pLib->dd, bFuncNand2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [populate hash table of gates to be exlcuded from genlib]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * tExcludeGate )
+{
+ int nDel = 0;
+ FILE *pEx;
+ char buffer[128];
+
+ assert ( tExcludeGate );
+
+ if ( ExcludeFile )
+ {
+ pEx = fopen( ExcludeFile, "r" );
+
+ if ( pEx == NULL )
+ {
+ fprintf ( Abc_FrameReadErr( pAbc ), "Error: Could not open exclude file %s. Stop.\n", ExcludeFile );
+ return -1;
+ }
+
+ while (1 == fscanf( pEx, "%127s", buffer ))
+ {
+ //printf ("Read: '%s'\n", buffer );
+ st_insert( tExcludeGate, util_strsav( buffer ), (char *)0 );
+ nDel++;
+ }
+
+ fclose( pEx );
+ }
+
+ return nDel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Eliminates comments from the input file.]
+
+ Description [As a byproduct, this procedure also counts the number
+ lines and dot-statements in the input file. This also joins non-comment
+ lines that are joined with a backspace '\']
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines )
+{
+ char * pCur;
+ int nDots, nLines;
+ // scan through the buffer and eliminate comments
+ // (in the BLIF file, comments are lines starting with "#")
+ nDots = nLines = 0;
+ for ( pCur = pBuffer; *pCur; pCur++ )
+ {
+ // if this is the beginning of comment
+ // clean it with spaces until the new line statement
+ if ( *pCur == '#' )
+ while ( *pCur != '\n' )
+ *pCur++ = ' ';
+
+ // count the number of new lines and dots
+ if ( *pCur == '\n' ) {
+ if (*(pCur-1)=='\r') {
+ // DOS(R) file support
+ if (*(pCur-2)!='\\') nLines++;
+ else {
+ // rewind to backslash and overwrite with a space
+ *(pCur-2) = ' ';
+ *(pCur-1) = ' ';
+ *pCur = ' ';
+ }
+ } else {
+ // UNIX(TM) file support
+ if (*(pCur-1)!='\\') nLines++;
+ else {
+ // rewind to backslash and overwrite with a space
+ *(pCur-1) = ' ';
+ *pCur = ' ';
+ }
+ }
+ }
+ else if ( *pCur == '.' )
+ nDots++;
+ }
+ if ( pnDots )
+ *pnDots = nDots;
+ if ( pnLines )
+ *pnLines = nLines;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c
new file mode 100644
index 00000000..aa373783
--- /dev/null
+++ b/src/map/mio/mioUtils.c
@@ -0,0 +1,531 @@
+/**CFile****************************************************************
+
+ FileName [mioUtils.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [File reading/writing for technology mapping.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: mioUtils.c,v 1.6 2004/09/03 18:02:20 satrajit Exp $]
+
+***********************************************************************/
+
+#include "mioInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int fPrintSops );
+static void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin );
+static int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 );
+static void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_LibraryDelete( Mio_Library_t * pLib )
+{
+ Mio_Gate_t * pGate, * pGate2;
+ if ( pLib == NULL )
+ return;
+ // free the bindings of nodes to gates from this library for all networks
+// Mv_FrameFreeNetworkBindings( Mv_FrameGetGlobalFrame() );
+ // free the library
+ FREE( pLib->pName );
+ Mio_LibraryForEachGateSafe( pLib, pGate, pGate2 )
+ Mio_GateDelete( pGate );
+ Extra_MmFlexStop( pLib->pMmFlex, 0 );
+ Vec_StrFree( pLib->vCube );
+ if ( pLib->tName2Gate )
+ st_free_table( pLib->tName2Gate );
+ if ( pLib->dd )
+ Cudd_Quit( pLib->dd );
+ free( pLib );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_GateDelete( Mio_Gate_t * pGate )
+{
+ Mio_Pin_t * pPin, * pPin2;
+ FREE( pGate->pOutName );
+ FREE( pGate->pName );
+ FREE( pGate->pForm );
+ if ( pGate->bFunc )
+ Cudd_RecursiveDeref( pGate->pLib->dd, pGate->bFunc );
+ Mio_GateForEachPinSafe( pGate, pPin, pPin2 )
+ Mio_PinDelete( pPin );
+ free( pGate );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_PinDelete( Mio_Pin_t * pPin )
+{
+ FREE( pPin->pName );
+ free( pPin );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin )
+{
+ Mio_Pin_t * pPinNew;
+
+ pPinNew = ALLOC( Mio_Pin_t, 1 );
+ *pPinNew = *pPin;
+ pPinNew->pName = (pPinNew->pName ? util_strsav(pPinNew->pName) : NULL);
+ pPinNew->pNext = NULL;
+
+ return pPinNew;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops )
+{
+ Mio_Gate_t * pGate;
+
+ fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName );
+ Mio_LibraryForEachGate( pLib, pGate )
+ Mio_WriteGate( pFile, pGate, fPrintSops );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int fPrintSops )
+{
+ Mio_Pin_t * pPin;
+
+ fprintf( pFile, "GATE " );
+ fprintf( pFile, "%12s ", pGate->pName );
+ fprintf( pFile, "%10.2f ", pGate->dArea );
+ fprintf( pFile, "O=%s;\n", pGate->pForm );
+ // print the pins
+ if ( fPrintSops )
+ fprintf( pFile, "%s", pGate->pSop? pGate->pSop : "unspecified\n" );
+// Extra_bddPrint( pGate->pLib->dd, pGate->bFunc );
+// fprintf( pFile, "\n" );
+ Mio_GateForEachPin( pGate, pPin )
+ Mio_WritePin( pFile, pPin );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin )
+{
+ char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" };
+ fprintf( pFile, " PIN " );
+ fprintf( pFile, "%9s ", pPin->pName );
+ fprintf( pFile, "%10s ", pPhaseNames[pPin->Phase] );
+ fprintf( pFile, "%6d ", (int)pPin->dLoadInput );
+ fprintf( pFile, "%6d ", (int)pPin->dLoadMax );
+ fprintf( pFile, "%6.2f ", pPin->dDelayBlockRise );
+ fprintf( pFile, "%6.2f ", pPin->dDelayFanoutRise );
+ fprintf( pFile, "%6.2f ", pPin->dDelayBlockFall );
+ fprintf( pFile, "%6.2f", pPin->dDelayFanoutFall );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the set of root gates.]
+
+ Description [Only collects the gates with unique functionality,
+ which have fewer inputs and shorter delay than the given limits.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, bool fSkipInv, int * pnGates )
+{
+ Mio_Gate_t * pGate;
+ Mio_Gate_t ** ppGates;
+ /* st_table * tFuncs; */
+ /* st_generator * gen; */
+ DdNode * bFunc;
+ DdManager * dd;
+ int nGates, iGate;
+
+ dd = Mio_LibraryReadDd( pLib );
+ nGates = Mio_LibraryReadGateNum( pLib );
+
+ /*
+
+ // for each functionality select one gate; skip constants and buffers
+ tFuncs = st_init_table( st_ptrcmp, st_ptrhash );
+ Mio_LibraryForEachGate( pLib, pGate )
+ {
+ bFunc = Mio_GateReadFunc(pGate);
+ if ( pGate->nInputs > nInputs )
+ continue;
+ if ( pGate->dDelayMax > (double)tDelay )
+ continue;
+ if ( bFunc == b0 || bFunc == b1 )
+ continue;
+ if ( bFunc == dd->vars[0] )
+ continue;
+ if ( bFunc == Cudd_Not(dd->vars[0]) && fSkipInv )
+ continue;
+ if ( st_is_member( tFuncs, (char *)bFunc ) )
+ continue;
+ st_insert( tFuncs, (char *)bFunc, (char *)pGate );
+ }
+
+ // collect the gates into the array
+ ppGates = ALLOC( Mio_Gate_t *, nGates );
+ iGate = 0;
+ st_foreach_item( tFuncs, gen, (char **)&bFunc, (char **)&pGate )
+ ppGates[ iGate++ ] = pGate;
+ assert( iGate <= nGates );
+ st_free_table( tFuncs );
+
+ */
+
+ ppGates = ALLOC( Mio_Gate_t *, nGates );
+ iGate = 0;
+ Mio_LibraryForEachGate( pLib, pGate )
+ {
+ bFunc = Mio_GateReadFunc(pGate);
+ if ( pGate->nInputs > nInputs )
+ continue;
+ if ( pGate->dDelayMax > (double)tDelay )
+ continue;
+ if ( bFunc == b0 || bFunc == b1 )
+ continue;
+ if ( bFunc == dd->vars[0] )
+ continue;
+ if ( bFunc == Cudd_Not(dd->vars[0]) && fSkipInv )
+ continue;
+
+ assert( iGate < nGates );
+ ppGates[ iGate++ ] = pGate;
+ }
+
+ if ( iGate > 0 )
+ {
+ // sort the gates by delay
+ qsort( (void *)ppGates, iGate, sizeof(Mio_Gate_t *),
+ (int (*)(const void *, const void *)) Mio_DelayCompare );
+ assert( Mio_DelayCompare( ppGates, ppGates + iGate - 1 ) <= 0 );
+ }
+
+ if ( pnGates )
+ *pnGates = iGate;
+ return ppGates;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the max delay of two gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 )
+{
+ if ( (*ppG1)->dDelayMax < (*ppG2)->dDelayMax )
+ return -1;
+ if ( (*ppG1)->dDelayMax > (*ppG2)->dDelayMax )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the truth table of the gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] )
+{
+ Mio_DeriveTruthTable_rec( pGate->bFunc, uTruthsIn, uTruthRes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively derives the truth table of the gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] )
+{
+ unsigned uTruthsCof0[2];
+ unsigned uTruthsCof1[2];
+
+ // complement the resulting truth table, if the function is complemented
+ if ( Cudd_IsComplement(bFunc) )
+ {
+ Mio_DeriveTruthTable_rec( Cudd_Not(bFunc), uTruthsIn, uTruthRes );
+ uTruthRes[0] = ~uTruthRes[0];
+ uTruthRes[1] = ~uTruthRes[1];
+ return;
+ }
+
+ // if the function is constant 1, return the constant 1 truth table
+ if ( bFunc->index == CUDD_CONST_INDEX )
+ {
+ uTruthRes[0] = MIO_FULL;
+ uTruthRes[1] = MIO_FULL;
+ return;
+ }
+
+ // solve the problem for both cofactors
+ Mio_DeriveTruthTable_rec( cuddE(bFunc), uTruthsIn, uTruthsCof0 );
+ Mio_DeriveTruthTable_rec( cuddT(bFunc), uTruthsIn, uTruthsCof1 );
+
+ // derive the resulting truth table using the input truth tables
+ uTruthRes[0] = (uTruthsCof0[0] & ~uTruthsIn[bFunc->index][0]) |
+ (uTruthsCof1[0] & uTruthsIn[bFunc->index][0]);
+ uTruthRes[1] = (uTruthsCof0[1] & ~uTruthsIn[bFunc->index][1]) |
+ (uTruthsCof1[1] & uTruthsIn[bFunc->index][1]);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the truth table of the root of the gate.]
+
+ Description [Given the truth tables of the leaves of the gate,
+ this procedure derives the truth table of the root.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_DeriveTruthTable2( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nTruths, int nInputs, unsigned uTruthRes[] )
+{
+ unsigned uSignCube[2];
+ int i, nFanins;
+ char * pCube;
+
+ // make sure that the number of input truth tables in equal to the number of gate inputs
+ assert( pGate->nInputs == nTruths );
+ assert( nInputs < 7 );
+
+ nFanins = Abc_SopGetVarNum( pGate->pSop );
+ assert( nFanins == nInputs );
+
+ // clean the resulting truth table
+ uTruthRes[0] = 0;
+ uTruthRes[1] = 0;
+ if ( nInputs < 6 )
+ {
+// for ( c = 0; *(pCube = pGate->pSop + c * (nFanins + 3)); c++ )
+ Abc_SopForEachCube( pGate->pSop, nFanins, pCube )
+ {
+ // add the clause
+ uSignCube[0] = MIO_FULL;
+ for ( i = 0; i < nFanins; i++ )
+ {
+ if ( pCube[i] == '0' )
+ uSignCube[0] &= ~uTruthsIn[i][0];
+ else if ( pCube[i] == '1' )
+ uSignCube[0] &= uTruthsIn[i][0];
+ }
+ }
+ if ( nInputs < 5 )
+ uTruthRes[0] &= MIO_MASK(1<<nInputs);
+ }
+ else
+ {
+ // consider the case when two unsigneds should be used
+// for ( c = 0; *(pCube = pGate->pSop + c * (nFanins + 3)); c++ )
+ Abc_SopForEachCube( pGate->pSop, nFanins, pCube )
+ {
+ uSignCube[0] = MIO_FULL;
+ uSignCube[1] = MIO_FULL;
+ for ( i = 0; i < nFanins; i++ )
+ {
+ if ( pCube[i] == '0' )
+ {
+ uSignCube[0] &= ~uTruthsIn[i][0];
+ uSignCube[1] &= ~uTruthsIn[i][1];
+ }
+ else if ( pCube[i] == '1' )
+ {
+ uSignCube[0] &= uTruthsIn[i][0];
+ uSignCube[1] &= uTruthsIn[i][1];
+ }
+ }
+ uTruthRes[0] |= uSignCube[0];
+ uTruthRes[1] |= uSignCube[1];
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the area and delay of the root of the gate.]
+
+ Description [Array of the resulting delays should be initialized
+ to the (negative) SUPER_NO_VAR value.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_DeriveGateDelays( Mio_Gate_t * pGate,
+ float ** ptPinDelays, int nPins, int nInputs, float tDelayZero,
+ float * ptDelaysRes, float * ptPinDelayMax )
+{
+ Mio_Pin_t * pPin;
+ float Delay, DelayMax;
+ int i, k;
+ assert( pGate->nInputs == nPins );
+ // set all the delays to the unused delay
+ for ( i = 0; i < nInputs; i++ )
+ ptDelaysRes[i] = tDelayZero;
+ // compute the delays for each input and the max delay at the same time
+ DelayMax = 0;
+ for ( i = 0; i < nInputs; i++ )
+ {
+ for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ )
+ {
+ if ( ptPinDelays[k][i] < 0 )
+ continue;
+ Delay = ptPinDelays[k][i] + (float)pPin->dDelayBlockMax;
+ if ( ptDelaysRes[i] < Delay )
+ ptDelaysRes[i] = Delay;
+ }
+ if ( k != nPins )
+ {
+ printf ("DEBUG: problem gate is %s\n", Mio_GateReadName( pGate ));
+ }
+ assert( k == nPins );
+ if ( DelayMax < ptDelaysRes[i] )
+ DelayMax = ptDelaysRes[i];
+ }
+ *ptPinDelayMax = DelayMax;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates a pseudo-gate.]
+
+ Description [The pseudo-gate is a N-input gate with all info set to 0.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Mio_Gate_t * Mio_GateCreatePseudo( int nInputs )
+{
+ Mio_Gate_t * pGate;
+ Mio_Pin_t * pPin;
+ int i;
+ // allocate the gate structure
+ pGate = ALLOC( Mio_Gate_t, 1 );
+ memset( pGate, 0, sizeof(Mio_Gate_t) );
+ pGate->nInputs = nInputs;
+ // create pins
+ for ( i = 0; i < nInputs; i++ )
+ {
+ pPin = ALLOC( Mio_Pin_t, 1 );
+ memset( pPin, 0, sizeof(Mio_Pin_t) );
+ pPin->pNext = pGate->pPins;
+ pGate->pPins = pPin;
+ }
+ return pGate;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/mio/module.make b/src/map/mio/module.make
new file mode 100644
index 00000000..26a4561c
--- /dev/null
+++ b/src/map/mio/module.make
@@ -0,0 +1,5 @@
+SRC += src/map/mio/mio.c \
+ src/map/mio/mioApi.c \
+ src/map/mio/mioFunc.c \
+ src/map/mio/mioRead.c \
+ src/map/mio/mioUtils.c
diff --git a/src/map/super/module.make b/src/map/super/module.make
new file mode 100644
index 00000000..19ce8228
--- /dev/null
+++ b/src/map/super/module.make
@@ -0,0 +1,4 @@
+SRC += src/map/super/super.c \
+ src/map/super/superAnd.c \
+ src/map/super/superGate.c \
+ src/map/super/superWrite.c
diff --git a/src/map/super/super.c b/src/map/super/super.c
new file mode 100644
index 00000000..ffb432d5
--- /dev/null
+++ b/src/map/super/super.c
@@ -0,0 +1,319 @@
+/**CFile****************************************************************
+
+ FileName [super.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Pre-computation of supergates.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 18, 2003.]
+
+ Revision [$Id: super.c,v 1.6 2004/10/30 20:51:11 satrajit Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+#include "mainInt.h"
+#include "mio.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Super_CommandSupergates ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_Init( Abc_Frame_t * pAbc )
+{
+ Cmd_CommandAdd( pAbc, "SC mapping", "super", Super_CommandSupergates, 0 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "super2", Super_CommandSupergatesAnd, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_End()
+{
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pOut, * pErr;
+ int nVarsMax, nLevels;
+ int fVerbose;
+ int c;
+
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ nVarsMax = 4;
+ nLevels = 3;
+ fVerbose = 0;
+ util_getopt_reset();
+ while ( (c = util_getopt(argc, argv, "ilvh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'i':
+ nVarsMax = atoi(argv[util_optind]);
+ util_optind++;
+ if ( nVarsMax < 0 )
+ goto usage;
+ break;
+ case 'l':
+ nLevels = atoi(argv[util_optind]);
+ util_optind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ Super2_Precompute( nVarsMax, nLevels, fVerbose );
+
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: super2 [-i num] [-l num] [-vh]\n");
+ fprintf( pErr, "\t precomputes the supergates composed of AND2s and INVs\n" );
+ fprintf( pErr, "\t-i num : the max number of inputs to the supergate [default = %d]\n", nVarsMax );
+ fprintf( pErr, "\t-l num : the max number of logic levels of gates [default = %d]\n", nLevels );
+ fprintf( pErr, "\t-v : enable verbose output\n");
+ fprintf( pErr, "\t-h : print the help message\n");
+ return 1; /* error exit */
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pFile;
+ FILE * pOut, * pErr;
+ Mio_Library_t * pLib;
+ char * FileName, * ExcludeFile;
+ float DelayLimit;
+ float AreaLimit;
+ bool fSkipInvs;
+ bool fWriteOldFormat;
+ int nVarsMax, nLevels, TimeLimit;
+ int fVerbose;
+ int c;
+
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ nVarsMax = 5;
+ nLevels = 3;
+ DelayLimit = 3.5;
+ AreaLimit = 9;
+ TimeLimit = 10;
+ fSkipInvs = 1;
+ fVerbose = 0;
+ fWriteOldFormat = 0;
+ ExcludeFile = 0;
+
+ util_getopt_reset();
+ while ( (c = util_getopt(argc, argv, "eiltdasovh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'e':
+ ExcludeFile = argv[util_optind];
+ if ( ExcludeFile == 0 )
+ goto usage;
+ util_optind++;
+ break;
+ case 'i':
+ nVarsMax = atoi(argv[util_optind]);
+ util_optind++;
+ if ( nVarsMax < 0 )
+ goto usage;
+ break;
+ case 'l':
+ nLevels = atoi(argv[util_optind]);
+ util_optind++;
+ if ( nLevels < 0 )
+ goto usage;
+ break;
+ case 't':
+ TimeLimit = atoi(argv[util_optind]);
+ util_optind++;
+ if ( TimeLimit < 0 )
+ goto usage;
+ break;
+ case 'd':
+ DelayLimit = (float)atof(argv[util_optind]);
+ util_optind++;
+ if ( DelayLimit <= 0.0 )
+ goto usage;
+ break;
+ case 'a':
+ AreaLimit = (float)atof(argv[util_optind]);
+ util_optind++;
+ if ( AreaLimit <= 0.0 )
+ goto usage;
+ break;
+ case 's':
+ fSkipInvs ^= 1;
+ break;
+ case 'o':
+ fWriteOldFormat ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+
+ if ( argc != util_optind + 1 )
+ {
+ fprintf( pErr, "The GENLIB library file should be given on the command line.\n" );
+ goto usage;
+ }
+
+ if ( nVarsMax < 2 || nVarsMax > 6 )
+ {
+ fprintf( pErr, "The max number of variables (%d) should be more than 1 and less than 7.\n", nVarsMax );
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[util_optind];
+// if ( (pFile = Io_FileOpen( FileName, "open_path", "r" )) == NULL )
+ if ( (pFile = fopen( FileName, "r" )) == NULL )
+ {
+ fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+ if (( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) ))
+ fprintf( pErr, "Did you mean \"%s\"?", FileName );
+ fprintf( pErr, "\n" );
+ return 1;
+ }
+ fclose( pFile );
+
+ // set the new network
+ pLib = Mio_LibraryRead( pAbc, FileName, ExcludeFile, fVerbose );
+ if ( pLib == NULL )
+ {
+ fprintf( pErr, "Reading library has failed.\n" );
+ goto usage;
+ }
+
+ // compute the gates
+ Super_Precompute( pLib, nVarsMax, nLevels, DelayLimit, AreaLimit, TimeLimit, fSkipInvs, fWriteOldFormat, fVerbose );
+
+ // delete the library
+ Mio_LibraryDelete( pLib );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: super [-i num] [-l num] [-d float] [-a float] [-t num] [-sovh] <genlib_file>\n");
+ fprintf( pErr, "\t precomputes the supergates for the given GENLIB library\n" );
+ fprintf( pErr, "\t-i num : the max number of supergate inputs [default = %d]\n", nVarsMax );
+ fprintf( pErr, "\t-l num : the max number of levels of gates [default = %d]\n", nLevels );
+ fprintf( pErr, "\t-d float : the max delay of the supergates [default = %.2f]\n", DelayLimit );
+ fprintf( pErr, "\t-a float : the max area of the supergates [default = %.2f]\n", AreaLimit );
+ fprintf( pErr, "\t-t num : the approximate runtime limit in seconds [default = %d]\n", TimeLimit );
+ fprintf( pErr, "\t-s : toggle the use of inverters at the inputs [default = %s]\n", (fSkipInvs? "no": "yes") );
+ fprintf( pErr, "\t-o : toggle dumping the supergate library in old format [default = %s]\n", (fWriteOldFormat? "yes": "no") );
+ fprintf( pErr, "\t-e file : file contains list of genlib gates to exclude\n" );
+ fprintf( pErr, "\t-v : enable verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+ fprintf( pErr, "\t-h : print the help message\n");
+ fprintf( pErr, "\n");
+ fprintf( pErr, "\tHere is a piece of advice on precomputing supergate libraries:\n");
+ fprintf( pErr, "\t\n");
+ fprintf( pErr, "\tStart with the number of inputs equal to 5 (-i 5), the number of \n");
+ fprintf( pErr, "\tlevels equal to 3 (-l 3), the delay equal to 2-3 delays of inverter, \n");
+ fprintf( pErr, "\tthe area equal to 3-4 areas of two input NAND, and runtime limit equal \n");
+ fprintf( pErr, "\tto 10 seconds (-t 10). Run precomputation and learn from the result.\n");
+ fprintf( pErr, "\tDetermine what parameter is most constraining and try to increase \n");
+ fprintf( pErr, "\tthe value of that parameter. The goal is to have a well-balanced\n");
+ fprintf( pErr, "\tset of constraints and the resulting supergate library containing\n");
+ fprintf( pErr, "\tapproximately 100K-200K supergates. Typically, it is better to increase\n");
+ fprintf( pErr, "\tdelay limit rather than area limit, because having large-area supergates\n");
+ fprintf( pErr, "\tmay result in a considerable increase in area.\n");
+ fprintf( pErr, "\t\n");
+ fprintf( pErr, "\tNote that a good supergate library for experiments typically can be \n");
+ fprintf( pErr, "\tprecomputed in 30 sec. Increasing the runtime limit makes sense when\n");
+ fprintf( pErr, "\tother parameters are well-balanced and it is needed to enumerate more\n");
+ fprintf( pErr, "\tchoices to have a good result. In the end, to compute the final library\n");
+ fprintf( pErr, "\tthe runtime can be set to 300 sec to ensure the ultimate quality.\n");
+ fprintf( pErr, "\tIn some cases, the runtime has to be reduced if the supergate library\n");
+ fprintf( pErr, "\tcontains too many supergates (> 500K).\n");
+ fprintf( pErr, "\t\n");
+ fprintf( pErr, "\tWhen precomputing libraries of 6 inputs (-i 6), start with even more \n");
+ fprintf( pErr, "\trestricted parameters and gradually increase them until the goal is met.\n");
+ fprintf( pErr, "\t\n");
+ return 1; /* error exit */
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/super/super.h b/src/map/super/super.h
new file mode 100644
index 00000000..ce2b7433
--- /dev/null
+++ b/src/map/super/super.h
@@ -0,0 +1,51 @@
+/**CFile****************************************************************
+
+ FileName [super.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Pre-computation of supergates (delay-limited gate combinations).]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: super.h,v 1.3 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __SUPER_H__
+#define __SUPER_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== superCore.c =============================================================*/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/src/map/super/superAnd.c b/src/map/super/superAnd.c
new file mode 100644
index 00000000..e90fc76d
--- /dev/null
+++ b/src/map/super/superAnd.c
@@ -0,0 +1,696 @@
+/**CFile****************************************************************
+
+ FileName [superAnd.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Pre-computation of supergates.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: superAnd.c,v 1.3 2004/06/28 14:20:25 alanmi Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit masks
+#define SUPER_MASK(n) ((~((unsigned)0)) >> (32-n))
+#define SUPER_FULL (~((unsigned)0))
+
+// data structure for AND2 subgraph precomputation
+typedef struct Super2_ManStruct_t_ Super2_Man_t; // manager
+typedef struct Super2_LibStruct_t_ Super2_Lib_t; // library
+typedef struct Super2_GateStruct_t_ Super2_Gate_t; // supergate
+
+struct Super2_ManStruct_t_
+{
+ Extra_MmFixed_t * pMem; // memory manager for all supergates
+ stmm_table * tTable; // mapping of truth tables into gates
+ int nTried; // the total number of tried
+};
+
+struct Super2_LibStruct_t_
+{
+ int i; // used to iterate through the table
+ int k; // used to iterate through the table
+ int nInputs; // the number of inputs
+ int nMints; // the number of minterms
+ int nLevels; // the number of logic levels
+ int nGates; // the number of gates in the library
+ int nGatesAlloc; // the number of allocated places
+ Super2_Gate_t ** pGates; // the gates themselves
+ unsigned uMaskBit; // the mask used to determine the compl bit
+};
+
+struct Super2_GateStruct_t_
+{
+ unsigned uTruth; // the truth table of this supergate
+ Super2_Gate_t * pOne; // the left wing
+ Super2_Gate_t * pTwo; // the right wing
+ Super2_Gate_t * pNext; // the next gate in the table
+};
+
+
+// manipulation of complemented attributes
+#define Super2_IsComplement(p) (((int)((long) (p) & 01)))
+#define Super2_Regular(p) ((Super2_Gate_t *)((unsigned)(p) & ~01))
+#define Super2_Not(p) ((Super2_Gate_t *)((long)(p) ^ 01))
+#define Super2_NotCond(p,c) ((Super2_Gate_t *)((long)(p) ^ (c)))
+
+// iterating through the gates in the library
+#define Super2_LibForEachGate( Lib, Gate ) \
+ for ( Lib->i = 0; \
+ Lib->i < Lib->nGates && (Gate = Lib->pGates[Lib->i]); \
+ Lib->i++ )
+#define Super2_LibForEachGate2( Lib, Gate2 ) \
+ for ( Lib->k = 0; \
+ Lib->k < Lib->i && (Gate2 = Lib->pGates[Lib->k]); \
+ Lib->k++ )
+
+// static functions
+static Super2_Man_t * Super2_ManStart();
+static void Super2_ManStop( Super2_Man_t * pMan );
+static Super2_Lib_t * Super2_LibStart();
+static Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib );
+static void Super2_LibStop( Super2_Lib_t * pLib );
+static void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate );
+static Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs );
+static Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib );
+
+static void Super2_LibWrite( Super2_Lib_t * pLib );
+static void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate );
+static char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level );
+static int Super2_LibWriteCompare( char * pStr1, char * pStr2 );
+static int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Precomputes the library of AND2 gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super2_Precompute( int nInputs, int nLevels, int fVerbose )
+{
+ Super2_Man_t * pMan;
+ Super2_Lib_t * pLibCur, * pLibNext;
+ int Level;
+ int clk;
+
+ assert( nInputs < 6 );
+
+ // start the manager
+ pMan = Super2_ManStart();
+
+ // get the starting supergates
+ pLibCur = Super2_LibFirst( pMan, nInputs );
+
+ // perform the computation of supergates
+printf( "Computing supergates for %d inputs and %d levels:\n", nInputs, nLevels );
+ for ( Level = 1; Level <= nLevels; Level++ )
+ {
+clk = clock();
+ pLibNext = Super2_LibCompute( pMan, pLibCur );
+ pLibNext->nLevels = Level;
+ Super2_LibStop( pLibCur );
+ pLibCur = pLibNext;
+printf( "Level %d: Tried = %7d. Computed = %7d. ", Level, pMan->nTried, pLibCur->nGates );
+PRT( "Runtime", clock() - clk );
+fflush( stdout );
+ }
+
+printf( "Writing the output file...\n" );
+fflush( stdout );
+ // write them into a file
+ Super2_LibWrite( pLibCur );
+ Super2_LibStop( pLibCur );
+
+ // stop the manager
+ Super2_ManStop( pMan );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Super2_Man_t * Super2_ManStart()
+{
+ Super2_Man_t * pMan;
+ pMan = ALLOC( Super2_Man_t, 1 );
+ memset( pMan, 0, sizeof(Super2_Man_t) );
+ pMan->pMem = Extra_MmFixedStart( sizeof(Super2_Gate_t) );
+ pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super2_ManStop( Super2_Man_t * pMan )
+{
+ Extra_MmFixedStop( pMan->pMem, 0 );
+ stmm_free_table( pMan->tTable );
+ free( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Super2_Lib_t * Super2_LibStart()
+{
+ Super2_Lib_t * pLib;
+ pLib = ALLOC( Super2_Lib_t, 1 );
+ memset( pLib, 0, sizeof(Super2_Lib_t) );
+ return pLib;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib )
+{
+ Super2_Lib_t * pLibNew;
+ pLibNew = Super2_LibStart();
+ pLibNew->nInputs = pLib->nInputs;
+ pLibNew->nMints = pLib->nMints;
+ pLibNew->nLevels = pLib->nLevels;
+ pLibNew->nGates = pLib->nGates;
+ pLibNew->uMaskBit = pLib->uMaskBit;
+ pLibNew->nGatesAlloc = 1000 + pLib->nGatesAlloc;
+ pLibNew->pGates = ALLOC( Super2_Gate_t *, pLibNew->nGatesAlloc );
+ memcpy( pLibNew->pGates, pLib->pGates, pLibNew->nGates * sizeof(Super2_Gate_t *) );
+ return pLibNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add gate to the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate )
+{
+ if ( pLib->nGates == pLib->nGatesAlloc )
+ {
+ pLib->pGates = REALLOC( Super2_Gate_t *, pLib->pGates, 3 * pLib->nGatesAlloc );
+ pLib->nGatesAlloc *= 3;
+ }
+ pLib->pGates[ pLib->nGates++ ] = pGate;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super2_LibStop( Super2_Lib_t * pLib )
+{
+ free( pLib->pGates );
+ free( pLib );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the starting supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs )
+{
+ Super2_Lib_t * pLib;
+ int v, m;
+
+ // start the library
+ pLib = Super2_LibStart();
+
+ // create the starting supergates
+ pLib->nInputs = nInputs;
+ pLib->nMints = (1 << nInputs);
+ pLib->nLevels = 0;
+ pLib->nGates = nInputs + 1;
+ pLib->nGatesAlloc = nInputs + 1;
+ pLib->uMaskBit = (1 << (pLib->nMints-1));
+ pLib->pGates = ALLOC( Super2_Gate_t *, nInputs + 1 );
+ // add the constant 0
+ pLib->pGates[0] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+ memset( pLib->pGates[0], 0, sizeof(Super2_Gate_t) );
+ // add the elementary gates
+ for ( v = 0; v < nInputs; v++ )
+ {
+ pLib->pGates[v+1] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+ memset( pLib->pGates[v+1], 0, sizeof(Super2_Gate_t) );
+ pLib->pGates[v+1]->pTwo = (Super2_Gate_t *)v;
+ }
+
+ // set up their truth tables
+ for ( m = 0; m < pLib->nMints; m++ )
+ for ( v = 0; v < nInputs; v++ )
+ if ( m & (1 << v) )
+ pLib->pGates[v+1]->uTruth |= (1 << m);
+ return pLib;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Precomputes one level of supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib )
+{
+ Super2_Lib_t * pLibNew;
+ Super2_Gate_t * pGate1, * pGate2, * pGateNew;
+ Super2_Gate_t ** ppGate;
+ unsigned Mask = SUPER_MASK(pLib->nMints);
+ unsigned uTruth, uTruthR, uTruth1, uTruth2, uTruth1c, uTruth2c;
+
+ // start the new library
+ pLibNew = Super2_LibDup( pLib );
+
+ // reset the hash table
+ stmm_free_table( pMan->tTable );
+ pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash );
+ // set the starting things into the hash table
+ Super2_LibForEachGate( pLibNew, pGate1 )
+ {
+ uTruthR = ((pGate1->uTruth & pLibNew->uMaskBit)? Mask & ~pGate1->uTruth : pGate1->uTruth);
+
+ if ( stmm_lookup( pMan->tTable, (char *)uTruthR, (char **)&pGate2 ) )
+ {
+ printf( "New gate:\n" );
+ Super2_LibWriteGate( stdout, pLibNew, pGate1 );
+ printf( "Gate in the table:\n" );
+ Super2_LibWriteGate( stdout, pLibNew, pGate2 );
+ assert( 0 );
+ }
+ stmm_insert( pMan->tTable, (char *)uTruthR, (char *)pGate1 );
+ }
+
+
+ // set the number of gates tried
+ pMan->nTried = pLibNew->nGates;
+
+ // go through the gate pairs
+ Super2_LibForEachGate( pLib, pGate1 )
+ {
+ if ( pLib->i && pLib->i % 300 == 0 )
+ {
+ printf( "Tried %5d first gates...\n", pLib->i );
+ fflush( stdout );
+ }
+
+ Super2_LibForEachGate2( pLib, pGate2 )
+ {
+ uTruth1 = pGate1->uTruth;
+ uTruth2 = pGate2->uTruth;
+ uTruth1c = Mask & ~uTruth1;
+ uTruth2c = Mask & ~uTruth2;
+
+ // none complemented
+ uTruth = uTruth1 & uTruth2;
+ uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth);
+
+ if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) )
+ {
+ pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+ pGateNew->pOne = pGate1;
+ pGateNew->pTwo = pGate2;
+ pGateNew->uTruth = uTruth;
+ *ppGate = pGateNew;
+ Super2_LibAddGate( pLibNew, pGateNew );
+ }
+
+ // one complemented
+ uTruth = uTruth1c & uTruth2;
+ uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth);
+
+ if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) )
+ {
+ pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+ pGateNew->pOne = Super2_Not(pGate1);
+ pGateNew->pTwo = pGate2;
+ pGateNew->uTruth = uTruth;
+ *ppGate = pGateNew;
+ Super2_LibAddGate( pLibNew, pGateNew );
+ }
+
+ // another complemented
+ uTruth = uTruth1 & uTruth2c;
+ uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth);
+
+ if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) )
+ {
+ pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+ pGateNew->pOne = pGate1;
+ pGateNew->pTwo = Super2_Not(pGate2);
+ pGateNew->uTruth = uTruth;
+ *ppGate = pGateNew;
+ Super2_LibAddGate( pLibNew, pGateNew );
+ }
+
+ // both complemented
+ uTruth = uTruth1c & uTruth2c;
+ uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth);
+
+ if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) )
+ {
+ pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+ pGateNew->pOne = Super2_Not(pGate1);
+ pGateNew->pTwo = Super2_Not(pGate2);
+ pGateNew->uTruth = uTruth;
+ *ppGate = pGateNew;
+ Super2_LibAddGate( pLibNew, pGateNew );
+ }
+
+ pMan->nTried += 4;
+ }
+ }
+ return pLibNew;
+}
+
+
+static unsigned s_uMaskBit;
+static unsigned s_uMaskAll;
+
+/**Function*************************************************************
+
+ Synopsis [Writes the library into the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super2_LibWrite( Super2_Lib_t * pLib )
+{
+ Super2_Gate_t * pGate;
+ FILE * pFile;
+ char FileName[100];
+ int clk;
+
+ if ( pLib->nLevels > 5 )
+ {
+ printf( "Cannot write file for %d levels.\n", pLib->nLevels );
+ return;
+ }
+
+clk = clock();
+ // sort the supergates by truth table
+ s_uMaskBit = pLib->uMaskBit;
+ s_uMaskAll = SUPER_MASK(pLib->nMints);
+ qsort( (void *)pLib->pGates, pLib->nGates, sizeof(Super2_Gate_t *),
+ (int (*)(const void *, const void *)) Super2_LibCompareGates );
+ assert( Super2_LibCompareGates( pLib->pGates, pLib->pGates + pLib->nGates - 1 ) < 0 );
+PRT( "Sorting", clock() - clk );
+
+
+ // start the file
+ sprintf( FileName, "superI%dL%d", pLib->nInputs, pLib->nLevels );
+ pFile = fopen( FileName, "w" );
+ fprintf( pFile, "# AND2/INV supergates derived on %s.\n", Extra_TimeStamp() );
+ fprintf( pFile, "# Command line: \"super2 -i %d -l %d\".\n", pLib->nInputs, pLib->nLevels );
+ fprintf( pFile, "# The number of inputs = %6d.\n", pLib->nInputs );
+ fprintf( pFile, "# The number of levels = %6d.\n", pLib->nLevels );
+ fprintf( pFile, "# The number of supergates = %6d.\n", pLib->nGates );
+ fprintf( pFile, "# The total functions = %6d.\n", (1<<(pLib->nMints-1)) );
+ fprintf( pFile, "\n" );
+ fprintf( pFile, "%6d\n", pLib->nGates );
+
+ // print the gates
+ Super2_LibForEachGate( pLib, pGate )
+ Super2_LibWriteGate( pFile, pLib, pGate );
+ fclose( pFile );
+
+ printf( "The supergates are written into file \"%s\" ", FileName );
+ printf( "(%0.2f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the gate into the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 )
+{
+ Super2_Gate_t * pG1 = *ppG1;
+ Super2_Gate_t * pG2 = *ppG2;
+ unsigned uTruth1, uTruth2;
+
+ uTruth1 = (pG1->uTruth & s_uMaskBit)? s_uMaskAll & ~pG1->uTruth : pG1->uTruth;
+ uTruth2 = (pG2->uTruth & s_uMaskBit)? s_uMaskAll & ~pG2->uTruth : pG2->uTruth;
+
+ if ( uTruth1 < uTruth2 )
+ return -1;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the gate into the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate )
+{
+// unsigned uTruthR;
+ unsigned uTruth;
+ int fInv;
+
+ // check whether the gate need complementation
+ fInv = (int)(pGate->uTruth & pLib->uMaskBit);
+ uTruth = (fInv? ~pGate->uTruth : pGate->uTruth);
+/*
+ // reverse the truth table
+ uTruthR = 0;
+ for ( m = 0; m < pLib->nMints; m++ )
+ if ( uTruth & (1 << m) )
+ uTruthR |= (1 << (pLib->nMints-1-m));
+*/
+ // write the truth table
+ Extra_PrintBinary( pFile, &uTruth, pLib->nMints );
+ fprintf( pFile, " " );
+ // write the symbolic expression
+ fprintf( pFile, "%s", Super2_LibWriteGate_rec( pGate, fInv, pLib->nLevels ) );
+ fprintf( pFile, "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively writes the gate into the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level )
+{
+ static char Buff01[ 3], Buff02[ 3]; // Max0 = 1
+ static char Buff11[ 6], Buff12[ 6]; // Max1 = 2*Max0 + 2 = 4
+ static char Buff21[ 12], Buff22[ 12]; // Max2 = 2*Max1 + 2 = 10
+ static char Buff31[ 25], Buff32[ 25]; // Max3 = 2*Max2 + 2 = 22
+ static char Buff41[ 50], Buff42[ 50]; // Max4 = 2*Max3 + 2 = 46
+ static char Buff51[100], Buff52[100]; // Max5 = 2*Max4 + 2 = 94
+ static char * pBuffs1[6] = { Buff01, Buff11, Buff21, Buff31, Buff41, Buff51 };
+ static char * pBuffs2[6] = { Buff02, Buff12, Buff22, Buff32, Buff42, Buff52 };
+ char * pBranch;
+ char * pBuffer1 = pBuffs1[Level];
+ char * pBuffer2 = pBuffs2[Level];
+ Super2_Gate_t * pGateNext1, * pGateNext2;
+ int fInvNext1, fInvNext2;
+ int RetValue;
+
+ // consider the last level
+ assert( Level >= 0 );
+ if ( pGate->pOne == NULL )
+ {
+ if ( pGate->uTruth == 0 )
+ {
+ pBuffer1[0] = (fInv? '1': '0');
+ pBuffer1[1] = '$';
+ pBuffer1[2] = 0;
+ }
+ else
+ {
+ pBuffer1[0] = (fInv? 'A' + ((int)pGate->pTwo): 'a' + ((int)pGate->pTwo));
+ pBuffer1[1] = 0;
+ }
+ return pBuffer1;
+ }
+ assert( Level > 0 );
+
+
+ // get the left branch
+ pGateNext1 = Super2_Regular(pGate->pOne);
+ fInvNext1 = Super2_IsComplement(pGate->pOne);
+ pBranch = Super2_LibWriteGate_rec(pGateNext1, fInvNext1, Level - 1);
+ // copy into Buffer1
+ strcpy( pBuffer1, pBranch );
+
+ // get the right branch
+ pGateNext2 = Super2_Regular(pGate->pTwo);
+ fInvNext2 = Super2_IsComplement(pGate->pTwo);
+ pBranch = Super2_LibWriteGate_rec(pGateNext2, fInvNext2, Level - 1);
+
+ // consider the case when comparison is not necessary
+ if ( fInvNext1 ^ fInvNext2 )
+ {
+ if ( fInvNext1 > fInvNext2 )
+ sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') );
+ else
+ sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') );
+ }
+ else
+ {
+ // compare the two branches
+ RetValue = Super2_LibWriteCompare( pBuffer1, pBranch );
+ if ( RetValue == 1 )
+ sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') );
+ else // if ( RetValue == -1 )
+ {
+ sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') );
+ if ( RetValue == 0 )
+ printf( "Strange!\n" );
+ }
+ }
+ return pBuffer2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the two branches of the tree.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Super2_LibWriteCompare( char * pStr1, char * pStr2 )
+{
+ while ( 1 )
+ {
+ // skip extra symbols
+ while ( *pStr1 && *pStr1 < 'A' )
+ pStr1++;
+ while ( *pStr2 && *pStr2 < 'A' )
+ pStr2++;
+
+ // check if any one is finished
+ if ( *pStr1 == 0 || *pStr2 == 0 )
+ {
+ if ( *pStr2 )
+ return 1;
+ return -1;
+ }
+
+ // compare
+ if ( *pStr1 == *pStr2 )
+ {
+ pStr1++;
+ pStr2++;
+ }
+ else
+ {
+ if ( *pStr1 < *pStr2 )
+ return 1;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/super/superGENERIC.c b/src/map/super/superGENERIC.c
new file mode 100644
index 00000000..4c7b67ca
--- /dev/null
+++ b/src/map/super/superGENERIC.c
@@ -0,0 +1,46 @@
+/**CFile****************************************************************
+
+ FileName [super__.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Pre-computation of supergates.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: super__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/super/superGate.c b/src/map/super/superGate.c
new file mode 100644
index 00000000..d0cd0ad7
--- /dev/null
+++ b/src/map/super/superGate.c
@@ -0,0 +1,1324 @@
+/**CFile****************************************************************
+
+ FileName [superGate.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Pre-computation of supergates.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: superGate.c,v 1.7 2004/08/03 00:11:40 satrajit Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the bit masks
+#define SUPER_MASK(n) ((~((unsigned)0)) >> (32-(n)))
+#define SUPER_FULL (~((unsigned)0))
+#define SUPER_NO_VAR (-9999.0)
+#define SUPER_EPSILON (0.001)
+
+// data structure for supergate precomputation
+typedef struct Super_ManStruct_t_ Super_Man_t; // manager
+typedef struct Super_GateStruct_t_ Super_Gate_t; // supergate
+
+struct Super_ManStruct_t_
+{
+ // parameters
+ char * pName; // the original genlib file name
+ int nVarsMax; // the number of inputs
+ int nMints; // the number of minterms
+ int nLevels; // the number of logic levels
+ float tDelayMax; // the max delay of the supergates in the library
+ float tAreaMax; // the max area of the supergates in the library
+ int fSkipInv; // the flag says about skipping inverters
+ int fWriteOldFormat; // in addition, writes the file in the old format
+ int fVerbose;
+
+ // supergates
+ Super_Gate_t * pInputs[10]; // the input supergates
+ int nGates; // the number of gates in the library
+ Super_Gate_t ** pGates; // the gates themselves
+ stmm_table * tTable; // mapping of truth tables into gates
+
+ // memory managers
+ Extra_MmFixed_t * pMem; // memory manager for the supergates
+ Extra_MmFlex_t * pMemFlex; // memory manager for the fanin arrays
+
+ // statistics
+ int nTried; // the total number of tried
+ int nAdded; // the number of entries added
+ int nRemoved; // the number of entries removed
+ int nUnique; // the number of unique gates
+ int nLookups; // the number of hash table lookups
+ int nAliases; // the number of hash table lookups thrown away due to aliasing
+
+ // runtime
+ int Time; // the runtime of the generation procedure
+ int TimeLimit; // the runtime limit (in seconds)
+ int TimeSec; // the time passed (in seconds)
+ int TimeStop; // the time to stop computation (in miliseconds)
+ int TimePrint; // the time to print message
+};
+
+struct Super_GateStruct_t_
+{
+ Mio_Gate_t * pRoot; // the root gate for this supergate
+ unsigned fVar : 1; // the flag signaling the elementary variable
+ unsigned fSuper : 1; // the flag signaling the elementary variable
+ unsigned nFanins : 6; // the number of fanin gates
+ unsigned Number : 24; // the number assigned in the process
+ unsigned uTruth[2]; // the truth table of this supergate
+ Super_Gate_t * pFanins[6]; // the fanins of the gate
+ float Area; // the area of this gate
+ float ptDelays[6]; // the pin-to-pin delays for all inputs
+ float tDelayMax; // the maximum delay
+ Super_Gate_t * pNext; // the next gate in the table
+};
+
+
+// iterating through the gates in the library
+#define Super_ManForEachGate( GateArray, Limit, Index, Gate ) \
+ for ( Index = 0; \
+ Index < Limit && (Gate = GateArray[Index]); \
+ Index++ )
+
+// static functions
+static Super_Man_t * Super_ManStart();
+static void Super_ManStop( Super_Man_t * pMan );
+
+static void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate );
+static void Super_First( Super_Man_t * pMan, int nVarsMax );
+static Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, bool fSkipInv );
+static Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins );
+static bool Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins );
+static int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 );
+static int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 );
+static void Super_TranferGatesToArray( Super_Man_t * pMan );
+static int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan );
+
+static void Super_Write( Super_Man_t * pMan );
+static int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 );
+static void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile );
+
+static void Super_WriteLibrary( Super_Man_t * pMan );
+static void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num );
+static char * Super_WriteLibraryGateName( Super_Gate_t * pGate );
+static void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer );
+
+static void Super_WriteLibraryTree( Super_Man_t * pMan );
+static void Super_WriteLibraryTree_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Precomputes the library of supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, float tDelayMax, float tAreaMax, int TimeLimit, bool fSkipInv, bool fWriteOldFormat, int fVerbose )
+{
+ Super_Man_t * pMan;
+ Mio_Gate_t ** ppGates;
+ int nGates, Level, clk, clockStart;
+
+ assert( nVarsMax < 7 );
+
+ // get the root gates
+ ppGates = Mio_CollectRoots( pLibGen, nVarsMax, tDelayMax, 0, &nGates );
+
+ // start the manager
+ pMan = Super_ManStart();
+ pMan->pName = Mio_LibraryReadName(pLibGen);
+ pMan->fSkipInv = fSkipInv;
+ pMan->tDelayMax = tDelayMax;
+ pMan->tAreaMax = tAreaMax;
+ pMan->TimeLimit = TimeLimit; // in seconds
+ pMan->TimeStop = TimeLimit * CLOCKS_PER_SEC + clock(); // in CPU ticks
+ pMan->fWriteOldFormat = fWriteOldFormat;
+ pMan->fVerbose = fVerbose;
+
+ if ( nGates == 0 )
+ {
+ fprintf( stderr, "Error: No genlib gates satisfy the limits criteria. Stop.\n");
+ fprintf( stderr, "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n",
+ pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit );
+
+ // stop the manager
+ Super_ManStop( pMan );
+ free( ppGates );
+
+ return;
+ }
+
+ // get the starting supergates
+ Super_First( pMan, nVarsMax );
+
+ // perform the computation of supergates
+ clockStart = clock();
+if ( fVerbose )
+{
+ printf( "Computing supergates with %d inputs and %d levels.\n",
+ pMan->nVarsMax, nLevels );
+ printf( "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n",
+ pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit );
+}
+
+ for ( Level = 1; Level <= nLevels; Level++ )
+ {
+ if ( clock() > pMan->TimeStop )
+ break;
+clk = clock();
+ Super_Compute( pMan, ppGates, nGates, fSkipInv );
+ pMan->nLevels = Level;
+if ( fVerbose )
+{
+ printf( "Lev %d: Try =%12d. Add =%6d. Rem =%5d. Save =%6d. Lookups =%12d. Aliases =%12d. ",
+ Level, pMan->nTried, pMan->nAdded, pMan->nRemoved, pMan->nAdded - pMan->nRemoved, pMan->nLookups, pMan->nAliases );
+PRT( "Time", clock() - clk );
+fflush( stdout );
+}
+ }
+ pMan->Time = clock() - clockStart;
+
+if ( fVerbose )
+{
+printf( "Writing the output file...\n" );
+fflush( stdout );
+}
+ // write them into a file
+ Super_Write( pMan );
+
+ // stop the manager
+ Super_ManStop( pMan );
+ free( ppGates );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the starting supergates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_First( Super_Man_t * pMan, int nVarsMax )
+{
+ Super_Gate_t * pSuper;
+ int nMintLimit, nVarLimit;
+ int v, m;
+ // set the parameters
+ pMan->nVarsMax = nVarsMax;
+ pMan->nMints = (1 << nVarsMax);
+ pMan->nLevels = 0;
+ // allocate room for the gates
+ pMan->nGates = nVarsMax;
+ pMan->pGates = ALLOC( Super_Gate_t *, nVarsMax + 2 );
+ // create the gates corresponding to the elementary variables
+ for ( v = 0; v < nVarsMax; v++ )
+ {
+ // get a new gate
+ pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+ memset( pSuper, 0, sizeof(Super_Gate_t) );
+ // assign the elementary variable, the truth table, and the delays
+ pSuper->fVar = 1;
+ pSuper->Number = v;
+ for ( m = 0; m < nVarsMax; m++ )
+ pSuper->ptDelays[m] = SUPER_NO_VAR;
+ pSuper->ptDelays[v] = 0.0;
+ // set the gate
+ pMan->pGates[v] = pSuper;
+ Super_AddGateToTable( pMan, pSuper );
+ pMan->pInputs[v] = pSuper;
+ }
+ // set up their truth tables
+ nVarLimit = (nVarsMax >= 5)? 5 : nVarsMax;
+ nMintLimit = (1 << nVarLimit);
+ for ( m = 0; m < nMintLimit; m++ )
+ for ( v = 0; v < nVarLimit; v++ )
+ if ( m & (1 << v) )
+ pMan->pGates[v]->uTruth[0] |= (1 << m);
+ // make adjustments for the case of 6 variables
+ if ( nVarsMax == 6 )
+ {
+ for ( v = 0; v < 5; v++ )
+ pMan->pGates[v]->uTruth[1] = pMan->pGates[v]->uTruth[0];
+ pMan->pGates[5]->uTruth[0] = 0;
+ pMan->pGates[5]->uTruth[1] = ~((unsigned)0);
+ }
+ else
+ {
+ for ( v = 0; v < nVarsMax; v++ )
+ pMan->pGates[v]->uTruth[1] = 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Precomputes one level of supergates.]
+
+ Description [This procedure computes the set of supergates that can be
+ derived from the given set of root gates (from GENLIB library) by composing
+ the root gates with the currently available supergates. This procedure is
+ smart in the sense that it tries to avoid useless emuration by imposing
+ tight bounds by area and delay. Only the supergates and are guaranteed to
+ have smaller area and delay are enumereated. See comments below for details.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, bool fSkipInv )
+{
+ Super_Gate_t * pSupers[6], * pGate0, * pGate1, * pGate2, * pGate3, * pGate4, * pGate5, * pGateNew;
+ float tPinDelaysRes[6], * ptPinDelays[6], tPinDelayMax, tDelayMio;
+ float Area, Area0, Area1, Area2, Area3, Area4, AreaMio;
+ unsigned uTruth[2], uTruths[6][2];
+ int i0, i1, i2, i3, i4, i5;
+ Super_Gate_t ** ppGatesLimit;
+ int nFanins, nGatesLimit, k, s, t;
+ ProgressBar * pProgress;
+ int fTimeOut;
+ int fPrune = 1; // Shall we prune?
+ int iPruneLimit = 3; // Each of the gates plugged into the root gate will have
+ // less than these many fanins
+ int iPruneLimitRoot = 4; // The root gate may have only less than these many fanins
+
+ // put the gates from the unique table into the array
+ // the gates from the array will be used to compose other gates
+ // the gates in tbe table are used to check uniqueness of collected gates
+ Super_TranferGatesToArray( pMan );
+
+ // sort the gates in the increasing order of maximum delay
+ if ( pMan->nGates > 10000 )
+ {
+ printf( "Sorting array of %d supergates...\r", pMan->nGates );
+ fflush( stdout );
+ }
+ qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *),
+ (int (*)(const void *, const void *)) Super_DelayCompare );
+ assert( Super_DelayCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 );
+ if ( pMan->nGates > 10000 )
+ {
+ printf( " \r" );
+ }
+
+ pProgress = Extra_ProgressBarStart( stdout, pMan->TimeLimit );
+ pMan->TimePrint = clock() + CLOCKS_PER_SEC;
+ ppGatesLimit = ALLOC( Super_Gate_t *, pMan->nGates );
+ // go through the root gates
+ // the root gates are sorted in the increasing gelay
+ fTimeOut = 0;
+ for ( k = 0; k < nGates; k++ )
+ {
+ if ( fTimeOut ) break;
+
+ if ( fPrune )
+ {
+ if ( pMan->nLevels >= 1 ) // First level gates have been computed
+ {
+ if ( Mio_GateReadInputs(ppGates[k]) >= iPruneLimitRoot )
+ continue;
+ }
+ }
+
+ // select the subset of gates to be considered with this root gate
+ // all the gates past this point will lead to delay larger than the limit
+ tDelayMio = (float)Mio_GateReadDelayMax(ppGates[k]);
+ for ( s = 0, t = 0; s < pMan->nGates; s++ )
+ {
+ if ( fPrune && ( pMan->nLevels >= 1 ) && ( ((int)pMan->pGates[s]->nFanins) >= iPruneLimit ))
+ continue;
+
+ ppGatesLimit[t] = pMan->pGates[s];
+ if ( ppGatesLimit[t++]->tDelayMax + tDelayMio > pMan->tDelayMax )
+ break;
+ }
+ nGatesLimit = t;
+
+ if ( pMan->fVerbose )
+ {
+ printf ("Trying %d choices for %d inputs\n", t, Mio_GateReadInputs(ppGates[k]) );
+ }
+
+ // resort part of this range by area
+ // now we can prune the search by going up in the list until we reach the limit on area
+ // all the gates beyond this point can be skipped because their area can be only larger
+ if ( nGatesLimit > 10000 )
+ printf( "Sorting array of %d supergates...\r", nGatesLimit );
+ qsort( (void *)ppGatesLimit, nGatesLimit, sizeof(Super_Gate_t *),
+ (int (*)(const void *, const void *)) Super_AreaCompare );
+ assert( Super_AreaCompare( ppGatesLimit, ppGatesLimit + nGatesLimit - 1 ) <= 0 );
+ if ( nGatesLimit > 10000 )
+ printf( " \r" );
+
+ // consider the combinations of gates with the root gate on top
+ AreaMio = (float)Mio_GateReadArea(ppGates[k]);
+ nFanins = Mio_GateReadInputs(ppGates[k]);
+ switch ( nFanins )
+ {
+ case 0: // should not happen
+ assert( 0 );
+ break;
+ case 1: // interter root
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+ {
+ if ( fTimeOut ) break;
+ fTimeOut = Super_CheckTimeout( pProgress, pMan );
+ // skip the inverter as the root gate before the elementary variable
+ // as a result, the supergates will not have inverters on the input side
+ // but inverters still may occur at the output of or inside complex supergates
+ if ( fSkipInv && pGate0->tDelayMax == 0 )
+ continue;
+ // compute area
+ Area = AreaMio + pGate0->Area;
+ if ( Area > pMan->tAreaMax )
+ break;
+
+ pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays;
+ Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+ Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+ if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+ continue;
+ // create a new gate
+ pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+ Super_AddGateToTable( pMan, pGateNew );
+ }
+ break;
+ case 2: // two-input root gate
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+ {
+ Area0 = AreaMio + pGate0->Area;
+ if ( Area0 > pMan->tAreaMax )
+ break;
+ pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays;
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+ if ( i1 != i0 )
+ {
+ if ( fTimeOut ) goto done;
+ fTimeOut = Super_CheckTimeout( pProgress, pMan );
+ // compute area
+ Area = Area0 + pGate1->Area;
+ if ( Area > pMan->tAreaMax )
+ break;
+
+ pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays;
+ Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+ Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+ if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+ continue;
+ // create a new gate
+ pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+ Super_AddGateToTable( pMan, pGateNew );
+ }
+ }
+ break;
+ case 3: // three-input root gate
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+ {
+ Area0 = AreaMio + pGate0->Area;
+ if ( Area0 > pMan->tAreaMax )
+ break;
+ pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+ if ( i1 != i0 )
+ {
+ Area1 = Area0 + pGate1->Area;
+ if ( Area1 > pMan->tAreaMax )
+ break;
+ pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 )
+ if ( i2 != i0 && i2 != i1 )
+ {
+ if ( fTimeOut ) goto done;
+ fTimeOut = Super_CheckTimeout( pProgress, pMan );
+ // compute area
+ Area = Area1 + pGate2->Area;
+ if ( Area > pMan->tAreaMax )
+ break;
+ pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays;
+
+ Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+ Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+ if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+ continue;
+ // create a new gate
+ pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+ Super_AddGateToTable( pMan, pGateNew );
+ }
+ }
+ }
+ break;
+ case 4: // four-input root gate
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+ {
+ Area0 = AreaMio + pGate0->Area;
+ if ( Area0 > pMan->tAreaMax )
+ break;
+ pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+ if ( i1 != i0 )
+ {
+ Area1 = Area0 + pGate1->Area;
+ if ( Area1 > pMan->tAreaMax )
+ break;
+ pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 )
+ if ( i2 != i0 && i2 != i1 )
+ {
+ Area2 = Area1 + pGate2->Area;
+ if ( Area2 > pMan->tAreaMax )
+ break;
+ pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 )
+ if ( i3 != i0 && i3 != i1 && i3 != i2 )
+ {
+ if ( fTimeOut ) goto done;
+ fTimeOut = Super_CheckTimeout( pProgress, pMan );
+ // compute area
+ Area = Area2 + pGate3->Area;
+ if ( Area > pMan->tAreaMax )
+ break;
+ pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays;
+
+ Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+ Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+ if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+ continue;
+ // create a new gate
+ pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+ Super_AddGateToTable( pMan, pGateNew );
+ }
+ }
+ }
+ }
+ break;
+ case 5: // five-input root gate
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+ {
+ Area0 = AreaMio + pGate0->Area;
+ if ( Area0 > pMan->tAreaMax )
+ break;
+ pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+ if ( i1 != i0 )
+ {
+ Area1 = Area0 + pGate1->Area;
+ if ( Area1 > pMan->tAreaMax )
+ break;
+ pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 )
+ if ( i2 != i0 && i2 != i1 )
+ {
+ Area2 = Area1 + pGate2->Area;
+ if ( Area2 > pMan->tAreaMax )
+ break;
+ pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 )
+ if ( i3 != i0 && i3 != i1 && i3 != i2 )
+ {
+ Area3 = Area2 + pGate3->Area;
+ if ( Area3 > pMan->tAreaMax )
+ break;
+ pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 )
+ if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 )
+ {
+ if ( fTimeOut ) goto done;
+ fTimeOut = Super_CheckTimeout( pProgress, pMan );
+ // compute area
+ Area = Area3 + pGate4->Area;
+ if ( Area > pMan->tAreaMax )
+ break;
+ pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays;
+
+ Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+ Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+ if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+ continue;
+ // create a new gate
+ pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+ Super_AddGateToTable( pMan, pGateNew );
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 6: // six-input root gate
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 )
+ {
+ Area0 = AreaMio + pGate0->Area;
+ if ( Area0 > pMan->tAreaMax )
+ break;
+ pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 )
+ if ( i1 != i0 )
+ {
+ Area1 = Area0 + pGate1->Area;
+ if ( Area1 > pMan->tAreaMax )
+ break;
+ pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 )
+ if ( i2 != i0 && i2 != i1 )
+ {
+ Area2 = Area1 + pGate2->Area;
+ if ( Area2 > pMan->tAreaMax )
+ break;
+ pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 )
+ if ( i3 != i0 && i3 != i1 && i3 != i2 )
+ {
+ Area3 = Area2 + pGate3->Area;
+ if ( Area3 > pMan->tAreaMax )
+ break;
+ pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 )
+ if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 )
+ {
+ if ( fTimeOut ) break;
+ fTimeOut = Super_CheckTimeout( pProgress, pMan );
+ // compute area
+ Area4 = Area3 + pGate4->Area;
+ if ( Area > pMan->tAreaMax )
+ break;
+ pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays;
+
+ Super_ManForEachGate( ppGatesLimit, nGatesLimit, i5, pGate5 )
+ if ( i5 != i0 && i5 != i1 && i5 != i2 && i5 != i3 && i5 != i4 )
+ {
+ if ( fTimeOut ) goto done;
+ fTimeOut = Super_CheckTimeout( pProgress, pMan );
+ // compute area
+ Area = Area4 + pGate5->Area;
+ if ( Area > pMan->tAreaMax )
+ break;
+ pSupers[5] = pGate5; uTruths[5][0] = pGate5->uTruth[0]; uTruths[5][1] = pGate5->uTruth[1]; ptPinDelays[5] = pGate5->ptDelays;
+
+ Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax );
+ Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth );
+ if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) )
+ continue;
+ // create a new gate
+ pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax );
+ Super_AddGateToTable( pMan, pGateNew );
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ default :
+ assert( 0 );
+ break;
+ }
+ }
+done:
+ Extra_ProgressBarStop( pProgress );
+ free( ppGatesLimit );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers gates from table into the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan )
+{
+ int TimeNow = clock();
+ if ( TimeNow > pMan->TimePrint )
+ {
+ Extra_ProgressBarUpdate( pPro, ++pMan->TimeSec, NULL );
+ pMan->TimePrint = clock() + CLOCKS_PER_SEC;
+ }
+ if ( TimeNow > pMan->TimeStop )
+ {
+ printf ("Timeout!\n");
+ return 1;
+ }
+ pMan->nTried++;
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers gates from table into the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_TranferGatesToArray( Super_Man_t * pMan )
+{
+ stmm_generator * gen;
+ Super_Gate_t * pGate, * pList;
+ unsigned Key;
+
+ // put the gates fron the table into the array
+ free( pMan->pGates );
+ pMan->pGates = ALLOC( Super_Gate_t *, pMan->nAdded );
+ pMan->nGates = 0;
+ stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pList )
+ {
+ for ( pGate = pList; pGate; pGate = pGate->pNext )
+ pMan->pGates[ pMan->nGates++ ] = pGate;
+ }
+// assert( pMan->nGates == pMan->nAdded - pMan->nRemoved );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one supergate into the unique table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate )
+{
+ Super_Gate_t ** ppList;
+ unsigned Key;
+// Key = pGate->uTruth[0] + 2003 * pGate->uTruth[1];
+ Key = pGate->uTruth[0] ^ pGate->uTruth[1];
+ if ( !stmm_find_or_add( pMan->tTable, (char *)Key, (char ***)&ppList ) )
+ *ppList = NULL;
+ pGate->pNext = *ppList;
+ *ppList = pGate;
+ pMan->nAdded++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check the manager's unique table for comparable gates.]
+
+ Description [Returns 0 if the gate is dominated by others. Returns 1
+ if the gate is new or is better than the available ones. In this case,
+ cleans the table by removing the gates that are worse than the given one.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins )
+{
+ Super_Gate_t ** ppList, * pPrev, * pGate, * pGate2;
+ int i, fNewIsBetter, fGateIsBetter;
+ unsigned Key;
+
+ // skip constant functions
+ if ( pMan->nVarsMax < 6 )
+ {
+ if ( uTruth[0] == 0 || ~uTruth[0] == 0 )
+ return 0;
+ }
+ else
+ {
+ if ( ( uTruth[0] == 0 && uTruth[1] == 0 ) || ( ~uTruth[0] == 0 && ~uTruth[1] == 0 ) )
+ return 0;
+ }
+
+ // get hold of the place where the entry is stored
+// Key = uTruth[0] + 2003 * uTruth[1];
+ Key = uTruth[0] ^ uTruth[1];
+ if ( !stmm_find( pMan->tTable, (char *)Key, (char ***)&ppList ) )
+ return 1;
+ // the entry with this truth table is found
+ pPrev = NULL;
+ for ( pGate = *ppList, pGate2 = pGate? pGate->pNext: NULL; pGate;
+ pGate = pGate2, pGate2 = pGate? pGate->pNext: NULL )
+ {
+ pMan->nLookups++;
+ if ( pGate->uTruth[0] != uTruth[0] || pGate->uTruth[1] != uTruth[1] )
+ {
+ pMan->nAliases++;
+ continue;
+ }
+ fGateIsBetter = 0;
+ fNewIsBetter = 0;
+ if ( pGate->Area + SUPER_EPSILON < Area )
+ fGateIsBetter = 1;
+ else if ( pGate->Area > Area + SUPER_EPSILON )
+ fNewIsBetter = 1;
+ for ( i = 0; i < nPins; i++ )
+ {
+ if ( pGate->ptDelays[i] == SUPER_NO_VAR || tPinDelaysRes[i] == SUPER_NO_VAR )
+ continue;
+ if ( pGate->ptDelays[i] + SUPER_EPSILON < tPinDelaysRes[i] )
+ fGateIsBetter = 1;
+ else if ( pGate->ptDelays[i] > tPinDelaysRes[i] + SUPER_EPSILON )
+ fNewIsBetter = 1;
+ if ( fGateIsBetter && fNewIsBetter )
+ break;
+ }
+ // consider 4 cases
+ if ( fGateIsBetter && fNewIsBetter ) // Pareto points; save both
+ pPrev = pGate;
+ else if ( fNewIsBetter ) // gate is worse; remove the gate
+ {
+ if ( pPrev == NULL )
+ *ppList = pGate->pNext;
+ else
+ pPrev->pNext = pGate->pNext;
+ Extra_MmFixedEntryRecycle( pMan->pMem, (char *)pGate );
+ pMan->nRemoved++;
+ }
+ else if ( fGateIsBetter ) // new is worse, already dominated no need to see others
+ return 0;
+ else // if ( !fGateIsBetter && !fNewIsBetter ) // they are identical, no need to see others
+ return 0;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Create a new supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers,
+ unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins )
+{
+ Super_Gate_t * pSuper;
+ pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem );
+ memset( pSuper, 0, sizeof(Super_Gate_t) );
+ pSuper->pRoot = pRoot;
+ pSuper->uTruth[0] = uTruth[0];
+ pSuper->uTruth[1] = uTruth[1];
+ memcpy( pSuper->ptDelays, tPinDelaysRes, sizeof(float) * nPins );
+ pSuper->Area = Area;
+ pSuper->nFanins = nSupers;
+ memcpy( pSuper->pFanins, pSupers, sizeof(Super_Gate_t *) * nSupers );
+ pSuper->pNext = NULL;
+ pSuper->tDelayMax = tDelayMax;
+ return pSuper;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Super_Man_t * Super_ManStart()
+{
+ Super_Man_t * pMan;
+ pMan = ALLOC( Super_Man_t, 1 );
+ memset( pMan, 0, sizeof(Super_Man_t) );
+ pMan->pMem = Extra_MmFixedStart( sizeof(Super_Gate_t) );
+ pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash );
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_ManStop( Super_Man_t * pMan )
+{
+ Extra_MmFixedStop( pMan->pMem, 0 );
+ if ( pMan->tTable ) stmm_free_table( pMan->tTable );
+ FREE( pMan->pGates );
+ free( pMan );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Writes the supergate library into the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_Write( Super_Man_t * pMan )
+{
+ Super_Gate_t * pGateRoot, * pGate;
+ stmm_generator * gen;
+ int fZeroFound, clk, v;
+ unsigned Key;
+
+ if ( pMan->nGates < 1 )
+ {
+ printf( "The generated library is empty. No output file written.\n" );
+ return;
+ }
+
+ // Filters the supergates by removing those that have fewer inputs than
+ // the given limit, provided that the inputs are not consequtive.
+ // For example, NAND2(a,c) is removed, but NAND2(a,b) is left,
+ // because a and b are consequtive.
+ FREE( pMan->pGates );
+ pMan->pGates = ALLOC( Super_Gate_t *, pMan->nAdded );
+ pMan->nGates = 0;
+ stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pGateRoot )
+ {
+ for ( pGate = pGateRoot; pGate; pGate = pGate->pNext )
+ {
+ // skip the elementary variables
+ if ( pGate->pRoot == NULL )
+ continue;
+ // skip the non-consequtive gates
+ fZeroFound = 0;
+ for ( v = 0; v < pMan->nVarsMax; v++ )
+ if ( pGate->ptDelays[v] < SUPER_NO_VAR + SUPER_EPSILON )
+ fZeroFound = 1;
+ else if ( fZeroFound )
+ break;
+ if ( v < pMan->nVarsMax )
+ continue;
+ // save the unique gate
+ pMan->pGates[ pMan->nGates++ ] = pGate;
+ }
+ }
+
+clk = clock();
+ // sort the supergates by truth table
+ qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *),
+ (int (*)(const void *, const void *)) Super_WriteCompare );
+ assert( Super_WriteCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 );
+if ( pMan->fVerbose )
+{
+PRT( "Sorting", clock() - clk );
+}
+
+
+ // write library in the old format
+clk = clock();
+ if ( pMan->fWriteOldFormat )
+ Super_WriteLibrary( pMan );
+if ( pMan->fVerbose )
+{
+PRT( "Writing old format", clock() - clk );
+}
+
+ // write the tree-like structure of supergates
+clk = clock();
+ Super_WriteLibraryTree( pMan );
+if ( pMan->fVerbose )
+{
+PRT( "Writing new format", clock() - clk );
+}
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Writes the file header.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile )
+{
+ fprintf( pFile, "#\n" );
+ fprintf( pFile, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() );
+ fprintf( pFile, "#\n" );
+ fprintf( pFile, "# Command line: \"super -i %d -l %d -d %.2f -a %.2f -t %d %s %s\".\n",
+ pMan->nVarsMax, pMan->nLevels, pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit, (pMan->fSkipInv? "" : "-s"), pMan->pName );
+ fprintf( pFile, "#\n" );
+ fprintf( pFile, "# The number of inputs = %10d.\n", pMan->nVarsMax );
+ fprintf( pFile, "# The number of levels = %10d.\n", pMan->nLevels );
+ fprintf( pFile, "# The maximum delay = %10.2f.\n", pMan->tDelayMax );
+ fprintf( pFile, "# The maximum area = %10.2f.\n", pMan->tAreaMax );
+ fprintf( pFile, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit );
+ fprintf( pFile, "#\n" );
+ fprintf( pFile, "# The number of attempts = %10d.\n", pMan->nTried );
+ fprintf( pFile, "# The number of supergates = %10d.\n", pMan->nGates );
+ fprintf( pFile, "# The number of functions = %10d.\n", pMan->nUnique );
+ fprintf( pFile, "# The total functions = %.0f (2^%d).\n", pow(2,pMan->nMints), pMan->nMints );
+ fprintf( pFile, "#\n" );
+ fprintf( pFile, "# Generation time (sec) = %10.2f.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pFile, "#\n" );
+ fprintf( pFile, "%s\n", pMan->pName );
+ fprintf( pFile, "%d\n", pMan->nVarsMax );
+ fprintf( pFile, "%d\n", pMan->nGates );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the truth tables of two gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 )
+{
+ unsigned * pTruth1 = (*ppG1)->uTruth;
+ unsigned * pTruth2 = (*ppG2)->uTruth;
+ if ( pTruth1[1] < pTruth2[1] )
+ return -1;
+ if ( pTruth1[1] > pTruth2[1] )
+ return 1;
+ if ( pTruth1[0] < pTruth2[0] )
+ return -1;
+ if ( pTruth1[0] > pTruth2[0] )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the max delay of two gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 )
+{
+ if ( (*ppG1)->tDelayMax < (*ppG2)->tDelayMax )
+ return -1;
+ if ( (*ppG1)->tDelayMax > (*ppG2)->tDelayMax )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the area of two gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 )
+{
+ if ( (*ppG1)->Area < (*ppG2)->Area )
+ return -1;
+ if ( (*ppG1)->Area > (*ppG2)->Area )
+ return 1;
+ return 0;
+}
+
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Writes the gates into the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_WriteLibrary( Super_Man_t * pMan )
+{
+ Super_Gate_t * pGate, * pGateNext;
+ FILE * pFile;
+ char FileName[100];
+ char * pNameGeneric;
+ int i, Counter;
+
+ // get the file name
+ pNameGeneric = Extra_FileNameGeneric( pMan->pName );
+ sprintf( FileName, "%s.super_old", pNameGeneric );
+ free( pNameGeneric );
+
+ // count the number of unique functions
+ pMan->nUnique = 1;
+ Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate )
+ {
+ if ( i == pMan->nGates - 1 )
+ break;
+ // print the newline if this gate is different from the following one
+ pGateNext = pMan->pGates[i+1];
+ if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] )
+ pMan->nUnique++;
+ }
+
+ // start the file
+ pFile = fopen( FileName, "w" );
+ Super_WriteFileHeader( pMan, pFile );
+
+ // print the gates
+ Counter = 0;
+ Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate )
+ {
+ Super_WriteLibraryGate( pFile, pMan, pGate, ++Counter );
+ if ( i == pMan->nGates - 1 )
+ break;
+ // print the newline if this gate is different from the following one
+ pGateNext = pMan->pGates[i+1];
+ if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] )
+ fprintf( pFile, "\n" );
+ }
+ assert( Counter == pMan->nGates );
+ fclose( pFile );
+
+if ( pMan->fVerbose )
+{
+ printf( "The supergates are written using old format \"%s\" ", FileName );
+ printf( "(%0.3f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) );
+}
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the supergate into the file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num )
+{
+ int i;
+ fprintf( pFile, "%04d ", Num ); // the number
+ Extra_PrintBinary( pFile, pGate->uTruth, pMan->nMints ); // the truth table
+ fprintf( pFile, " %5.2f", pGate->tDelayMax ); // the max delay
+ fprintf( pFile, " " );
+ for ( i = 0; i < pMan->nVarsMax; i++ ) // the pin-to-pin delays
+ fprintf( pFile, " %5.2f", pGate->ptDelays[i]==SUPER_NO_VAR? 0.0 : pGate->ptDelays[i] );
+ fprintf( pFile, " %5.2f", pGate->Area ); // the area
+ fprintf( pFile, " " );
+ fprintf( pFile, "%s", Super_WriteLibraryGateName(pGate) ); // the symbolic expression
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively generates symbolic name of the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Super_WriteLibraryGateName( Super_Gate_t * pGate )
+{
+ static char Buffer[2000];
+ Buffer[0] = 0;
+ Super_WriteLibraryGateName_rec( pGate, Buffer );
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively generates symbolic name of the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer )
+{
+ char Buffer[10];
+ int i;
+
+ if ( pGate->pRoot == NULL )
+ {
+ sprintf( Buffer, "%c", 'a' + pGate->Number );
+ strcat( pBuffer, Buffer );
+ return;
+ }
+ strcat( pBuffer, Mio_GateReadName(pGate->pRoot) );
+ strcat( pBuffer, "(" );
+ for ( i = 0; i < (int)pGate->nFanins; i++ )
+ {
+ if ( i )
+ strcat( pBuffer, "," );
+ Super_WriteLibraryGateName_rec( pGate->pFanins[i], pBuffer );
+ }
+ strcat( pBuffer, ")" );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively writes the gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_WriteLibraryTree( Super_Man_t * pMan )
+{
+ Super_Gate_t * pSuper;
+ FILE * pFile;
+ char FileName[100];
+ char * pNameGeneric;
+ int i, Counter;
+ int posStart;
+
+ // get the file name
+ pNameGeneric = Extra_FileNameGeneric( pMan->pName );
+ sprintf( FileName, "%s.super", pNameGeneric );
+ free( pNameGeneric );
+
+ // write the elementary variables
+ pFile = fopen( FileName, "w" );
+ Super_WriteFileHeader( pMan, pFile );
+ // write the place holder for the number of lines
+ posStart = ftell( pFile );
+ fprintf( pFile, " \n" );
+ // mark the real supergates
+ Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper )
+ pSuper->fSuper = 1;
+ // write the supergates
+ Counter = pMan->nVarsMax;
+ Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper )
+ Super_WriteLibraryTree_rec( pFile, pMan, pSuper, &Counter );
+ fclose( pFile );
+ // write the number of lines
+ pFile = fopen( FileName, "rb+" );
+ fseek( pFile, posStart, SEEK_SET );
+ fprintf( pFile, "%d", Counter );
+ fclose( pFile );
+
+if ( pMan->fVerbose )
+{
+ printf( "The supergates are written using new format \"%s\" ", FileName );
+ printf( "(%0.3f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) );
+}
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively writes the gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Super_WriteLibraryTree_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter )
+{
+ int nFanins, i;
+ // skip an elementary variable and a gate that was already written
+ if ( pSuper->fVar || pSuper->Number > 0 )
+ return;
+ // write the fanins
+ nFanins = Mio_GateReadInputs(pSuper->pRoot);
+ for ( i = 0; i < nFanins; i++ )
+ Super_WriteLibraryTree_rec( pFile, pMan, pSuper->pFanins[i], pCounter );
+ // finally write the gate
+ pSuper->Number = (*pCounter)++;
+ fprintf( pFile, "%s", pSuper->fSuper? "* " : "" );
+ fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) );
+ for ( i = 0; i < nFanins; i++ )
+ fprintf( pFile, " %d", pSuper->pFanins[i]->Number );
+ // write the formula
+ // this step is optional, the resulting library will work in any case
+ // however, it may be helpful to for debugging to compare the same library
+ // written in the old format and written in the new format with formulas
+// fprintf( pFile, " # %s", Super_WriteLibraryGateName( pSuper ) );
+ fprintf( pFile, "\n" );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/super/superInt.h b/src/map/super/superInt.h
new file mode 100644
index 00000000..686c8739
--- /dev/null
+++ b/src/map/super/superInt.h
@@ -0,0 +1,62 @@
+/**CFile****************************************************************
+
+ FileName [superInt.h]
+
+ PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
+
+ Synopsis [Pre-computation of supergates.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: superInt.h,v 1.4 2004/07/06 04:55:59 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __super_INT_H__
+#define __super_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abc.h"
+#include "mainInt.h"
+#include "mvc.h"
+#include "mio.h"
+#include "stmm.h"
+#include "super.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== superAnd.c =============================================================*/
+extern void Super2_Precompute( int nInputs, int nLevels, int fVerbose );
+/*=== superGate.c =============================================================*/
+extern void Super_Precompute( Mio_Library_t * pLibGen, int nInputs, int nLevels, float tDelayMax, float tAreaMax, int TimeLimit, bool fSkipInv, bool fWriteOldFormat, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/src/map/super/superWrite.c b/src/map/super/superWrite.c
new file mode 100644
index 00000000..a0e85604
--- /dev/null
+++ b/src/map/super/superWrite.c
@@ -0,0 +1,76 @@
+/**CFile****************************************************************
+
+ FileName [superWrite.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Pre-computation of supergates.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 8, 2003.]
+
+ Revision [$Id: superWrite.c,v 1.1 2004/04/03 01:36:45 alanmi Exp $]
+
+***********************************************************************/
+
+#include "superInt.h"
+
+/*
+ One record in the supergate library file consists of:
+
+ <gate_number> <truth_table> <delay_max> <pin-to-pin-delays> <area> <gate_formula>
+
+ <gate_number> is a zero-based integer
+ <truth_table> is a string of 2^n bits representing the value of the function for each minterm
+ <delay_max> is the maximum delay of the gate
+ <pin-to-pin-delays> is the array of n double values
+ <area> is a floating point value
+ <gate_formula> is the string representing the gate in the following format:
+ GATENAME1( GATENAME2( a, c ), GATENAME3( a, d ), ... )
+ The gate names (GATENAME1, etc) are the names as they appear in the .genlib library.
+ The primary inputs of the gates are denoted by lowercase chars 'a', 'b', etc.
+ The parantheses are mandatory for each gate, except for the wire.
+ The wire name can be omitted, so that "a" can be used instead of "**wire**( a )".
+ The spaces are optional in any position of this string.
+
+
+ The supergates are generated exhaustively from all gate combinations that
+ have the max delay lower than the delay given by the user, or until the specified time
+ limit is reached.
+
+ The supergates are stored in supergate classes by their functionality.
+ Among the gates with the equivalent functionaly only those are dropped, which are
+ dominated by at least one other gate in the class in terms of both delay and area.
+ For the definition of gate dominance see pliGenCheckDominance().
+*/
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+