From 81fae91a95b8b51d7a10d3884df92dc89eb266bf Mon Sep 17 00:00:00 2001
From: Alan Mishchenko <alanmi@berkeley.edu>
Date: Sun, 25 Feb 2007 08:01:00 -0800
Subject: Version abc70225

---
 src/aig/mem/mem.c                |   16 +
 src/aig/mem/mem.h                |    1 +
 src/base/abc/abc.h               |   20 +-
 src/base/abc/abcBlifMv.c         |  970 +++++++++++++++++++++++
 src/base/abc/abcCheck.c          |  128 +++
 src/base/abc/abcDfs.c            |    9 +-
 src/base/abc/abcFunc.c           |   16 +
 src/base/abc/abcHie.c            |  294 +------
 src/base/abc/abcLib.c            |   46 ++
 src/base/abc/abcNetlist.c        |   11 +-
 src/base/abc/abcNtk.c            |   45 +-
 src/base/abc/abcObj.c            |    9 +-
 src/base/abc/abcSop.c            |  133 ++++
 src/base/abc/abcUtil.c           |   43 --
 src/base/abc/module.make         |    1 +
 src/base/abci/abc.c              |   98 ++-
 src/base/abci/abcIf.c            |   20 +-
 src/base/abci/abcRenode.c        |   93 ++-
 src/base/cmd/cmd.c               |    6 +-
 src/base/io/io.h                 |    3 +-
 src/base/io/ioReadBlifMv.c       |  209 +++--
 src/base/io/ioReadVerilog.c      |   35 +-
 src/base/io/ioUtil.c             |  194 ++---
 src/base/io/ioWriteAiger.c       |    4 +-
 src/base/io/ioWriteBlif.c        |   16 +-
 src/base/io/ioWriteBlifMv.c      |   81 +-
 src/base/io/ioWriteDot.c         |    4 +-
 src/base/ver/ver.h               |    2 +
 src/base/ver/verCore.c           | 1583 +++++++++++++++++++++++++++++---------
 src/base/ver/verCore.zip         |  Bin 0 -> 13275 bytes
 src/base/ver/verFormula.c        |    4 +-
 src/bdd/cas/module.make          |    3 +-
 src/map/if/if.h                  |  120 +--
 src/map/if/ifCore.c              |   78 +-
 src/map/if/ifCut.c               |  145 +++-
 src/map/if/ifMan.c               |  336 ++++++--
 src/map/if/ifMap.c               |  192 ++---
 src/map/if/ifPrepro.c            |  175 -----
 src/map/if/ifReduce.c            |   16 +-
 src/map/if/ifSeq.c               |  448 +++++------
 src/map/if/ifUtil.c              |  171 +++-
 src/map/if/module.make           |    1 -
 src/map/mio/mioRead.c            |    4 +-
 src/misc/extra/extra.h           |    1 +
 src/misc/extra/extraUtilMemory.c |   18 +-
 src/misc/vec/vecStr.h            |   53 ++
 src/phys/place/libhmetis.h       |    8 +-
 47 files changed, 4091 insertions(+), 1772 deletions(-)
 create mode 100644 src/base/abc/abcBlifMv.c
 create mode 100644 src/base/ver/verCore.zip
 delete mode 100644 src/map/if/ifPrepro.c

(limited to 'src')

diff --git a/src/aig/mem/mem.c b/src/aig/mem/mem.c
index 15199755..f5bfbfd8 100644
--- a/src/aig/mem/mem.c
+++ b/src/aig/mem/mem.c
@@ -278,6 +278,22 @@ int Mem_FixedReadMemUsage( Mem_Fixed_t * p )
     return p->nMemoryAlloc;
 }
 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p )
+{
+    return p->nEntriesMax;
+}
+
 
 
 /**Function*************************************************************
diff --git a/src/aig/mem/mem.h b/src/aig/mem/mem.h
index 611c968d..d43e5fc3 100644
--- a/src/aig/mem/mem.h
+++ b/src/aig/mem/mem.h
@@ -45,6 +45,7 @@ extern char *        Mem_FixedEntryFetch( Mem_Fixed_t * p );
 extern void          Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry );
 extern void          Mem_FixedRestart( Mem_Fixed_t * p );
 extern int           Mem_FixedReadMemUsage( Mem_Fixed_t * p );
+extern int           Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p );
 // flexible-size-block memory manager
 extern Mem_Flex_t *  Mem_FlexStart();
 extern void          Mem_FlexStop( Mem_Flex_t * p, int fVerbose );
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h
index f638097f..c375a34e 100644
--- a/src/base/abc/abc.h
+++ b/src/base/abc/abc.h
@@ -316,6 +316,7 @@ static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk )        { return Ab
 static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk )        { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI );         }
 static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk )        { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO );         }
 static inline Abc_Obj_t * Abc_NtkCreateAssert( Abc_Ntk_t * pNtk )    { return Abc_NtkCreateObj( pNtk, ABC_OBJ_ASSERT );     }
+static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk )       { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );        }
 static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk )      { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE );       }
 static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk )     { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH );      }
 static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk )  { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX );   }
@@ -535,6 +536,15 @@ extern void               Abc_AigUpdateStop( Abc_Aig_t * pMan );
 extern void               Abc_AigUpdateReset( Abc_Aig_t * pMan );
 /*=== abcAttach.c ==========================================================*/
 extern int                Abc_NtkAttach( Abc_Ntk_t * pNtk );
+/*=== abcBlifMv.c ==========================================================*/
+extern void               Abc_NtkStartMvVars( Abc_Ntk_t * pNtk );
+extern void               Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk );
+extern void               Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues );
+extern Abc_Ntk_t *        Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t *        Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic );
+extern int                Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk );
+extern char *             Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 );
+extern int                Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 );
 /*=== abcBalance.c ==========================================================*/
 extern Abc_Ntk_t *        Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel );
 /*=== abcCheck.c ==========================================================*/
@@ -544,6 +554,9 @@ extern bool               Abc_NtkDoCheck( Abc_Ntk_t * pNtk );
 extern bool               Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj );
 extern bool               Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb );
 extern int                Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk );
+extern int                Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk );
+extern int                Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk );
+extern int                Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk );
 /*=== abcCollapse.c ==========================================================*/
 extern Abc_Ntk_t *        Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose );
 /*=== abcCut.c ==========================================================*/
@@ -616,6 +629,7 @@ extern void               Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk );
 extern void               Abc_LibPrint( Abc_Lib_t * pLib );
 extern int                Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk );
 extern Abc_Ntk_t *        Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName );
+extern int                Abc_LibFindTopLevelModels( Abc_Lib_t * pLib );
 extern Abc_Ntk_t *        Abc_LibDeriveRoot( Abc_Lib_t * pLib );
 /*=== abcMiter.c ==========================================================*/
 extern int                Abc_NtkMinimumBase( Abc_Ntk_t * pNtk );
@@ -682,7 +696,7 @@ extern void               Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk );
 extern void               Abc_NtkShortNames( Abc_Ntk_t * pNtk );
 /*=== abcNetlist.c ==========================================================*/
 extern Abc_Ntk_t *        Abc_NtkToLogic( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t *        Abc_NtkToNetlist( Abc_Ntk_t * pNtk, int fDirect );
+extern Abc_Ntk_t *        Abc_NtkToNetlist( Abc_Ntk_t * pNtk );
 extern Abc_Ntk_t *        Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk );
 /*=== abcNtbdd.c ==========================================================*/
 extern Abc_Ntk_t *        Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi );
@@ -783,6 +797,10 @@ extern int                Abc_SopIsExorType( char * pSop );
 extern bool               Abc_SopCheck( char * pSop, int nFanins );
 extern char *             Abc_SopFromTruthBin( char * pTruth );
 extern char *             Abc_SopFromTruthHex( char * pTruth );
+extern char *             Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues );
+extern char *             Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues );
+extern char *             Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues );
+extern char *             Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues );
 /*=== abcStrash.c ==========================================================*/
 extern Abc_Ntk_t *        Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup );
 extern Abc_Obj_t *        Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode );
diff --git a/src/base/abc/abcBlifMv.c b/src/base/abc/abcBlifMv.c
new file mode 100644
index 00000000..48ec58c0
--- /dev/null
+++ b/src/base/abc/abcBlifMv.c
@@ -0,0 +1,970 @@
+/**CFile****************************************************************
+
+  FileName    [abcBlifMv.c]
+
+  SystemName  [ABC: Logic synthesis and verification system.]
+
+  PackageName [Network and node package.]
+
+  Synopsis    [Procedures to process BLIF-MV networks and AIGs.]
+
+  Author      [Alan Mishchenko]
+  
+  Affiliation [UC Berkeley]
+
+  Date        [Ver. 1.0. Started - June 20, 2005.]
+
+  Revision    [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+///                        DECLARATIONS                              ///
+////////////////////////////////////////////////////////////////////////
+ 
+////////////////////////////////////////////////////////////////////////
+///                     FUNCTION DEFINITIONS                         ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+  Synopsis    [Starts the Mv-Var manager.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ) 
+{
+    Vec_Att_t * pAttMan;
+    assert( Abc_NtkMvVar(pNtk) == NULL );
+    pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, Extra_MmFlexStart(), Extra_MmFlexStop, NULL, NULL );
+    Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan );
+//printf( "allocing attr\n" );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Stops the Mv-Var manager.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ) 
+{ 
+    void * pUserMan;
+    pUserMan = Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 ); 
+    Extra_MmFlexStop( pUserMan );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the MV variable.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues )
+{
+    Extra_MmFlex_t * pFlex;
+    struct temp 
+    { 
+        int nValues; 
+        char ** pNames; 
+    } * pVarStruct;
+    assert( nValues > 1 );
+    // skip binary signals
+    if ( nValues == 2 )
+        return;
+    // skip already assigned signals
+    if ( Abc_ObjMvVar(pObj) != NULL )
+        return;
+    // create the structure
+    pFlex = Abc_NtkMvVarMan( pObj->pNtk );
+    pVarStruct = (void *)Extra_MmFlexEntryFetch( pFlex, sizeof(struct temp) );
+    pVarStruct->nValues = nValues;
+    pVarStruct->pNames = NULL;
+    Abc_ObjSetMvVar( pObj, pVarStruct );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes the BLIF-MV netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int Abc_StringGetNumber( char ** ppStr )
+{
+    char * pStr = *ppStr;
+    int Number = 0;
+    assert( *pStr >= '0' && *pStr <= '9' );
+    for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ )
+        Number = 10 * Number + *pStr - '0';
+    *ppStr = pStr;
+    return Number;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes one node in the BLIF-MV netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+{
+    char * pSop;
+    Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2;
+    Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet;
+    int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2;
+
+    // start the output values
+    assert( Abc_ObjIsNode(pObj) );
+    pNet = Abc_ObjFanout0(pObj);
+    nValues = Abc_ObjMvVarNum(pNet);
+    pValues = ALLOC( Abc_Obj_t *, nValues );
+    for ( k = 0; k < nValues; k++ )
+        pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+
+    // get the BLIF-MV formula
+    pSop = pObj->pData;
+    // skip the value line
+//    while ( *pSop++ != '\n' );
+
+    // handle the constant
+    if ( Abc_ObjFaninNum(pObj) == 0 )
+    {
+        // skip the default if present
+        if ( *pSop == 'd' )
+            while ( *pSop++ != '\n' );
+        // skip space if present
+        if ( *pSop == ' ' )
+            pSop++;
+        Index = Abc_StringGetNumber( &pSop );
+        assert( Index < nValues );
+        pValues[Index] = Abc_AigConst1(pNtkNew);
+        // save the values in the fanout net
+        pNet->pCopy = (Abc_Obj_t *)pValues;
+        return 1;
+    }
+
+    // parse the default line
+    Def = DefIndex = -1;
+    if ( *pSop == 'd' )
+    {
+        pSop++;
+        if ( *pSop == '=' )
+        {
+            pSop++;
+            DefIndex = Abc_StringGetNumber( &pSop );
+            assert( DefIndex < Abc_ObjFaninNum(pObj) );
+        }
+        else if ( *pSop == '-' )
+        {
+            pSop++;
+            Def = 0;
+        }
+        else
+        {
+            Def = Abc_StringGetNumber( &pSop );
+            assert( Def < nValues );
+        }
+        assert( *pSop == '\n' );
+        pSop++;
+    }
+
+    // convert the values
+    while ( *pSop )
+    {
+        // extract the values for each cube
+        pTemp = Abc_AigConst1(pNtkNew); 
+        Abc_ObjForEachFanin( pObj, pFanin, k )
+        {
+            if ( *pSop == '-' )
+            {
+                pSop += 2;
+                continue;
+            }
+            if ( *pSop == '!' )
+            {
+                printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) );
+                return 0;
+            }
+            if ( *pSop == '{' )
+            {
+                printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) );
+                return 0;
+            }
+            // get the value set
+            nValuesF = Abc_ObjMvVarNum(pFanin);
+            pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+            if ( *pSop == '(' )
+            {
+                pSop++;
+                pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+                while ( *pSop != ')' )
+                {
+                    Index = Abc_StringGetNumber( &pSop );
+                    assert( Index < nValuesF );
+                    pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, pValuesF[Index] );
+                    assert( *pSop == ')' || *pSop == ',' );
+                    if ( *pSop == ',' )
+                        pSop++;
+                }
+                assert( *pSop == ')' );
+                pSop++;
+            }
+            else if ( *pSop == '=' )
+            {
+                pSop++;
+                // get the fanin index
+                Index = Abc_StringGetNumber( &pSop );
+                assert( Index < Abc_ObjFaninNum(pObj) );
+                assert( Index != k );
+                // get the fanin
+                pFanin2 = Abc_ObjFanin( pObj, Index );
+                nValuesF2 = Abc_ObjMvVarNum(pFanin2);
+                pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy;
+                // create the sum of products of values
+                assert( nValuesF == nValuesF2 );
+                pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+                for ( v = 0; v < nValues; v++ )
+                    pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, Abc_AigAnd(pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) );
+            }
+            else
+            {
+                Index = Abc_StringGetNumber( &pSop );
+                assert( Index < nValuesF );
+                pTemp2 = pValuesF[Index];
+            }
+            // compute the compute
+            pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, pTemp2 );
+            // advance the reading point
+            assert( *pSop == ' ' );
+            pSop++;
+        }
+        // check if the output value is an equal construct
+        if ( *pSop == '=' )
+        {
+            pSop++;
+            // get the output value
+            Index = Abc_StringGetNumber( &pSop );
+            assert( Index < Abc_ObjFaninNum(pObj) );
+            // add values of the given fanin with the given cube
+            pFanin = Abc_ObjFanin( pObj, Index );
+            nValuesF = Abc_ObjMvVarNum(pFanin);
+            pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+            assert( nValuesF == nValues ); // should be guaranteed by the parser
+            for ( k = 0; k < nValuesF; k++ )
+                pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) );
+        }
+        else
+        {
+            // get the output value
+            Index = Abc_StringGetNumber( &pSop );
+            assert( Index < nValues );
+            pValues[Index] = Abc_AigOr( pNtkNew->pManFunc, pValues[Index], pTemp );
+        }
+        // advance the reading point
+        assert( *pSop == '\n' );
+        pSop++;
+    }
+
+    // compute the default value
+    if ( Def >= 0 || DefIndex >= 0 )
+    {
+        pTemp = Abc_AigConst1(pNtkNew);
+        for ( k = 0; k < nValues; k++ )
+        {
+            if ( k == Def )
+                continue;
+            pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) );
+        }
+
+        // assign the default value
+        if ( Def >= 0 )
+            pValues[Def] = pTemp;
+        else
+        {
+            assert( DefIndex >= 0 );
+            // add values of the given fanin with the given cube
+            pFanin = Abc_ObjFanin( pObj, DefIndex );
+            nValuesF = Abc_ObjMvVarNum(pFanin);
+            pValuesF = (Abc_Obj_t **)pFanin->pCopy;
+            assert( nValuesF == nValues ); // should be guaranteed by the parser
+            for ( k = 0; k < nValuesF; k++ )
+                pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) );
+        }
+
+    }
+
+    // save the values in the fanout net
+    pNet->pCopy = (Abc_Obj_t *)pValues;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Assigns name with index.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index )
+{
+    char Suffix[16];
+    assert( Abc_ObjIsTerm(pObj) );
+    assert( Abc_ObjIsNet(pNet) );
+    sprintf( Suffix, "[%d]", Index );
+    Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Strashes the BLIF-MV netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk )
+{
+    int fUsePositional = 0;
+    Vec_Ptr_t * vNodes;
+    Abc_Obj_t ** pBits;
+    Abc_Obj_t ** pValues;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pTemp, * pBit, * pNet;
+    int i, k, v, nValues, nValuesMax, nBits;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkHasBlifMv(pNtk) );
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtk) == 0 );
+
+    // get the largest number of values
+    nValuesMax = 2;
+    Abc_NtkForEachNet( pNtk, pObj, i )
+    {
+        nValues = Abc_ObjMvVarNum(pObj);
+        if ( nValuesMax < nValues )
+            nValuesMax = nValues;
+    }
+    nBits = Extra_Base2Log( nValuesMax );
+    pBits = ALLOC( Abc_Obj_t *, nBits );
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+    // collect the nodes
+    vNodes = Abc_NtkDfs( pNtk, 0 );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
+//    pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
+
+    // encode the CI nets
+    Abc_NtkIncrementTravId( pNtk );
+    if ( fUsePositional )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = ALLOC( Abc_Obj_t *, nValues );
+            // create PIs for the values
+            for ( v = 0; v < nValues; v++ )
+            {
+                pValues[v] = Abc_NtkCreatePi( pNtkNew );
+                Abc_NtkConvertAssignName( pValues[v], pNet, v );
+            }
+            // save the values in the fanout net
+            pNet->pCopy = (Abc_Obj_t *)pValues;
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = ALLOC( Abc_Obj_t *, nValues );
+            // create PIs for the encoding bits
+            nBits = Extra_Base2Log( nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pBits[k] = Abc_NtkCreatePi( pNtkNew );
+                Abc_NtkConvertAssignName( pBits[k], pNet, k );
+            }
+            // encode the values
+            for ( v = 0; v < nValues; v++ )
+            {
+                pValues[v] = Abc_AigConst1(pNtkNew);
+                for ( k = 0; k < nBits; k++ )
+                {
+                    pBit = Abc_ObjNotCond( pBits[k], (v&(1<<k)) == 0 );
+                    pValues[v] = Abc_AigAnd( pNtkNew->pManFunc, pValues[v], pBit );
+                }
+            }
+            // save the values in the fanout net
+            pNet->pCopy = (Abc_Obj_t *)pValues;
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+    }
+
+    // process nodes in the topological order
+    Vec_PtrForEachEntry( vNodes, pObj, i )
+        if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) )
+        {
+            Abc_NtkDelete( pNtkNew );
+            return NULL;
+        }
+    Vec_PtrFree( vNodes );
+
+    // encode the CO nets
+    if ( fUsePositional )
+    {
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+            if ( Abc_NodeIsTravIdCurrent(pNet) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = (Abc_Obj_t **)pNet->pCopy;
+            for ( v = 0; v < nValues; v++ )
+            {
+                pTemp = Abc_NtkCreatePo( pNtkNew );
+                Abc_ObjAddFanin( pTemp, pValues[v] );
+                Abc_NtkConvertAssignName( pTemp, pNet, v );
+            }
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+            if ( Abc_NodeIsTravIdCurrent(pNet) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            pValues = (Abc_Obj_t **)pNet->pCopy;
+            nBits = Extra_Base2Log( nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
+                for ( v = 0; v < nValues; v++ )
+                    if ( v & (1<<k) )
+                        pBit = Abc_AigOr( pNtkNew->pManFunc, pBit, pValues[v] );
+                pTemp = Abc_NtkCreatePo( pNtkNew );
+                Abc_ObjAddFanin( pTemp, pBit );
+                Abc_NtkConvertAssignName( pTemp, pNet, k );
+            }
+        }
+    }
+
+    // cleanup
+    free( pBits );
+    Abc_NtkForEachObj( pNtk, pObj, i )
+        if ( pObj->pCopy )
+            free( pObj->pCopy );
+
+    // remove dangling nodes
+    i = Abc_AigCleanup(pNtkNew->pManFunc);
+//    printf( "Cleanup removed %d nodes.\n", i );
+//    Abc_NtkReassignIds( pNtkNew );
+
+    // check integrity
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Extract the MV-skeleton of the BLIF-MV network.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk )
+{
+    int fUsePositional = 0;
+    Abc_Ntk_t * pNtkNew;
+    Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew;
+    int i, k, v, nValues, nBits;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkHasBlifMv(pNtk) );
+    assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtk) == 0 );
+
+    // clean the node copy fields
+    Abc_NtkCleanCopy( pNtk );
+
+    // start the network
+    pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+    // duplicate the name and the spec
+    pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
+    pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
+    // create the internal box (it is important to put it first!)
+    pBoxNew = Abc_NtkCreateWhitebox( pNtkNew );
+    // create PIs and their nets
+    Abc_NtkForEachPi( pNtk, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        pNet = Abc_ObjFanout0(pObj);
+        Abc_NtkDupObj( pNtkNew, pNet, 1 );
+        Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy );
+    }
+    // create POs and their nets
+    Abc_NtkForEachPo( pNtk, pObj, i )
+    {
+        Abc_NtkDupObj( pNtkNew, pObj, 0 );
+        pNet = Abc_ObjFanin0(pObj);
+        if ( pNet->pCopy == NULL )
+            Abc_NtkDupObj( pNtkNew, pNet, 1 );
+        Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy );
+    }
+    // create latches
+    Abc_NtkForEachLatch( pNtk, pObj, i )
+    {
+        Abc_NtkDupBox( pNtkNew, pObj, 0 );
+        // latch outputs
+        pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj));
+        assert( pNet->pCopy == NULL );
+        Abc_NtkDupObj( pNtkNew, pNet, 1 );
+        Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy );
+        // latch inputs
+        pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+        if ( pNet->pCopy == NULL )
+            Abc_NtkDupObj( pNtkNew, pNet, 1 );
+        Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy );
+    }
+
+    // encode the CI nets
+    Abc_NtkIncrementTravId( pNtk );
+    if ( fUsePositional )
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            for ( v = 0; v < nValues; v++ )
+            {
+                pNodeNew = Abc_NtkCreateNode( pNtkNew );
+                pNodeNew->pData = Abc_SopEncoderPos( pNtkNew->pManFunc, v, nValues );
+                pNetNew = Abc_NtkCreateNet( pNtkNew );
+                pTermNew = Abc_NtkCreateBi( pNtkNew );
+                Abc_ObjAddFanin( pNodeNew, pNet->pCopy );
+                Abc_ObjAddFanin( pNetNew, pNodeNew );
+                Abc_ObjAddFanin( pTermNew, pNetNew );
+                Abc_ObjAddFanin( pBoxNew, pTermNew );
+            }
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCi( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanout0(pObj);
+            nValues = Abc_ObjMvVarNum(pNet);
+            nBits = Extra_Base2Log( nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pNodeNew = Abc_NtkCreateNode( pNtkNew );
+                pNodeNew->pData = Abc_SopEncoderLog( pNtkNew->pManFunc, k, nValues );
+                pNetNew = Abc_NtkCreateNet( pNtkNew );
+                pTermNew = Abc_NtkCreateBi( pNtkNew );
+                Abc_ObjAddFanin( pNodeNew, pNet->pCopy );
+                Abc_ObjAddFanin( pNetNew, pNodeNew );
+                Abc_ObjAddFanin( pTermNew, pNetNew );
+                Abc_ObjAddFanin( pBoxNew, pTermNew );
+            }
+            // mark the net
+            Abc_NodeSetTravIdCurrent( pNet );
+        }
+    }
+
+    // encode the CO nets
+    if ( fUsePositional )
+    {
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+            if ( Abc_NodeIsTravIdCurrent(pNet) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            pNodeNew = Abc_NtkCreateNode( pNtkNew );
+            pNodeNew->pData = Abc_SopDecoderPos( pNtkNew->pManFunc, nValues );
+            for ( v = 0; v < nValues; v++ )
+            {
+                pTermNew = Abc_NtkCreateBo( pNtkNew );
+                pNetNew = Abc_NtkCreateNet( pNtkNew );
+                Abc_ObjAddFanin( pTermNew, pBoxNew );
+                Abc_ObjAddFanin( pNetNew, pTermNew );
+                Abc_ObjAddFanin( pNodeNew, pNetNew );
+            }
+            Abc_ObjAddFanin( pNet->pCopy, pNodeNew );
+        }
+    }
+    else
+    {
+        Abc_NtkForEachCo( pNtk, pObj, i )
+        {
+            pNet = Abc_ObjFanin0(pObj);
+            // skip marked nets
+            if ( Abc_NodeIsTravIdCurrent(pNet) )
+                continue;
+            Abc_NodeSetTravIdCurrent( pNet );
+            nValues = Abc_ObjMvVarNum(pNet);
+            nBits = Extra_Base2Log( nValues );
+            pNodeNew = Abc_NtkCreateNode( pNtkNew );
+            pNodeNew->pData = Abc_SopDecoderLog( pNtkNew->pManFunc, nValues );
+            for ( k = 0; k < nBits; k++ )
+            {
+                pTermNew = Abc_NtkCreateBo( pNtkNew );
+                pNetNew = Abc_NtkCreateNet( pNtkNew );
+                Abc_ObjAddFanin( pTermNew, pBoxNew );
+                Abc_ObjAddFanin( pNetNew, pTermNew );
+                Abc_ObjAddFanin( pNodeNew, pNetNew );
+            }
+            Abc_ObjAddFanin( pNet->pCopy, pNodeNew );
+        }
+    }
+
+    // if it is a BLIF-MV netlist transfer the values of all nets
+    if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
+    {
+        if ( Abc_NtkMvVar( pNtkNew ) == NULL )
+            Abc_NtkStartMvVars( pNtkNew );
+        Abc_NtkForEachNet( pNtk, pObj, i )
+            if ( pObj->pCopy )
+                Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
+    }
+
+    // check integrity
+    if ( !Abc_NtkCheck( pNtkNew ) )
+    {
+        fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" );
+        Abc_NtkDelete( pNtkNew );
+        return NULL;
+    }
+    return pNtkNew;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Inserts processed network into original base MV network.]
+
+  Description [The original network remembers the interface of combinational 
+  logic (PIs/POs/latches names and values). The processed network may 
+  be binary or multi-valued (currently, multi-value is not supported). 
+  The resulting network has the same interface as the original network 
+  while the internal logic is the same as that of the processed network.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic )
+{
+    Abc_Ntk_t * pNtkSkel, * pNtkNew;
+    Abc_Obj_t * pBox;
+
+    assert( Abc_NtkIsNetlist(pNtkBase) );
+    assert( Abc_NtkHasBlifMv(pNtkBase) );
+    assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtkBase) == 0 );
+
+    assert( Abc_NtkIsNetlist(pNtkLogic) );
+    assert( Abc_NtkHasBlifMv(pNtkLogic) );
+    assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 );
+    assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 );
+
+    // extract the skeleton of the old network
+    pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase );
+
+    // set the implementation of the box to be the same as the processed network
+    assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 );
+    pBox = Abc_NtkBox( pNtkSkel, 0 );
+    assert( Abc_ObjIsWhitebox(pBox) );
+    assert( pBox->pData == NULL );
+    assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) );
+    assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) );
+    pBox->pData = pNtkLogic;
+
+    // flatten the hierarchy to insert the processed network
+    pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel );
+    pBox->pData = NULL;
+    Abc_NtkDelete( pNtkSkel );
+    return pNtkNew;    
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP netlist into BLIF-MV netlist.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk )
+{
+    Extra_MmFlex_t * pMmFlex;
+    Abc_Obj_t * pNode;
+    Vec_Str_t * vCube;
+    char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur;
+    int Value, nCubes, nSize, i, k;
+
+    assert( Abc_NtkIsNetlist(pNtk) );
+    if ( !Abc_NtkToBdd(pNtk) )
+    {
+        printf( "Converting logic functions to BDDs has failed.\n" );
+        return 0;
+    }
+
+    pMmFlex = Extra_MmFlexStart();
+    vCube   = Vec_StrAlloc( 100 );
+    Abc_NtkForEachNode( pNtk, pNode, i )
+    {
+        // convert BDD into cubes for on-set and off-set
+        Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 );
+        // allocate room for the MV-SOP
+        nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1);
+        nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1;
+        pBlifMv = Extra_MmFlexEntryFetch( pMmFlex, nSize );
+        // add the cubes
+        pCur = pBlifMv;
+        Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube )
+        {
+            Abc_CubeForEachVar( pCube, Value, k )
+            {
+                *pCur++ = Value;
+                *pCur++ = ' ';
+            }
+            *pCur++ = '0';
+            *pCur++ = '\n';
+        }
+        Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube )
+        {
+            Abc_CubeForEachVar( pCube, Value, k )
+            {
+                *pCur++ = Value;
+                *pCur++ = ' ';
+            }
+            *pCur++ = '1';
+            *pCur++ = '\n';
+        }
+        *pCur++ = 0;
+        assert( pCur - pBlifMv == nSize );
+        // update the node representation
+        Cudd_RecursiveDeref( pNtk->pManFunc, pNode->pData );
+        pNode->pData = pBlifMv;
+    }
+
+    // update the functionality type
+    pNtk->ntkFunc = ABC_FUNC_BLIFMV;
+    Cudd_Quit( pNtk->pManFunc );
+    pNtk->pManFunc = pMmFlex;
+
+    Vec_StrFree( vCube );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP into MV-SOP.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 )
+{
+    char * pMvSop, * pCur;
+    unsigned uCube;
+    int nCubes, nSize, Value, i, k;
+    // consider the case of the constant node
+    if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 )
+    {
+        // (temporary) create a tautology cube
+        pMvSop = ALLOC( char, nVars + 3 );
+        for ( k = 0; k < nVars; k++ )
+            pMvSop[k] = '-';
+        pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0);
+        pMvSop[nVars+1] = '\n';
+        pMvSop[nVars+2] = 0;
+        return pMvSop;
+    }
+    // find the total number of cubes
+    nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1);
+    // find the size of the MVSOP represented as a C-string
+    // (each cube has nVars variables + one output literal + end-of-line,
+    // and the string is zero-terminated)
+    nSize = nCubes * (nVars + 2) + 1; 
+    // allocate memory
+    pMvSop = pCur = ALLOC( char, nSize );
+    // fill in the negative polarity cubes
+    Vec_IntForEachEntry( vSop0, uCube, i )
+    {
+        for ( k = 0; k < nVars; k++ )
+        {
+            Value = (uCube >> (2*k)) & 3;
+            if ( Value == 1 )
+                *pCur++ = '0';
+            else if ( Value == 2 )
+                *pCur++ = '1';
+            else if ( Value == 0 )
+                *pCur++ = '-';
+            else
+                assert( 0 );
+        }
+        *pCur++ = '0';
+        *pCur++ = '\n';
+    }
+    // fill in the positive polarity cubes
+    Vec_IntForEachEntry( vSop1, uCube, i )
+    {
+        for ( k = 0; k < nVars; k++ )
+        {
+            Value = (uCube >> (2*k)) & 3;
+            if ( Value == 1 )
+                *pCur++ = '0';
+            else if ( Value == 2 )
+                *pCur++ = '1';
+            else if ( Value == 0 )
+                *pCur++ = '-';
+            else
+                assert( 0 );
+        }
+        *pCur++ = '1';
+        *pCur++ = '\n';
+    }
+    *pCur++ = 0;
+    assert( pCur - pMvSop == nSize );
+    return pMvSop;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [A prototype of internal cost evaluation procedure.]
+
+  Description [This procedure takes the number of variables (nVars),
+  the array of values of the inputs and the output (pVarValues) 
+  (note that this array has nVars+1 entries), and an MV-SOP represented
+  as a C-string with one charater for each literal, including inputs
+  and output. Each cube is terminated with the new-line character ('\n').
+  The string is zero-terminated.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop ) 
+{
+    // for now, return the number of cubes in the MV-SOP
+    int Counter = 0;
+    while ( *pMvSop ) Counter += (*pMvSop++ == '\n');
+    return Counter;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Evaluates the cost of the cut.]
+
+  Description [The Boolean function of the cut is specified by two SOPs, 
+  which represent the negative/positive polarities of the cut function.
+  Converts these two SOPs into a mutually-agreed-upon representation 
+  to be passed to the internal cost-evaluation procedure (see the above
+  prototype Abc_NodeEvalMvCostInternal).]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) 
+{
+    char * pMvSop;
+    int * pVarValues;
+    int i, RetValue;
+    // collect the input and output values (currently, they are binary)
+    pVarValues = ALLOC( int, nVars + 1 );
+    for ( i = 0; i <= nVars; i++ )
+        pVarValues[i] = 2;
+    // prepare MV-SOP for evaluation
+    pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 );
+    // have a look at the MV-SOP:
+//    printf( "%s\n", pMvSop );
+    // get the result of internal cost evaluation
+    RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop );
+    // cleanup
+    free( pVarValues );
+    free( pMvSop );
+    return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+///                       END OF FILE                                ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abc/abcCheck.c b/src/base/abc/abcCheck.c
index e159bcab..24f10475 100644
--- a/src/base/abc/abcCheck.c
+++ b/src/base/abc/abcCheck.c
@@ -277,6 +277,19 @@ bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk )
         }
     }
     Vec_IntFree( vNameIds );
+
+    // make sure the CI names are unique
+    if ( !Abc_NtkCheckUniqueCiNames(pNtk) )
+        return 0;
+
+    // make sure the CO names are unique
+    if ( !Abc_NtkCheckUniqueCoNames(pNtk) )
+        return 0;
+
+    // make sure that if a CO has the same name as a CI, they point directly
+    if ( !Abc_NtkCheckUniqueCioNames(pNtk) )
+        return 0;
+
     return 1;
 }
 
@@ -804,6 +817,121 @@ int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk )
     return RetValue;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if CI names are repeated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkNamesCompare( char ** pName1, char ** pName2 )
+{
+    return strcmp( *pName1, *pName2 );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if CI names are repeated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNames;
+    Abc_Obj_t * pObj;
+    int i, fRetValue = 1;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) );
+    Abc_NtkForEachCi( pNtk, pObj, i )
+        Vec_PtrPush( vNames, Abc_ObjName(pObj) );
+    Vec_PtrSort( vNames, Abc_NtkNamesCompare );
+    for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ )
+        if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) )
+        {
+            printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) );
+            fRetValue = 0;
+        }
+    Vec_PtrFree( vNames );
+    return fRetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if CO names are repeated.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk )
+{
+    Vec_Ptr_t * vNames;
+    Abc_Obj_t * pObj;
+    int i, fRetValue = 1;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+        Vec_PtrPush( vNames, Abc_ObjName(pObj) );
+    Vec_PtrSort( vNames, Abc_NtkNamesCompare );
+    for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ )
+    {
+//        printf( "%s\n", Vec_PtrEntry(vNames,i) );
+        if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) )
+        {
+            printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) );
+            fRetValue = 0;
+        }
+    }
+    Vec_PtrFree( vNames );
+    return fRetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns 0 if there is a pair of CI/CO with the same name and logic in between.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk )
+{
+    Abc_Obj_t * pObj, * pObjCi;
+    int i, nCiId, fRetValue = 1;
+    assert( !Abc_NtkIsNetlist(pNtk) );
+    Abc_NtkForEachCo( pNtk, pObj, i )
+    {
+        nCiId = Nm_ManFindIdByName( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI );
+        if ( nCiId == -1 )
+            nCiId = Nm_ManFindIdByName( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_BO );
+        if ( nCiId == -1 )
+            continue;
+        pObjCi = Abc_NtkObj( pNtk, nCiId );
+        assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) );
+        if ( Abc_ObjFanin0(pObj) != pObjCi )
+        {
+            printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly.\n", Abc_ObjName(pObj) );
+            fRetValue = 0;
+        }
+    }
+    return fRetValue;
+}
+
 ////////////////////////////////////////////////////////////////////////
 ///                       END OF FILE                                ///
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c
index da4617ca..3dd9a132 100644
--- a/src/base/abc/abcDfs.c
+++ b/src/base/abc/abcDfs.c
@@ -884,7 +884,8 @@ int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode )
         if ( pNode->Level < (unsigned)Level )
             pNode->Level = Level;
     }
-    pNode->Level++;
+    if ( Abc_ObjFaninNum(pNode) > 0 )
+        pNode->Level++;
     return pNode->Level;
 }
 
@@ -975,8 +976,8 @@ bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode )
     if ( Abc_NodeIsTravIdCurrent(pNode) )
     {
         fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) );
-        fprintf( stdout, "Node \"%s\" is encountered twice on the following path:\n", Abc_ObjName(pNode) );
-        fprintf( stdout, " %s", Abc_ObjIsNode(pNode)? Abc_ObjName(pNode) : Abc_NtkName(pNode->pData) );
+        fprintf( stdout, "Node \"%s\" is encountered twice on the following path:\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
+        fprintf( stdout, " %s", Abc_ObjIsNode(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)) : Abc_NtkName(pNode->pData) );
         return 0;
     }
     // mark this node as a node on the current path
@@ -1041,7 +1042,7 @@ bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk )
         if ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) )
             continue;
         // stop as soon as the first loop is detected
-        fprintf( stdout, " (cone of CO \"%s\")\n", Abc_ObjName(pNode) );
+        fprintf( stdout, " (cone of CO \"%s\")\n", Abc_ObjName(Abc_ObjFanout0(pNode)) );
         break;
     }
     return fAcyclic;
diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c
index 0947b58a..7a271338 100644
--- a/src/base/abc/abcFunc.c
+++ b/src/base/abc/abcFunc.c
@@ -878,6 +878,22 @@ int Abc_NtkMapToSop( Abc_Ntk_t * pNtk )
     return 1;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Converts SOP functions into BLIF-MV functions.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk )
+{
+    return 1;
+}
+
 /**Function*************************************************************
 
   Synopsis    [Convers logic network to the SOP form.]
diff --git a/src/base/abc/abcHie.c b/src/base/abc/abcHie.c
index b38afb59..9e9d921b 100644
--- a/src/base/abc/abcHie.c
+++ b/src/base/abc/abcHie.c
@@ -146,6 +146,15 @@ void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, in
         // call recursively
         Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter );
     }
+
+    // if it is a BLIF-MV netlist transfer the values of all nets
+    if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
+    {
+        if ( Abc_NtkMvVar( pNtkNew ) == NULL )
+            Abc_NtkStartMvVars( pNtkNew );
+        Abc_NtkForEachNet( pNtk, pObj, i )
+            Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
+    }
 }
 
 /**Function*************************************************************
@@ -198,12 +207,15 @@ Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk )
     printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", 
         Counter, Abc_NtkBlackboxNum(pNtkNew) );
 
-    // pass the design
-    assert( Vec_PtrEntry(pNtk->pDesign->vModules, 0) == pNtk );
-    pNtkNew->pDesign = Abc_LibDupBlackboxes( pNtk->pDesign, pNtkNew );
-    // update the pointers
-    Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
-        pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
+    if ( pNtk->pDesign )
+    {
+        // pass on the design
+        assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
+        pNtkNew->pDesign = Abc_LibDupBlackboxes( pNtk->pDesign, pNtkNew );
+        // update the pointers
+        Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
+            pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
+    }
 
     // copy the timing information
 //    Abc_ManTimeDup( pNtk, pNtkNew );
@@ -473,276 +485,6 @@ Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL )
     return pNtkNew;
 }
 
-/**Function*************************************************************
-
-  Synopsis    [Assigns name with index.]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index )
-{
-    char Suffix[16];
-    assert( Abc_ObjIsTerm(pObj) );
-    assert( Abc_ObjIsNet(pNet) );
-    sprintf( Suffix, "[%d]", Index );
-    Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix );
-}
-
-/**Function*************************************************************
-
-  Synopsis    [Strashes the BLIF-MV netlist.]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-Abc_Ntk_t * Abc_NtkConvertBlifMv( Abc_Ntk_t * pNtk )
-{
-    char * pSop;
-    Vec_Ptr_t * vNodes;
-    Abc_Obj_t * pBits[16];
-    Abc_Obj_t ** pValues, ** pValuesF;
-    Abc_Ntk_t * pNtkNew;
-    Abc_Obj_t * pObj, * pTemp, * pBit, * pFanin, * pNet;
-    int fUsePositional = 0;
-    int i, k, v, nValues, Val, Index, Len, nBits, Def;
-
-    assert( Abc_NtkIsNetlist(pNtk) );
-    assert( Abc_NtkHasBlifMv(pNtk) );
-
-    // clean the node copy fields
-    Abc_NtkCleanCopy( pNtk );
-
-    // start the network
-    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
-    // duplicate the name and the spec
-    pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
-//    pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName );
-
-    // check temporary assumptions
-    Abc_NtkForEachNet( pNtk, pObj, i )
-        assert( Abc_ObjMvVarNum(pObj) < 10 );
-
-    // encode the CI nets
-    if ( fUsePositional )
-    {
-        Abc_NtkForEachCi( pNtk, pObj, i )
-        {
-            pNet = Abc_ObjFanout0(pObj);
-            nValues = Abc_ObjMvVarNum(pNet);
-            pValues = ALLOC( Abc_Obj_t *, nValues );
-            // create PIs for the values
-            for ( v = 0; v < nValues; v++ )
-            {
-                pValues[v] = Abc_NtkCreatePi( pNtkNew );
-                Abc_NtkConvertAssignName( pValues[v], pNet, v );
-            }
-            // save the values in the fanout net
-            pNet->pCopy = (Abc_Obj_t *)pValues;
-        }
-    }
-    else
-    {
-        Abc_NtkForEachCi( pNtk, pObj, i )
-        {
-            pNet = Abc_ObjFanout0(pObj);
-            nValues = Abc_ObjMvVarNum(pNet);
-            pValues = ALLOC( Abc_Obj_t *, nValues );
-            // create PIs for the encoding bits
-            nBits = Extra_Base2Log( nValues );
-            for ( k = 0; k < nBits; k++ )
-            {
-                pBits[k] = Abc_NtkCreatePi( pNtkNew );
-                Abc_NtkConvertAssignName( pBits[k], pNet, k );
-            }
-            // encode the values
-            for ( v = 0; v < nValues; v++ )
-            {
-                pValues[v] = Abc_AigConst1(pNtkNew);
-                for ( k = 0; k < nBits; k++ )
-                {
-                    pBit = Abc_ObjNotCond( pBits[k], (v&(1<<k)) == 0 );
-                    pValues[v] = Abc_AigAnd( pNtkNew->pManFunc, pValues[v], pBit );
-                }
-            }
-            // save the values in the fanout net
-            pNet->pCopy = (Abc_Obj_t *)pValues;
-        }
-    }
-
-    // process nodes in the topological order
-    vNodes = Abc_NtkDfs( pNtk, 0 );
-    Vec_PtrForEachEntry( vNodes, pObj, i )
-    {
-        assert( Abc_ObjIsNode(pObj) );
-        pNet = Abc_ObjFanout0(pObj);
-        nValues = Abc_ObjMvVarNum(pNet);
-        pValues = ALLOC( Abc_Obj_t *, nValues );
-        for ( v = 0; v < nValues; v++ )
-            pValues[v] = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
-        // get the BLIF-MV formula
-        pSop = pObj->pData;
-        // skip the value line
-        while ( *pSop++ != '\n' );
-
-        // handle the constant
-        if ( Abc_ObjFaninNum(pObj) == 0 )
-        {
-            Index = *pSop-'0';
-            pValues[Index] = Abc_AigConst1(pNtkNew);
-            // save the values in the fanout net
-            pNet->pCopy = (Abc_Obj_t *)pValues;
-            continue;
-        }
-/*
-        // handle the mux
-        if ( *pSop != 'd' )
-        {
-            assert( Abc_ObjFaninNum(pObj) == 3 );
-            pValuesF = (Abc_Obj_t **)Abc_ObjFanin(pObj,1)->pCopy;
-            for ( v = 0; v < nValues; v++ )
-                pValues[v] = pValuesF[v];
-            // save the values in the fanout net
-            pNet->pCopy = (Abc_Obj_t *)pValues;
-            continue;
-        }
-*/
-        // detect muxes
-        Len = strlen(pSop);
-        for ( k = 0; k < Len; k++ )
-            if ( *(pSop+k) == '=' )
-                break;
-        if ( k < Len )
-        {
-            assert( Abc_ObjFaninNum(pObj) == 3 );
-            pValuesF = (Abc_Obj_t **)Abc_ObjFanin(pObj,1)->pCopy;
-            for ( v = 0; v < nValues; v++ )
-                pValues[v] = pValuesF[v];
-            // save the values in the fanout net
-            pNet->pCopy = (Abc_Obj_t *)pValues;
-            continue;
-        }
- 
-        // skip the default line
-//        assert( *pSop == 'd' );
-        if ( *pSop == 'd' )
-        {
-            Def = *(pSop+1) - '0';
-            while ( *pSop++ != '\n' );
-        }
-        else
-            Def = -1;
-        // convert the values
-        while ( *pSop )
-        {
-            // encode the values
-            pTemp = Abc_AigConst1(pNtkNew); 
-            Abc_ObjForEachFanin( pObj, pFanin, k )
-            {
-                if ( *pSop == '-' )
-                {
-                    pSop += 2;
-                    continue;
-                }
-                Val = Abc_ObjMvVarNum(pFanin);
-                pValuesF = (Abc_Obj_t **)pFanin->pCopy;
-                Index = *pSop-'0';
-                assert( Index >= 0 && Index <= 9 && Index < Val );
-                pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, pValuesF[Index] );
-                pSop += 2;
-            }
-            // get the output value
-            Index = *pSop-'0';
-            assert( Index >= 0 && Index <= 9 );
-            pValues[Index] = Abc_AigOr( pNtkNew->pManFunc, pValues[Index], pTemp );
-            pSop++;
-            assert( *pSop == '\n' );
-            pSop++;
-        }
-        // compute the default value
-//        Def = 0;
-        if ( Def >= 0 )
-        {
-            assert( pValues[Def] == Abc_ObjNot( Abc_AigConst1(pNtkNew) ) );
-            pValues[Def] = Abc_AigConst1(pNtkNew);
-            for ( v = 0; v < nValues; v++ )
-            {
-                if ( v == Def )
-                    continue;
-                pValues[Def] = Abc_AigAnd( pNtkNew->pManFunc, pValues[Def], Abc_ObjNot(pValues[v]) );
-            }
-            // experiment
-    //        if ( nValues > 2 )
-    //            pValues[Def] = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
-        }
-
-        // save the values in the fanout net
-        pNet->pCopy = (Abc_Obj_t *)pValues;
-    }
-    Vec_PtrFree( vNodes );
-
-    // encode the CO nets
-    if ( fUsePositional )
-    {
-        Abc_NtkForEachCo( pNtk, pObj, i )
-        {
-            pNet = Abc_ObjFanin0(pObj);
-            nValues = Abc_ObjMvVarNum(pNet);
-            pValues = (Abc_Obj_t **)pNet->pCopy;
-            for ( v = 0; v < nValues; v++ )
-            {
-                pTemp = Abc_NtkCreatePo( pNtkNew );
-                Abc_ObjAddFanin( pTemp, pValues[v] );
-                Abc_NtkConvertAssignName( pTemp, pNet, v );
-            }
-        }
-    }
-    else
-    {
-        Abc_NtkForEachCo( pNtk, pObj, i )
-        {
-            pNet = Abc_ObjFanin0(pObj);
-            nValues = Abc_ObjMvVarNum(pNet);
-            pValues = (Abc_Obj_t **)pNet->pCopy;
-            nBits = Extra_Base2Log( nValues );
-            for ( k = 0; k < nBits; k++ )
-            {
-                pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) );
-                for ( v = 0; v < nValues; v++ )
-                    if ( v & (1<<k) )
-                        pBit = Abc_AigOr( pNtkNew->pManFunc, pBit, pValues[v] );
-                pTemp = Abc_NtkCreatePo( pNtkNew );
-                Abc_ObjAddFanin( pTemp, pBit );
-                Abc_NtkConvertAssignName( pTemp, pNet, k );
-            }
-        }
-    }
-
-    // cleanup
-    Abc_NtkForEachObj( pNtk, pObj, i )
-        if ( pObj->pCopy )
-            free( pObj->pCopy );
-
-    Abc_AigCleanup(pNtkNew->pManFunc);
-
-    // check integrity
-    if ( !Abc_NtkCheck( pNtkNew ) )
-    {
-        fprintf( stdout, "Abc_NtkConvertBlifMv(): Network check has failed.\n" );
-        Abc_NtkDelete( pNtkNew );
-        return NULL;
-    }
-    return pNtkNew;
-}
-
 ////////////////////////////////////////////////////////////////////////
 ///                       END OF FILE                                ///
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcLib.c b/src/base/abc/abcLib.c
index 1f741ca8..d9d8bce9 100644
--- a/src/base/abc/abcLib.c
+++ b/src/base/abc/abcLib.c
@@ -108,8 +108,11 @@ Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave )
     Abc_Lib_t * pLibNew;
     Abc_Ntk_t * pNtkTemp;
     int i;
+    assert( Vec_PtrSize(pLib->vTops) > 0 );
+    assert( Vec_PtrSize(pLib->vModules) > 1 );
     pLibNew = Abc_LibCreate( pLib->pName );
 //    pLibNew->pManFunc = pNtkSave->pManFunc;
+    Vec_PtrPush( pLibNew->vTops, pNtkSave );
     Vec_PtrPush( pLibNew->vModules, pNtkSave );
     Vec_PtrForEachEntry( pLib->vModules, pNtkTemp, i )
         if ( Abc_NtkHasBlackbox( pNtkTemp ) )
@@ -215,7 +218,50 @@ Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib )
     return pNtk;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Detects the top-level models.]
+
+  Description []
+               
+  SideEffects []
 
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib )
+{
+    Abc_Ntk_t * pNtk, * pNtkBox;
+    Abc_Obj_t * pObj;
+    int i, k;
+    assert( Vec_PtrSize( pLib->vModules ) > 0 );
+    // clear the models
+    Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
+        pNtk->fHieVisited = 0;
+    // mark all the models reachable from other models
+    Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
+    {
+        Abc_NtkForEachBox( pNtk, pObj, k )
+        {
+            if ( Abc_ObjIsLatch(pObj) )
+                continue;
+            if ( pObj->pData == NULL )
+                continue;
+            pNtkBox = pObj->pData;
+            pNtkBox->fHieVisited = 1;
+        }
+    }
+    // collect the models that are not marked
+    Vec_PtrClear( pLib->vTops );
+    Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
+    {
+        if ( pNtk->fHieVisited == 0 )
+            Vec_PtrPush( pLib->vTops, pNtk );
+        else
+            pNtk->fHieVisited = 0;
+    }
+    return Vec_PtrSize( pLib->vTops );
+}
 
 
 /**Function*************************************************************
diff --git a/src/base/abc/abcNetlist.c b/src/base/abc/abcNetlist.c
index f57bcc21..26b88c68 100644
--- a/src/base/abc/abcNetlist.c
+++ b/src/base/abc/abcNetlist.c
@@ -55,7 +55,7 @@ Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk )
         return Abc_NtkAigToLogicSop( pNtk );
     assert( Abc_NtkIsNetlist(pNtk) );
     // consider simple case when there is hierarchy
-    assert( pNtk->pDesign == NULL );
+//    assert( pNtk->pDesign == NULL );
     assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
     assert( Abc_NtkBlackboxNum(pNtk) == 0 );
     // start the network
@@ -90,7 +90,7 @@ Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk )
   SeeAlso     []
 
 ***********************************************************************/
-Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk, int fDirect )
+Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk )
 {
     Abc_Ntk_t * pNtkNew, * pNtkTemp; 
     assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
@@ -151,6 +151,11 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
     // remove dangling nodes
     Abc_NtkCleanup( pNtk, 0 );
 
+    // make sure the CO names are unique
+    Abc_NtkCheckUniqueCiNames( pNtk );
+    Abc_NtkCheckUniqueCoNames( pNtk );
+    Abc_NtkCheckUniqueCioNames( pNtk );
+
 //    assert( Abc_NtkLogicHasSimpleCos(pNtk) );
     if ( !Abc_NtkLogicHasSimpleCos(pNtk) )
     {
@@ -213,7 +218,7 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
             Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
     // duplicate EXDC 
     if ( pNtk->pExdc )
-        pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc, 0 );
+        pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc );
     if ( !Abc_NtkCheck( pNtkNew ) )
         fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" );
     return pNtkNew;
diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c
index deddb712..e0773e3f 100644
--- a/src/base/abc/abcNtk.c
+++ b/src/base/abc/abcNtk.c
@@ -264,18 +264,23 @@ void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk )
     assert( Abc_NtkIsNetlist(pNtk) );
 
     // check if constant 0 net is used
-    pNet = Abc_NtkFindOrCreateNet( pNtk, "1\'b0" );
-    if ( Abc_ObjFanoutNum(pNet) == 0 )
-        Abc_NtkDeleteObj(pNet);
-    else if ( Abc_ObjFaninNum(pNet) == 0 )
-        Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) );
+    pNet = Abc_NtkFindNet( pNtk, "1\'b0" );
+    if ( pNet )
+    {
+        if ( Abc_ObjFanoutNum(pNet) == 0 )
+            Abc_NtkDeleteObj(pNet);
+        else if ( Abc_ObjFaninNum(pNet) == 0 )
+            Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) );
+    }
     // check if constant 1 net is used
-    pNet = Abc_NtkFindOrCreateNet( pNtk, "1\'b1" );
-    if ( Abc_ObjFanoutNum(pNet) == 0 )
-        Abc_NtkDeleteObj(pNet);
-    else if ( Abc_ObjFaninNum(pNet) == 0 )
-        Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) );
-
+    pNet = Abc_NtkFindNet( pNtk, "1\'b1" );
+    if ( pNet )
+    {
+        if ( Abc_ObjFanoutNum(pNet) == 0 )
+            Abc_NtkDeleteObj(pNet);
+        else if ( Abc_ObjFaninNum(pNet) == 0 )
+            Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) );
+    }
     // fix the net drivers
     Abc_NtkFixNonDrivenNets( pNtk );
 
@@ -872,7 +877,10 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk )
     // free node attributes
     Vec_PtrForEachEntry( pNtk->vAttrs, pAttrMan, i )
         if ( pAttrMan )
+        {
+//printf( "deleting attr\n" );
             Vec_AttFree( pAttrMan, 1 );
+        }
     Vec_PtrFree( pNtk->vAttrs );
     FREE( pNtk->pName );
     FREE( pNtk->pSpec );
@@ -892,16 +900,12 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk )
 ***********************************************************************/
 void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
 { 
-    char Buffer[10];
     Vec_Ptr_t * vNets;
     Abc_Obj_t * pNet, * pNode;
     int i;
 
     if ( Abc_NtkNodeNum(pNtk) == 0 )
-    {
-//        pNtk->ntkFunc = ABC_FUNC_BLACKBOX;
         return;
-    }
 
     // check for non-driven nets
     vNets = Vec_PtrAlloc( 100 );
@@ -910,14 +914,7 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
         if ( Abc_ObjFaninNum(pNet) > 0 )
             continue;
         // add the constant 0 driver
-        if ( Abc_NtkHasBlifMv(pNtk) )
-        {
-            pNode = Abc_NtkCreateNode( pNtk );   
-            sprintf( Buffer, "%d\n0\n", Abc_ObjMvVarNum(pNet) );
-            pNode->pData = Abc_SopRegister( pNtk->pManFunc, Buffer );
-        }
-        else
-            pNode = Abc_NtkCreateNodeConst0( pNtk );
+        pNode = Abc_NtkCreateNodeConst0( pNtk );
         // add the fanout net
         Abc_ObjAddFanin( pNet, pNode );
         // add the net to those for which the warning will be printed
@@ -927,7 +924,7 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
     // print the warning
     if ( vNets->nSize > 0 )
     {
-        printf( "Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName );
+        printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName );
         Vec_PtrForEachEntry( vNets, pNet, i )
         {
             printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) );
diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c
index 4931f238..0425d984 100644
--- a/src/base/abc/abcObj.c
+++ b/src/base/abc/abcObj.c
@@ -349,7 +349,7 @@ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName
         {
             if ( Abc_NtkIsStrash(pNtkNew) ) 
             {}
-            else if ( Abc_NtkHasSop(pNtkNew) )
+            else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) )
                 pObjNew->pData = Abc_SopRegister( pNtkNew->pManFunc, pObj->pData );
             else if ( Abc_NtkHasBdd(pNtkNew) )
                 pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData);
@@ -558,8 +558,9 @@ Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName )
     assert( Abc_NtkIsNetlist(pNtk) );
     if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) )
         return pNet;
+//printf( "Creating net %s.\n", pName );
     // create a new net
-    pNet = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
+    pNet = Abc_NtkCreateNet( pNtk );
     if ( pName )
         Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL );
     return pNet;
@@ -581,7 +582,7 @@ Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk )
     Abc_Obj_t * pNode;
     assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
     pNode = Abc_NtkCreateNode( pNtk );   
-    if ( Abc_NtkHasSop(pNtk) )
+    if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
         pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" );
     else if ( Abc_NtkHasBdd(pNtk) )
         pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData );
@@ -610,7 +611,7 @@ Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk )
     Abc_Obj_t * pNode;
     assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) );
     pNode = Abc_NtkCreateNode( pNtk );   
-    if ( Abc_NtkHasSop(pNtk) )
+    if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
         pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" );
     else if ( Abc_NtkHasBdd(pNtk) )
         pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData );
diff --git a/src/base/abc/abcSop.c b/src/base/abc/abcSop.c
index 0836bb89..a39bd7bf 100644
--- a/src/base/abc/abcSop.c
+++ b/src/base/abc/abcSop.c
@@ -933,6 +933,139 @@ char * Abc_SopFromTruthHex( char * pTruth )
     return pSopCover;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Creates one encoder node.]
+
+  Description [Produces MV-SOP for BLIF-MV representation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues )
+{
+    char Buffer[32];
+    assert( iValue < nValues );
+    sprintf( Buffer, "d0\n%d 1\n", iValue );
+    return Abc_SopRegister( pMan, Buffer );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates one encoder node.]
+
+  Description [Produces MV-SOP for BLIF-MV representation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues )
+{
+    char * pResult;
+    Vec_Str_t * vSop;
+    int v, Counter, fFirst = 1, nBits = Extra_Base2Log(nValues);
+    assert( iBit < nBits );
+    // count the number of literals
+    Counter = 0;
+    for ( v = 0; v < nValues; v++ )
+        Counter += ( (v & (1 << iBit)) > 0 );
+    // create the cover
+    vSop = Vec_StrAlloc( 100 );
+    Vec_StrPrintStr( vSop, "d0\n" );
+    if ( Counter > 1 )
+        Vec_StrPrintStr( vSop, "(" );
+    for ( v = 0; v < nValues; v++ )
+        if ( v & (1 << iBit) )
+        {
+            if ( fFirst )
+                fFirst = 0;
+            else
+                Vec_StrPush( vSop, ',' );
+            Vec_StrPrintNum( vSop, v );
+        }
+    if ( Counter > 1 )
+        Vec_StrPrintStr( vSop, ")" );
+    Vec_StrPrintStr( vSop, " 1\n" );
+    Vec_StrPush( vSop, 0 );
+    pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+    Vec_StrFree( vSop );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the decoder node.]
+
+  Description [Produces MV-SOP for BLIF-MV representation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues )
+{
+    char * pResult;
+    Vec_Str_t * vSop;
+    int i, k;
+    assert( nValues > 1 );
+    vSop = Vec_StrAlloc( 100 );
+    for ( i = 0; i < nValues; i++ )
+    {
+        for ( k = 0; k < nValues; k++ )
+        {
+            if ( k == i )
+                Vec_StrPrintStr( vSop, "1 " );
+            else
+                Vec_StrPrintStr( vSop, "- " );
+        }
+        Vec_StrPrintNum( vSop, i );
+        Vec_StrPush( vSop, '\n' );
+    }
+    Vec_StrPush( vSop, 0 );
+    pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+    Vec_StrFree( vSop );
+    return pResult;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Creates the decover node.]
+
+  Description [Produces MV-SOP for BLIF-MV representation.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues )
+{
+    char * pResult;
+    Vec_Str_t * vSop;
+    int i, b, nBits = Extra_Base2Log(nValues);
+    assert( nValues > 1 && nValues <= (1<<nBits) );
+    vSop = Vec_StrAlloc( 100 );
+    for ( i = 0; i < nValues; i++ )
+    {
+        for ( b = 0; b < nBits; b++ )
+        {
+            Vec_StrPrintNum( vSop, (int)((i & (1 << b)) > 0) );
+            Vec_StrPush( vSop, ' ' );
+        }
+        Vec_StrPrintNum( vSop, i );
+        Vec_StrPush( vSop, '\n' );
+    }
+    Vec_StrPush( vSop, 0 );
+    pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) );
+    Vec_StrFree( vSop );
+    return pResult;
+}
+
 ////////////////////////////////////////////////////////////////////////
 ///                       END OF FILE                                ///
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c
index 353bf046..84952019 100644
--- a/src/base/abc/abcUtil.c
+++ b/src/base/abc/abcUtil.c
@@ -53,43 +53,6 @@ void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan )
     return pUserMan;
 }
 
-/**Function*************************************************************
-
-  Synopsis    [Starts the Mv-Var manager.]
-
-  Description []
-  
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ) 
-{
-    Vec_Att_t * pAttMan;
-    assert( Abc_NtkMvVar(pNtk) == NULL );
-    pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, Extra_MmFlexStart(), Extra_MmFlexStop, NULL, NULL );
-    Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan );
-}
-
-/**Function*************************************************************
-
-  Synopsis    [Stops the Mv-Var manager.]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ) 
-{ 
-    void * pUserMan;
-    pUserMan = Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 ); 
-    Extra_MmFlexStop( pUserMan );
-}
-
 /**Function*************************************************************
 
   Synopsis    [Increments the current traversal ID of the network.]
@@ -754,12 +717,6 @@ bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
     Abc_NtkIncrementTravId( pNtk );
     Abc_NtkForEachCo( pNtk, pNode, i ) 
     {
-/*
-        if ( strcmp( Abc_ObjName(pNode), "g704" ) == 0 )
-        {
-            int s = 1;
-        }
-*/
         // if the driver is complemented, this is an error
         pDriver = Abc_ObjFanin0(pNode);
         if ( Abc_ObjFaninC0(pNode) )
diff --git a/src/base/abc/module.make b/src/base/abc/module.make
index 5edf9000..7b34d8f6 100644
--- a/src/base/abc/module.make
+++ b/src/base/abc/module.make
@@ -1,4 +1,5 @@
 SRC +=    src/base/abc/abcAig.c \
+    src/base/abc/abcBlifMv.c \
     src/base/abc/abcCheck.c \
     src/base/abc/abcDfs.c \
     src/base/abc/abcFanio.c \
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index cf7cc0e9..dc185302 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -46,6 +46,7 @@ static int Abc_CommandPrintAuto      ( Abc_Frame_t * pAbc, int argc, char ** arg
 static int Abc_CommandPrintKMap      ( Abc_Frame_t * pAbc, int argc, char ** argv );
 static int Abc_CommandPrintGates     ( Abc_Frame_t * pAbc, int argc, char ** argv );
 static int Abc_CommandPrintSharing   ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPrintXCut      ( Abc_Frame_t * pAbc, int argc, char ** argv );
 
 static int Abc_CommandShow           ( Abc_Frame_t * pAbc, int argc, char ** argv );
 static int Abc_CommandShowBdd        ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -187,6 +188,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
     Cmd_CommandAdd( pAbc, "Printing",     "print_kmap",    Abc_CommandPrintKMap,        0 );
     Cmd_CommandAdd( pAbc, "Printing",     "print_gates",   Abc_CommandPrintGates,       0 );
     Cmd_CommandAdd( pAbc, "Printing",     "print_sharing", Abc_CommandPrintSharing,     0 );
+    Cmd_CommandAdd( pAbc, "Printing",     "print_xcut",    Abc_CommandPrintXCut,        0 );
 
     Cmd_CommandAdd( pAbc, "Printing",     "show",          Abc_CommandShow,             0 );
     Cmd_CommandAdd( pAbc, "Printing",     "show_bdd",      Abc_CommandShowBdd,          0 );
@@ -1394,6 +1396,64 @@ usage:
     return 1;
 }
 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+    FILE * pOut, * pErr;
+    Abc_Ntk_t * pNtk;
+    int c;
+    int fUseLibrary;
+
+    extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk );
+
+    pNtk = Abc_FrameReadNtk(pAbc);
+    pOut = Abc_FrameReadOut(pAbc);
+    pErr = Abc_FrameReadErr(pAbc);
+
+    // set defaults
+    fUseLibrary = 1;
+    Extra_UtilGetoptReset();
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
+    {
+        switch ( c )
+        {
+        case 'l':
+            fUseLibrary ^= 1;
+            break;
+        case 'h':
+            goto usage;
+        default:
+            goto usage;
+        }
+    }
+
+    if ( pNtk == NULL )
+    {
+        fprintf( pErr, "Empty network.\n" );
+        return 1;
+    }
+    Abc_NtkCrossCut( pNtk );
+    return 0;
+
+usage:
+    fprintf( pErr, "usage: print_xcut [-h]\n" );
+    fprintf( pErr, "\t        prints the size of the cross cut of the current network\n" );
+//    fprintf( pErr, "\t-l    : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" );
+    fprintf( pErr, "\t-h    : print the command usage\n");
+    return 1;
+}
+
+
 /**Function*************************************************************
 
   Synopsis    []
@@ -2057,8 +2117,9 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
     int fUseBdds;
     int fUseSops;
     int fUseCnfs;
+    int fUseMv;
     int fVerbose;
-    extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fVerbose );
+    extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose );
 
     pNtk = Abc_FrameReadNtk(pAbc);
     pOut = Abc_FrameReadOut(pAbc);
@@ -2066,16 +2127,17 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
 
     // set defaults
     nLutSize   =  8;
-    nCutsMax   =  5;
+    nCutsMax   =  4;
     nFlowIters =  1;
     nAreaIters =  1;
     fArea      =  0;
     fUseBdds   =  0;
     fUseSops   =  0;
     fUseCnfs   =  0;
+    fUseMv     =  0;
     fVerbose   =  0;
     Extra_UtilGetoptReset();
-    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscvh" ) ) != EOF )
+    while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF )
     {
         switch ( c )
         {
@@ -2135,6 +2197,9 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
         case 'c':
             fUseCnfs ^= 1;
             break;
+        case 'i':
+            fUseMv ^= 1;
+            break;
         case 'v':
             fVerbose ^= 1;
             break;
@@ -2145,7 +2210,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
         }
     }
 
-    if ( fUseBdds && fUseSops || fUseBdds && fUseCnfs || fUseSops && fUseCnfs )
+    if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 )
     {
         fprintf( pErr, "Cannot optimize two parameters at the same time.\n" );
         return 1;
@@ -2157,7 +2222,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
         return 1;
     }
 
-    if ( nCutsMax < 2 || nCutsMax >= (1<<12) )
+    if ( nCutsMax < 1 || nCutsMax >= (1<<12) )
     {
         fprintf( pErr, "Incorrect number of cuts.\n" );
         return 1;
@@ -2175,7 +2240,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
     }
 
     // get the new network
-    pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fVerbose );
+    pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose );
     if ( pNtkRes == NULL )
     {
         fprintf( pErr, "Renoding has failed.\n" );
@@ -2186,16 +2251,17 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
     return 0;
 
 usage:
-    fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbcav]\n" );
+    fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbciav]\n" );
     fprintf( pErr, "\t          transforms the AIG into a logic network with larger nodes\n" );
     fprintf( pErr, "\t          while minimizing the number of FF literals of the node SOPs\n" );
     fprintf( pErr, "\t-K num  : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize );
-    fprintf( pErr, "\t-C num  : the max number of cuts used at a node (1 < num < 2^12) [default = %d]\n", nCutsMax );
+    fprintf( pErr, "\t-C num  : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax );
     fprintf( pErr, "\t-F num  : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters );
     fprintf( pErr, "\t-A num  : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters );
     fprintf( pErr, "\t-s      : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" );
     fprintf( pErr, "\t-b      : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" );
     fprintf( pErr, "\t-c      : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" );
+    fprintf( pErr, "\t-i      : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" );
     fprintf( pErr, "\t-a      : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" );
     fprintf( pErr, "\t-v      : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); 
     fprintf( pErr, "\t-h      : print the command usage\n");
@@ -2706,7 +2772,7 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
     fVeryVerbose = 0;
     fPlaceEnable = 0;
     Extra_UtilGetoptReset();
-    while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwph" ) ) != EOF )
+    while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF )
     {
         switch ( c )
         {
@@ -2766,13 +2832,13 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
     return 0;
 
 usage:
-    fprintf( pErr, "usage: rewrite [-lzvwph]\n" );
+    fprintf( pErr, "usage: rewrite [-lzvwh]\n" );
     fprintf( pErr, "\t         performs technology-independent rewriting of the AIG\n" );
     fprintf( pErr, "\t-l     : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
     fprintf( pErr, "\t-z     : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
     fprintf( pErr, "\t-v     : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
     fprintf( pErr, "\t-w     : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" );
-    fprintf( pErr, "\t-p     : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" );
+//    fprintf( pErr, "\t-p     : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" );
     fprintf( pErr, "\t-h     : print the command usage\n");
     return 1;
 } 
@@ -8074,13 +8140,13 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
     pPars->nFlowIters  =  1;
     pPars->nAreaIters  =  2;
     pPars->DelayTarget = -1;
-    pPars->fPreprocess =  1;
+    pPars->fPreprocess =  1;//
     pPars->fArea       =  0;
     pPars->fFancy      =  0;
-    pPars->fExpRed     =  1;
+    pPars->fExpRed     =  1;//
     pPars->fLatchPaths =  0;
     pPars->fSeqMap     =  0;
-    pPars->fVerbose    =  0;
+    pPars->fVerbose    =  0;//
     // internal parameters
     pPars->fTruth      =  0;
     pPars->nLatches    =  pNtk? Abc_NtkLatchNum(pNtk) : 0;
@@ -8206,7 +8272,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
         return 1;
     }
 
-    if ( pPars->nCutsMax < 2 || pPars->nCutsMax >= (1<<12) )
+    if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) )
     {
         fprintf( pErr, "Incorrect number of cuts.\n" );
         return 1;
@@ -8279,7 +8345,7 @@ usage:
     fprintf( pErr, "usage: if [-K num] [-C num] [-F num] [-A num] [-D float] [-pafrsvh]\n" );
     fprintf( pErr, "\t           performs FPGA technology mapping of the network\n" );
     fprintf( pErr, "\t-K num   : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
-    fprintf( pErr, "\t-C num   : the max number of cuts to use (1 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
+    fprintf( pErr, "\t-C num   : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
     fprintf( pErr, "\t-F num   : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters );
     fprintf( pErr, "\t-A num   : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters );
     fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );  
diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c
index 887f6cc9..00861e1b 100644
--- a/src/base/abci/abcIf.c
+++ b/src/base/abci/abcIf.c
@@ -125,9 +125,9 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
     pIfMan = If_ManStart( pPars );
 
     // print warning about excessive memory usage
-    if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nEntrySize / (1<<30) > 0.5 )
-        printf( "Warning: The mapper is about to allocate %.1f Gb for to represent %d cuts per node.\n", 
-            1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nEntrySize / (1<<30), pPars->nCutsMax );
+    if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 )
+        printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n", 
+            1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) );
 
     // create PIs and remember them in the old nodes
     Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan );
@@ -184,7 +184,7 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
     Vec_Int_t * vCover;
     int i, nDupGates;
     // create the new network
-    if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs )
+    if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
         pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
     else if ( pIfMan->pPars->fUseSops )
         pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
@@ -214,7 +214,7 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
     if ( Abc_ObjFanoutNum(pNodeNew) == 0 )
         Abc_NtkDeleteObj( pNodeNew );
     // minimize the node
-    if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseBdds )
+    if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
         Abc_NtkSweep( pNtkNew, 0 );
     if ( pIfMan->pPars->fUseBdds )
         Abc_NtkBddReorder( pNtkNew, 0 );
@@ -251,7 +251,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
     // create a new node 
     pNodeNew = Abc_NtkCreateNode( pNtkNew );
     pCutBest = If_ObjCutBest( pIfObj );
-    if ( pIfMan->pPars->fUseCnfs )
+    if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
     {
         If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i )
             Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
@@ -269,7 +269,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
             // transform truth table into the BDD 
             pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 0 );  Cudd_Ref(pNodeNew->pData); 
         }
-        else if ( pIfMan->pPars->fUseCnfs )
+        else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
         { 
             // transform truth table into the BDD 
             pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 1 );  Cudd_Ref(pNodeNew->pData); 
@@ -329,7 +329,7 @@ Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_
     If_Cut_t * pCut;
     Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
     // get the best cut
-    pCut = If_ObjCutTriv(pIfObj);
+    pCut = If_ObjCutBest(pIfObj);
     // if the cut is visited, return the result
     if ( If_CutData(pCut) )
         return If_CutData(pCut);
@@ -367,14 +367,14 @@ Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t *
     assert( pCut->nLeaves > 1 );
     // set the leaf variables
     If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
-        If_CutSetData( If_ObjCutTriv(pLeaf), Hop_IthVar(pHopMan, i) );
+        If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) );
     // recursively compute the function while collecting visited cuts
     Vec_PtrClear( pIfMan->vTemp );
     gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); 
 //    printf( "%d ", Vec_PtrSize(p->vTemp) );
     // clean the cuts
     If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
-        If_CutSetData( If_ObjCutTriv(pLeaf), NULL );
+        If_CutSetData( If_ObjCutBest(pLeaf), NULL );
     Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i )
         If_CutSetData( pCut, NULL );
     return gFunc;
diff --git a/src/base/abci/abcRenode.c b/src/base/abci/abcRenode.c
index af3f55cf..17db7ed9 100644
--- a/src/base/abci/abcRenode.c
+++ b/src/base/abci/abcRenode.c
@@ -27,14 +27,16 @@
 ///                        DECLARATIONS                              ///
 ////////////////////////////////////////////////////////////////////////
 
+static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut );
 static int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut );
 static int Abc_NtkRenodeEvalSop( If_Cut_t * pCut );
 static int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut );
-static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut );
+static int Abc_NtkRenodeEvalMv( If_Cut_t * pCut );
 
-static reo_man * s_pReo      = NULL;
-static DdManager * s_pDd     = NULL;
-static Vec_Int_t * s_vMemory = NULL;
+static reo_man * s_pReo       = NULL;
+static DdManager * s_pDd      = NULL;
+static Vec_Int_t * s_vMemory  = NULL;
+static Vec_Int_t * s_vMemory2 = NULL;
 
 ////////////////////////////////////////////////////////////////////////
 ///                     FUNCTION DEFINITIONS                         ///
@@ -51,7 +53,7 @@ static Vec_Int_t * s_vMemory = NULL;
   SeeAlso     []
 
 ***********************************************************************/
-Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fVerbose )
+Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose )
 {
     extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
     If_Par_t Pars, * pPars = &Pars;
@@ -85,6 +87,7 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
     pPars->fUseBdds    =  fUseBdds;
     pPars->fUseSops    =  fUseSops;
     pPars->fUseCnfs    =  fUseCnfs;
+    pPars->fUseMv      =  fUseMv;
     if ( fUseBdds )
         pPars->pFuncCost = Abc_NtkRenodeEvalBdd;
     else if ( fUseSops )
@@ -94,6 +97,8 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
         pPars->fArea = 1;
         pPars->pFuncCost = Abc_NtkRenodeEvalCnf;
     }
+    else if ( fUseMv )
+        pPars->pFuncCost = Abc_NtkRenodeEvalMv;
     else
         pPars->pFuncCost = Abc_NtkRenodeEvalAig;
 
@@ -108,7 +113,8 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
     else
     {
         assert( s_vMemory == NULL );
-        s_vMemory = Vec_IntAlloc( 1 << 16 );
+        s_vMemory  = Vec_IntAlloc( 1 << 16 );
+        s_vMemory2 = Vec_IntAlloc( 1 << 16 );
     }
 
     // perform mapping/renoding
@@ -125,12 +131,43 @@ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nF
     else
     {
         Vec_IntFree( s_vMemory );
+        Vec_IntFree( s_vMemory2 );
         s_vMemory = NULL;
+        s_vMemory2 = NULL;
     }
 
     return pNtkNew;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Computes the cost based on the factored form.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Abc_NtkRenodeEvalAig( If_Cut_t * pCut )
+{
+    Kit_Graph_t * pGraph;
+    int i, nNodes;
+    pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory );
+    if ( pGraph == NULL )
+    {
+        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+            pCut->pPerm[i] = 100;
+        return IF_COST_MAX;
+    }
+    nNodes = Kit_GraphNodeNum( pGraph );
+    for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
+        pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) );
+    Kit_GraphFree( pGraph );
+    return nNodes;
+}
+
 /**Function*************************************************************
 
   Synopsis    [Computes the cost based on the BDD size after reordering.]
@@ -178,7 +215,7 @@ int Abc_NtkRenodeEvalSop( If_Cut_t * pCut )
         pCut->pPerm[i] = 1;
     RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 1 );
     if ( RetValue == -1 )
-        return ABC_INFINITY;
+        return IF_COST_MAX;
     assert( RetValue == 0 || RetValue == 1 );
     return Vec_IntSize( s_vMemory );
 }
@@ -197,12 +234,13 @@ int Abc_NtkRenodeEvalSop( If_Cut_t * pCut )
 int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
 {
     int i, RetValue, nClauses;
+    // set internal mapper parameters
     for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
         pCut->pPerm[i] = 1;
     // compute ISOP for the positive phase
     RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
     if ( RetValue == -1 )
-        return ABC_INFINITY;
+        return IF_COST_MAX;
     assert( RetValue == 0 || RetValue == 1 );
     nClauses = Vec_IntSize( s_vMemory );
     // compute ISOP for the negative phase
@@ -210,7 +248,7 @@ int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
     RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
     Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
     if ( RetValue == -1 )
-        return ABC_INFINITY;
+        return IF_COST_MAX;
     assert( RetValue == 0 || RetValue == 1 );
     nClauses += Vec_IntSize( s_vMemory );
     return nClauses;
@@ -218,7 +256,7 @@ int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
 
 /**Function*************************************************************
 
-  Synopsis    [Computes the cost based on the factored form.]
+  Synopsis    [Computes the cost of MV-SOP of the cut function.]
 
   Description []
                
@@ -227,22 +265,29 @@ int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut )
   SeeAlso     []
 
 ***********************************************************************/
-int Abc_NtkRenodeEvalAig( If_Cut_t * pCut )
+int Abc_NtkRenodeEvalMv( If_Cut_t * pCut )
 {
-    Kit_Graph_t * pGraph;
-    int i, nNodes;
-    pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory );
-    if ( pGraph == NULL )
-    {
-        for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
-            pCut->pPerm[i] = 100;
-        return ABC_INFINITY;
-    }
-    nNodes = Kit_GraphNodeNum( pGraph );
+    int i, RetValue;
+    // set internal mapper parameters
     for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
-        pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) );
-    Kit_GraphFree( pGraph );
-    return nNodes;
+        pCut->pPerm[i] = 1;
+    // compute ISOP for the positive phase
+    RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 );
+    if ( RetValue == -1 )
+        return IF_COST_MAX;
+    assert( RetValue == 0 || RetValue == 1 );
+    // compute ISOP for the negative phase
+    Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+    RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 );
+    Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) );
+    if ( RetValue == -1 )
+        return IF_COST_MAX;
+    assert( RetValue == 0 || RetValue == 1 );
+    // return the cost of the cut 
+    RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 );
+    if ( RetValue >= IF_COST_MAX )
+        return IF_COST_MAX;
+    return RetValue;
 }
 
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c
index 92691d6c..845f9d77 100644
--- a/src/base/cmd/cmd.c
+++ b/src/base/cmd/cmd.c
@@ -1265,7 +1265,7 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv )
     }
 
     // write out the current network
-    pNetlist = Abc_NtkToNetlist(pNtk,0);
+    pNetlist = Abc_NtkToNetlist(pNtk);
     if ( pNetlist == NULL )
     {
         fprintf( pErr, "Cannot produce the intermediate network.\n" );
@@ -1406,7 +1406,7 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv )
     }
 
     // write out the current network
-    pNetlist = Abc_NtkToNetlist(pNtk,0);
+    pNetlist = Abc_NtkToNetlist(pNtk);
     if ( pNetlist == NULL )
     {
         fprintf( pErr, "Cannot produce the intermediate network.\n" );
@@ -1552,7 +1552,7 @@ int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv )
     }
 
     // write out the current network
-    pNetlist = Abc_NtkToNetlist(pNtk,0);
+    pNetlist = Abc_NtkToNetlist(pNtk);
     if ( pNetlist == NULL )
     {
         fprintf( pErr, "Cannot produce the intermediate network.\n" );
diff --git a/src/base/io/io.h b/src/base/io/io.h
index 472e7b2d..7e23b6e4 100644
--- a/src/base/io/io.h
+++ b/src/base/io/io.h
@@ -95,8 +95,7 @@ extern void               Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName,
 extern void               Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches );
 extern void               Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk );
 /*=== abcWriteBlifMv.c ==========================================================*/ 
-extern void               Io_WriteBlifMvDesign( Abc_Lib_t * pLib, char * FileName );
-extern void               Io_WriteBlifMvNetlist( Abc_Ntk_t * pNtk, char * FileName );
+extern void               Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName );
 /*=== abcWriteBench.c =========================================================*/
 extern int                Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName );
 /*=== abcWriteCnf.c ===========================================================*/
diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c
index 3e09caf0..dc72c591 100644
--- a/src/base/io/ioReadBlifMv.c
+++ b/src/base/io/ioReadBlifMv.c
@@ -62,11 +62,13 @@ struct Io_MvMan_t_
 {
     // general info about file
     int                  fBlifMv;      // the file is BLIF-MV
+    int                  fUseReset;    // the reset circuitry is added
     char *               pFileName;    // the name of the file
     char *               pBuffer;      // the contents of the file
     Vec_Ptr_t *          vLines;       // the line beginnings
     // the results of reading
     Abc_Lib_t *          pDesign;      // the design under construction
+    int                  nNDnodes;     // the counter of ND nodes
     // intermediate storage for models
     Vec_Ptr_t *          vModels;      // vector of models
     Io_MvMod_t *         pLatest;      // the current model
@@ -99,6 +101,7 @@ static int               Io_MvParseLineMv( Io_MvMod_t * p, char * pLine );
 static int               Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset );
 static int               Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine );
 static int               Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens );
+static Io_MvVar_t *      Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar );
 
 static int               Io_MvCharIsSpace( char s )  { return s == ' ' || s == '\t' || s == '\r' || s == '\n';  }
 static int               Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!';  }
@@ -127,7 +130,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
     Abc_Ntk_t * pNtk;
     Abc_Lib_t * pDesign;
     char * pDesignName;
-    int i;
+    int RetValue, i;
 
     // check that the file is available
     pFile = fopen( pFileName, "rb" );
@@ -141,6 +144,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
     // start the file reader
     p = Io_MvAlloc();
     p->fBlifMv   = fBlifMv;
+    p->fUseReset = 0;
     p->pFileName = pFileName;
     p->pBuffer   = Io_MvLoadFile( pFileName );
     if ( p->pBuffer == NULL )
@@ -152,6 +156,9 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
     pDesignName  = Extra_FileNameGeneric( pFileName );
     p->pDesign   = Abc_LibCreate( pDesignName );
     free( pDesignName );
+    // free the HOP manager
+    Hop_ManStop( p->pDesign->pManFunc );
+    p->pDesign->pManFunc = NULL;
     // prepare the file for parsing
     Io_MvReadPreparse( p );
     // parse interfaces of each network
@@ -163,6 +170,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
     if ( pDesign == NULL )
         return NULL;
     Io_MvFree( p );
+// pDesign should be linked to all models of the design
 
     // make sure that everything is okay with the network structure
     if ( fCheck )
@@ -177,11 +185,19 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
             }
         }
     }
-// pDesign should be linked to all models of the design
+
+//Abc_LibPrint( pDesign );
+
+    // detect top-level model
+    RetValue = Abc_LibFindTopLevelModels( pDesign );
+    pNtk = Vec_PtrEntry( pDesign->vTops, 0 );
+    if ( RetValue > 1 )
+        printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
+            Vec_PtrSize(pDesign->vTops), pNtk->pName );
 
     // extract the master network
-    pNtk = Vec_PtrEntry( pDesign->vModules, 0 );
     pNtk->pDesign = pDesign;
+    pDesign->pManFunc = NULL;
 
     // verify the design for cyclic dependence
     assert( Vec_PtrSize(pDesign->vModules) > 0 );
@@ -195,10 +211,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
     else
         Abc_NtkIsAcyclicHierarchy( pNtk );
 
-//Io_WriteBlifMvDesign( pDesign, "_temp_.mv" );
-//Abc_LibPrint( pDesign );
-//Abc_LibFree( pDesign );
-//return NULL;
+//Io_WriteBlifMv( pNtk, "_temp_.mv" );
     return pNtk;
 }
 
@@ -691,16 +704,18 @@ static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p )
                 return NULL;
             }
             // create binary latch with 1-data and 0-init
-            pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv );
+            if ( p->fUseReset ) 
+                pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv );
         }
         // parse the latches
         Vec_PtrForEachEntry( pMod->vLatches, pLine, k )
             if ( !Io_MvParseLineLatch( pMod, pLine ) )
                 return NULL;
         // parse the reset lines
-        Vec_PtrForEachEntry( pMod->vResets, pLine, k )
-            if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) )
-                return NULL;
+        if ( p->fUseReset )
+            Vec_PtrForEachEntry( pMod->vResets, pLine, k )
+                if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) )
+                    return NULL;
         // parse the nodes
         if ( p->fBlifMv )
         {
@@ -721,6 +736,9 @@ static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p )
         // finalize the network
         Abc_NtkFinalizeRead( pMod->pNtk );
     }
+    if ( p->nNDnodes )
+//        printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes );
+        printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes );
     // return the network
     pDesign = p->pDesign;
     p->pDesign = NULL;
@@ -822,7 +840,7 @@ static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine )
 static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
 {
     Vec_Ptr_t * vTokens = p->pMan->vTokens;
-    Abc_Obj_t * pObj, * pMux, * pNet;
+    Abc_Obj_t * pObj, * pNet;
     char * pToken;
     int Init;
     Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
@@ -838,33 +856,35 @@ static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
     {
         pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Vec_PtrEntry(vTokens,2) );
         // get initial value
-        if ( Vec_PtrSize(vTokens) > 3 )
-            Init = atoi( Vec_PtrEntry(vTokens,3) );
+        if ( p->pMan->fBlifMv )
+            Abc_LatchSetInit0( pObj );
         else
-            Init = 2;
-        if ( Init < 0 || Init > 2 )
         {
-            sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) );
-            return 0;
+            if ( Vec_PtrSize(vTokens) > 3 )
+                Init = atoi( Vec_PtrEntry(vTokens,3) );
+            else
+                Init = 2;
+            if ( Init < 0 || Init > 2 )
+            {
+                sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) );
+                return 0;
+            }
+            if ( Init == 0 )
+                Abc_LatchSetInit0( pObj );
+            else if ( Init == 1 )
+                Abc_LatchSetInit1( pObj );
+            else // if ( Init == 2 )
+                Abc_LatchSetInitDc( pObj );
         }
-        if ( Init == 0 )
-            Abc_LatchSetInit0( pObj );
-        else if ( Init == 1 )
-            Abc_LatchSetInit1( pObj );
-        else // if ( Init == 2 )
-            Abc_LatchSetInitDc( pObj );
     }
     else
     {
-        // get the net corresponding to output of reset latch
-        pNet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch));
-        assert( Abc_ObjIsNet(pNet) );
-        // create mux
-        pMux = Io_ReadCreateResetMux( p->pNtk, Abc_ObjName(pNet), Vec_PtrEntry(vTokens,1), p->pMan->fBlifMv );
-        // get the net of mux output
-        pNet = Abc_ObjFanout0(pMux);
+        // get the net corresponding to the output of the latch
+        pNet = Abc_NtkFindOrCreateNet( p->pNtk, Vec_PtrEntry(vTokens,2) );
+        // get the net corresponding to the latch output (feeding into reset MUX)
+        pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") );
         // create latch
-        pObj = Io_ReadCreateLatch( p->pNtk, Abc_ObjName(pNet), Vec_PtrEntry(vTokens,2) );
+        pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) );
         Abc_LatchSetInit0( pObj );
     }
     return 1;
@@ -1180,7 +1200,7 @@ static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t *
     // prepare the place for the cover
     Vec_StrClear( vFunc );
     // write the number of values
-    Io_MvWriteValues( pNode, vFunc );
+//    Io_MvWriteValues( pNode, vFunc );
     // get the first token
     pFirst = Vec_PtrEntry( vTokens2, 0 );
     if ( pFirst[0] == '.' )
@@ -1215,6 +1235,60 @@ static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t *
     return Vec_StrArray( vFunc );
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Adds reset circuitry corresponding to latch with pName.]
+
+  Description [Returns the reset node's net.]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName )
+{
+    char Buffer[50];
+    Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet;
+    Io_MvVar_t * pVar;
+    // make sure the reset latch exists
+    assert( p->pResetLatch != NULL );
+    // get the reset net
+    pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch));
+    // get the output net
+    pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
+    // get the data nets
+    pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") );
+    pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") );
+    // duplicate MV variables
+    if ( Abc_NtkMvVar(p->pNtk) )
+    {
+        pVar = Abc_ObjMvVar( pOutNet );
+        Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
+        Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
+    }
+    // create the node
+    pNode = Abc_NtkCreateNode( p->pNtk );
+    // create the output net
+    Abc_ObjAddFanin( pOutNet, pNode );
+    // create the function
+    if ( p->pMan->fBlifMv )
+    {
+//        Vec_Att_t * p = Abc_NtkMvVar( pNtk );
+        int nValues = Abc_ObjMvVarNum(pOutNet);
+//        sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues );
+        sprintf( Buffer, "1 - - =1\n0 - - =2\n" );
+        pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, Buffer );
+    }
+    else
+        pNode->pData = Abc_SopCreateMux( p->pNtk->pManFunc );
+    // add nets
+    Abc_ObjAddFanin( pNode, pResetLONet );
+    Abc_ObjAddFanin( pNode, pData1Net );
+    Abc_ObjAddFanin( pNode, pData0Net );
+    return pData0Net;
+}
+
 /**Function*************************************************************
 
   Synopsis    [Parses the nodes line.]
@@ -1241,19 +1315,15 @@ static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Pt
             sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName );
             return 0;
         }
+/*
         if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) )
         {
             sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName );
             return 0;
         }
-        // get the latch input
-        pNode = Abc_ObjFanin0(Abc_ObjFanin0(Abc_ObjFanin0(pNet)));
-        assert( Abc_ObjIsBi(pNode) );
-        // get the MUX feeding into the latch
-        pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNode));
-        assert( Abc_ObjFaninNum(pNode) == 3 );
-        // get the corresponding fanin net
-        pNet = Abc_ObjFanin( pNode, 2 );
+*/
+        // construct the reset circuit and get the reset net feeding into it
+        pNet = Io_MvParseAddResetCircuit( p, pName );
         // create fanins
         pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs );
         assert( nInputs == Vec_PtrSize(vTokens) - 2 );
@@ -1292,6 +1362,7 @@ static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset )
 {
     Vec_Ptr_t * vTokens = p->pMan->vTokens;
     Vec_Ptr_t * vTokens2 = p->pMan->vTokens2;
+    Abc_Obj_t * pNet;
     char * pName, * pFirst, * pArrow;
     int nInputs, nOutputs, nLiterals, nLines, i;
     assert( p->pMan->fBlifMv );
@@ -1341,27 +1412,23 @@ static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset )
     nLines = nLiterals / (nInputs + nOutputs);
     if ( nInputs == 0 && nLines > 1 )
     {
-        Abc_Obj_t * pNode, * pNet;
         // add the outputs to the PIs
         for ( i = 0; i < nOutputs; i++ )
         {
             pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i );
-            fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName );
             // get the net corresponding to this node
             pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName);
             if ( fReset )
             {
-                // get the latch input
-                pNode = Abc_ObjFanin0(Abc_ObjFanin0(Abc_ObjFanin0(pNet)));
-                assert( Abc_ObjIsBi(pNode) );
-                // get the MUX feeding into the latch
-                pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNode));
-                assert( Abc_ObjFaninNum(pNode) == 3 );
-                // get the corresponding fanin net
-                pNet = Abc_ObjFanin( pNode, 2 );
+                assert( p->pResetLatch != NULL );
+                // construct the reset circuit and get the reset net feeding into it
+                pNet = Io_MvParseAddResetCircuit( p, pName );
             }
-//            Io_ReadCreatePi( p->pNtk, pName );
-            Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) );
+            // add the new PI node
+//            Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) );
+//            fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName );
+            p->pMan->nNDnodes++;
+            Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) );
         }
         return 1;
     }
@@ -1437,7 +1504,7 @@ static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins )
             sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity );
             return NULL;
         }
-        // parse one product product
+        // parse one product 
         Vec_StrAppend( vFunc, pProduct );
         Vec_StrPush( vFunc, ' ' );
         Vec_StrPush( vFunc, pOutput[0] );
@@ -1487,6 +1554,40 @@ static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine )
     return 1;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Duplicate the MV variable.]
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar )
+{
+    Extra_MmFlex_t * pFlex;
+    Io_MvVar_t * pVarDup;
+    int i;
+    if ( pVar == NULL )
+        return NULL;
+    pFlex = Abc_NtkMvVarMan( pNtk );
+    assert( pFlex != NULL );
+    pVarDup = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
+    pVarDup->nValues = pVar->nValues;
+    pVarDup->pNames = NULL;
+    if ( pVar->pNames == NULL )
+        return pVarDup;
+    pVarDup->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues );
+    for ( i = 0; i < pVar->nValues; i++ )
+    {
+        pVarDup->pNames[i] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 );
+        strcpy( pVarDup->pNames[i], pVar->pNames[i] );
+    }
+    return pVarDup;
+}
+
 
 #include "mio.h"
 #include "main.h"
diff --git a/src/base/io/ioReadVerilog.c b/src/base/io/ioReadVerilog.c
index 090cf254..c64e330c 100644
--- a/src/base/io/ioReadVerilog.c
+++ b/src/base/io/ioReadVerilog.c
@@ -45,14 +45,21 @@ Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck )
 {
     Abc_Ntk_t * pNtk;
     Abc_Lib_t * pDesign;
+    int RetValue;
 
     // parse the verilog file
     pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 );
     if ( pDesign == NULL )
         return NULL;
-/*
+
+    // detect top-level model
+    RetValue = Abc_LibFindTopLevelModels( pDesign );
+    pNtk = Vec_PtrEntry( pDesign->vTops, 0 );
+    if ( RetValue > 1 )
+        printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
+            Vec_PtrSize(pDesign->vTops), pNtk->pName );
+
     // extract the master network
-    pNtk = Vec_PtrEntryLast( pDesign->vModules );
     pNtk->pDesign = pDesign;
     pDesign->pManFunc = NULL;
 
@@ -67,35 +74,11 @@ Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck )
     }
     else
     {
-        // bring the root model to the beginning
-        for ( i = Vec_PtrSize(pDesign->vModules) - 2; i >= 0; i-- )
-            Vec_PtrWriteEntry(pDesign->vModules, i+1, Vec_PtrEntry(pDesign->vModules, i) );
-        Vec_PtrWriteEntry(pDesign->vModules, 0, pNtk );
         // check that there is no cyclic dependency
         Abc_NtkIsAcyclicHierarchy( pNtk );
     }
-*/
-    // extract the master network
-    pNtk = Vec_PtrEntry( pDesign->vModules, 0 );
-    pNtk->pDesign = pDesign;
-    pDesign->pManFunc = NULL;
 
 //Io_WriteVerilog( pNtk, "_temp.v" );
-
-    // verify the design for cyclic dependence
-    assert( Vec_PtrSize(pDesign->vModules) > 0 );
-    if ( Vec_PtrSize(pDesign->vModules) == 1 )
-    {
-//        printf( "Warning: The design is not hierarchical.\n" );
-        Abc_LibFree( pDesign, pNtk );
-        pNtk->pDesign = NULL;
-        pNtk->pSpec = Extra_UtilStrsav( pFileName );
-    }
-    else
-    {
-        // check that there is no cyclic dependency
-        Abc_NtkIsAcyclicHierarchy( pNtk );
-    }
     return pNtk;
 }
 
diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c
index 0ac3181a..9845fbab 100644
--- a/src/base/io/ioUtil.c
+++ b/src/base/io/ioUtil.c
@@ -173,27 +173,6 @@ Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck )
         return NULL;
     if ( !Abc_NtkIsNetlist(pNtk) )
         return pNtk;
-    // consider the case of BLIF-MV
-    if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
-    {
-        extern Abc_Ntk_t * Abc_NtkConvertBlifMv( Abc_Ntk_t * pNtk );
-Abc_NtkPrintStats( stdout, pNtk, 0 );
-/*
-{
-    FILE * pFile = fopen( "_temp_.mv", "w" );
-    Io_NtkWriteBlifMv( pFile, pNtk );
-    fclose( pFile );
-}
-*/
-        pNtk = Abc_NtkConvertBlifMv( pTemp = pNtk );
-        Abc_NtkDelete( pTemp );
-        if ( pNtk == NULL )
-        {
-            fprintf( stdout, "Converting BLIF-MV has failed.\n" );
-            return NULL;
-        }
-        return pNtk;
-    }
     // flatten logic hierarchy
     assert( Abc_NtkIsNetlist(pNtk) );
     if ( Abc_NtkWhiteboxNum(pNtk) > 0 )
@@ -218,69 +197,19 @@ Abc_NtkPrintStats( stdout, pNtk, 0 );
             return NULL;
         }
     }
-    // convert the netlist into the logic network
-    pNtk = Abc_NtkToLogic( pTemp = pNtk );
-    Abc_NtkDelete( pTemp );
-    if ( pNtk == NULL )
-    {
-        fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" );
-        return NULL;
-    }
-    return pNtk;
-}
-
-/**Function*************************************************************
-
-  Synopsis    [Read the network from a file.]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-Abc_Ntk_t * Io_ReadHie( char * pFileName, Io_FileType_t FileType, int fCheck )
-{
-    Abc_Ntk_t * pNtk, * pTemp;
-    // detect the file type
-    if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF )
-        pNtk = Io_ReadBlifMv( pFileName, 0, fCheck );
-//    else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
-//        pNtk = Io_ReadBlifMv( pFileName, 1, fCheck );
-    else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG )
-        pNtk = Io_ReadVerilog( pFileName, fCheck );
-    else
-    {
-        printf( "Wrong file type.\n" );
-        return NULL;
-    }
-    if ( pNtk == NULL )
-        return NULL;
-//    printf( "\n" );
-    // flatten logic hierarchy
-    assert( Abc_NtkIsNetlist(pNtk) );
-    if ( Abc_NtkWhiteboxNum(pNtk) > 0 )
-    {
-        pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk );
-        Abc_NtkDelete( pTemp );
-        if ( pNtk == NULL )
-        {
-            fprintf( stdout, "Flattening logic hierarchy has failed.\n" );
-            return NULL;
-        }
-    }
-    // convert blackboxes
-    if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+    // consider the case of BLIF-MV
+    if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
     {
-        printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) );
-        pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk );
+//Abc_NtkPrintStats( stdout, pNtk, 0 );
+//    Io_WriteBlifMv( pNtk, "_temp_.mv" );
+        pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk );
         Abc_NtkDelete( pTemp );
         if ( pNtk == NULL )
         {
-            fprintf( stdout, "Converting blackboxes has failed.\n" );
+            fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" );
             return NULL;
         }
+        return pNtk;
     }
     // convert the netlist into the logic network
     pNtk = Abc_NtkToLogic( pTemp = pNtk );
@@ -349,7 +278,13 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
         Io_WriteGml( pNtk, pFileName );
         return;
     }
-
+/*
+    if ( FileType == IO_FILE_BLIFMV )
+    {
+        Io_WriteBlifMv( pNtk, pFileName );
+        return;
+    }
+*/
     // convert logic network into netlist
     if ( FileType == IO_FILE_PLA )
     {
@@ -359,15 +294,17 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
             return;
         }
         if ( Abc_NtkIsComb(pNtk) )
-            pNtkTemp = Abc_NtkToNetlist( pNtk, 1 );
+            pNtkTemp = Abc_NtkToNetlist( pNtk );
         else
         {
             fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" );
             pNtkCopy = Abc_NtkDup( pNtk );
             Abc_NtkMakeComb( pNtkCopy );
-            pNtkTemp = Abc_NtkToNetlist( pNtk, 1 );
+            pNtkTemp = Abc_NtkToNetlist( pNtk );
             Abc_NtkDelete( pNtkCopy );
         }
+        if ( !Abc_NtkToSop( pNtk, 1 ) )
+            return;
     }
     else if ( FileType == IO_FILE_BENCH )
     {
@@ -379,7 +316,7 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
         pNtkTemp = Abc_NtkToNetlistBench( pNtk );
     }
     else
-        pNtkTemp = Abc_NtkToNetlist( pNtk, 0 );
+        pNtkTemp = Abc_NtkToNetlist( pNtk );
 
     if ( pNtkTemp == NULL )
     {
@@ -393,6 +330,12 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
             Abc_NtkToSop( pNtkTemp, 0 );
         Io_WriteBlif( pNtkTemp, pFileName, 1 );
     }
+    else if ( FileType == IO_FILE_BLIFMV )
+    {
+        if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) )
+            return;
+        Io_WriteBlifMv( pNtkTemp, pFileName );
+    }
     else if ( FileType == IO_FILE_BENCH )
         Io_WriteBench( pNtkTemp, pFileName );
     else if ( FileType == IO_FILE_PLA )
@@ -439,6 +382,8 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
     assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) );
     if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF )
         pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 );
+    else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV )
+        pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 );
     else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG )
         pNtkBase = Io_ReadVerilog( pBaseName, 1 );
     else 
@@ -446,6 +391,7 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
     if ( pNtkBase == NULL )
         return;
 
+    // flatten logic hierarchy if present
     if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 )
     {
         pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase );
@@ -455,10 +401,27 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
     }
 
     // reintroduce the boxes into the netlist
-    if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
+    if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) 
+    {
+        if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
+        {
+            printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" );
+            Abc_NtkDelete( pNtkBase );
+            return;
+        }
+        // convert the current network to BLIF-MV
+        assert( !Abc_NtkIsNetlist(pNtk) );
+        pNtkResult = Abc_NtkToNetlist( pNtk );
+        if ( !Abc_NtkConvertToBlifMv( pNtkResult ) )
+            return;
+        // reintroduce the network
+        pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult );
+        Abc_NtkDelete( pNtkTemp );
+    }
+    else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 )
     {
         // derive the netlist
-        pNtkResult = Abc_NtkToNetlist( pNtk, 0 );
+        pNtkResult = Abc_NtkToNetlist( pNtk );
         pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult );
         Abc_NtkDelete( pNtkTemp );
         if ( pNtkResult )
@@ -467,7 +430,7 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
     else
     {
         printf( "Warning: The output network does not contain blackboxes.\n" );
-        pNtkResult = Abc_NtkToNetlist( pNtk, 0 );
+        pNtkResult = Abc_NtkToNetlist( pNtk );
     }
     Abc_NtkDelete( pNtkBase );
     if ( pNtkResult == NULL )
@@ -486,6 +449,10 @@ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName )
             Abc_NtkToAig( pNtkResult );
         Io_WriteVerilog( pNtkResult, pFileName );
     }
+    else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV )
+    {
+        Io_WriteBlifMv( pNtkResult, pFileName );
+    }
     else 
         fprintf( stderr, "Unknown output file format.\n" );
 
@@ -614,59 +581,24 @@ Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO )
 Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv )
 {
     Abc_Obj_t * pLatch, * pNode;
+    Abc_Obj_t * pNetLI, * pNetLO;
     // create latch with 0 init value
-    pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" );
+//    pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" );
+    pNetLI = Abc_NtkCreateNet( pNtk );
+    pNetLO = Abc_NtkCreateNet( pNtk );
+    Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL );
+    Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL );
+    pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) );
+    // set the initial value
     Abc_LatchSetInit0( pLatch );
     // feed the latch with constant1- node
-    pNode = Abc_NtkCreateNode( pNtk );   
-    pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" );
+//    pNode = Abc_NtkCreateNode( pNtk );   
+//    pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" );
+    pNode = Abc_NtkCreateNodeConst1( pNtk );
     Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode );
     return pLatch;
 }
 
-/**Function*************************************************************
-
-  Synopsis    [Create a latch with the given input/output.]
-
-  Description [By default, the latch value is unknown (ABC_INIT_NONE).]
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-Abc_Obj_t * Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv )
-{
-    char Buffer[50];
-    Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pLINet;
-    // get the reset output net
-    pResetLONet = Abc_NtkFindNet( pNtk, pResetLO );
-    assert( pResetLONet );
-    // get the latch input net
-    pData1Net = Abc_NtkFindOrCreateNet( pNtk, pDataLI );
-    // create Data0 net (coming from reset node)
-    pData0Net = Abc_NtkFindOrCreateNet( pNtk, Abc_ObjNameSuffix(pData1Net, "_reset") );
-    // create the node
-    pNode = Abc_NtkCreateNode( pNtk );
-    if ( fBlifMv )
-    {
-//        Vec_Att_t * p = Abc_NtkMvVar( pNtk );
-        int nValues = Abc_ObjMvVarNum(pData1Net);
-        sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues );
-        pNode->pData = Abc_SopRegister( pNtk->pManFunc, Buffer );
-    }
-    else
-        pNode->pData = Abc_SopCreateMux( pNtk->pManFunc );
-    // add nets
-    Abc_ObjAddFanin( pNode, pResetLONet );
-    Abc_ObjAddFanin( pNode, pData1Net );
-    Abc_ObjAddFanin( pNode, pData0Net );
-    // create the output net
-    pLINet = Abc_NtkFindOrCreateNet( pNtk, Abc_ObjNameSuffix(pData1Net, "_mux") );
-    Abc_ObjAddFanin( pLINet, pNode );
-    return pNode;
-}
-
 /**Function*************************************************************
 
   Synopsis    [Create node and the net driven by it.]
diff --git a/src/base/io/ioWriteAiger.c b/src/base/io/ioWriteAiger.c
index 3b7d78ca..00768356 100644
--- a/src/base/io/ioWriteAiger.c
+++ b/src/base/io/ioWriteAiger.c
@@ -225,7 +225,7 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName )
     // write the buffer
     fwrite( pBuffer, 1, Pos, pFile );
     free( pBuffer );
-
+/*
     // write the symbol table
     // write PIs
     Abc_NtkForEachPi( pNtk, pObj, i )
@@ -236,7 +236,7 @@ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName )
     // write POs
     Abc_NtkForEachPo( pNtk, pObj, i )
         fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) );
-
+*/
     // write the comment
     fprintf( pFile, "c\n" );
     fprintf( pFile, "%s\n", pNtk->pName );
diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c
index 417fe2a3..c0c29d65 100644
--- a/src/base/io/ioWriteBlif.c
+++ b/src/base/io/ioWriteBlif.c
@@ -56,7 +56,7 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
 {
     Abc_Ntk_t * pNtkTemp;
     // derive the netlist
-    pNtkTemp = Abc_NtkToNetlist(pNtk,0);
+    pNtkTemp = Abc_NtkToNetlist(pNtk);
     if ( pNtkTemp == NULL )
     {
         fprintf( stdout, "Writing BLIF has failed.\n" );
@@ -80,6 +80,8 @@ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
 void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
 {
     FILE * pFile;
+    Abc_Ntk_t * pNtkTemp;
+    int i;
     assert( Abc_NtkIsNetlist(pNtk) );
     // start writing the file
     pFile = fopen( FileName, "w" );
@@ -96,18 +98,6 @@ void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches )
     // write the hierarchy if present
     if ( Abc_NtkBlackboxNum(pNtk) > 0 )
     {
-        Abc_Ntk_t * pNtkTemp;
-        int i;
-/*
-        Abc_Obj_t * pObj;
-        Abc_NtkForEachBlackbox( pNtk, pObj, i )
-        {
-            pNtkTemp = pObj->pData;
-            assert( pNtkTemp != NULL && Abc_NtkHasBlackbox(pNtkTemp) );
-            fprintf( pFile, "\n\n" );
-            Io_NtkWrite( pFile, pNtkTemp, fWriteLatches );
-        }
-*/
         Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i )
         {
             if ( pNtkTemp == pNtk )
diff --git a/src/base/io/ioWriteBlifMv.c b/src/base/io/ioWriteBlifMv.c
index 597ca945..775a2e07 100644
--- a/src/base/io/ioWriteBlifMv.c
+++ b/src/base/io/ioWriteBlifMv.c
@@ -26,7 +26,7 @@
 ///                        DECLARATIONS                              ///
 ////////////////////////////////////////////////////////////////////////
 
-void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk );
 static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk );
 static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk );
 static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk );
@@ -52,49 +52,34 @@ static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode );
   SeeAlso     []
 
 ***********************************************************************/
-void Io_WriteBlifMvDesign( Abc_Lib_t * pLib, char * FileName )
+void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName )
 {
     FILE * pFile;
-    Abc_Ntk_t * pNtk;
+    Abc_Ntk_t * pNtkTemp;
     int i;
+    assert( Abc_NtkIsNetlist(pNtk) );
+    assert( Abc_NtkHasBlifMv(pNtk) );
     // start writing the file
     pFile = fopen( FileName, "w" );
     if ( pFile == NULL )
     {
-        fprintf( stdout, "Io_WriteBlifMvDesign(): Cannot open the output file.\n" );
-        return;
-    }
-    fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pLib->pName, Extra_TimeStamp() );
-    // write the master network
-    Vec_PtrForEachEntry( pLib->vModules, pNtk, i )
-        Io_NtkWriteBlifMv( pFile, pNtk );
-    fclose( pFile );
-}
-
-/**Function*************************************************************
-
-  Synopsis    [Write the network into a BLIF file with the given name.]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-void Io_WriteBlifMvNetlist( Abc_Ntk_t * pNtk, char * FileName )
-{
-    FILE * pFile;
-    // start writing the file
-    pFile = fopen( FileName, "w" );
-    if ( pFile == NULL )
-    {
-        fprintf( stdout, "Io_WriteMvNetlist(): Cannot open the output file.\n" );
+        fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" );
         return;
     }
     fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
     // write the master network
     Io_NtkWriteBlifMv( pFile, pNtk );
+    // write the remaining networks
+    if ( pNtk->pDesign )
+    {
+        Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i )
+        {
+            if ( pNtkTemp == pNtk )
+                continue;
+            fprintf( pFile, "\n\n" );
+            Io_NtkWriteBlifMv( pFile, pNtkTemp );
+        }
+    }
     fclose( pFile );
 }
 
@@ -185,7 +170,7 @@ void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk )
             Io_NtkWriteBlifMvLatch( pFile, pLatch );
         fprintf( pFile, "\n" );
     }
-
+/*
     // write the subcircuits
     assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
     if ( Abc_NtkBlackboxNum(pNtk) > 0 )
@@ -195,6 +180,18 @@ void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk )
             Io_NtkWriteBlifMvSubckt( pFile, pNode );
         fprintf( pFile, "\n" );
     }
+*/
+    if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 )
+    {
+        fprintf( pFile, "\n" );
+        Abc_NtkForEachBox( pNtk, pNode, i )
+        {
+            if ( Abc_ObjIsLatch(pNode) )
+                continue;
+            Io_NtkWriteBlifMvSubckt( pFile, pNode );
+        }
+        fprintf( pFile, "\n" );
+    }
 
     // write each internal node
     pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
@@ -414,26 +411,32 @@ void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode )
     Abc_Obj_t * pFanin;
     char * pCur;
     int nValues, iFanin, i;
-    fprintf( pFile, "\n" );
+
     // write .mv directives for the fanins
-    pCur = Abc_ObjData(pNode);
+    fprintf( pFile, "\n" );
     Abc_ObjForEachFanin( pNode, pFanin, i )
     {
-        nValues = atoi(pCur);
+//        nValues = atoi(pCur);
+        nValues = Abc_ObjMvVarNum( pFanin );
         if ( nValues > 2 )
             fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues );
-        while ( *pCur++ != ' ' );
+//        while ( *pCur++ != ' ' );
     }
+
     // write .mv directives for the node
-    nValues = atoi(pCur);
+//    nValues = atoi(pCur);
+    nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) );
     if ( nValues > 2 )
         fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues );
-    while ( *pCur++ != '\n' );
+//    while ( *pCur++ != '\n' );
+
     // write the .names line
     fprintf( pFile, ".table" );
     Io_NtkWriteBlifMvNodeFanins( pFile, pNode );
     fprintf( pFile, "\n" );
+
     // write the cubes
+    pCur = Abc_ObjData(pNode);
     if ( *pCur == 'd' )
     {
         fprintf( pFile, ".default " );
diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c
index d8bb1855..8ae3cc42 100644
--- a/src/base/io/ioWriteDot.c
+++ b/src/base/io/ioWriteDot.c
@@ -277,6 +277,8 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho
         {
             if ( (int)pNode->Level != Level )
                 continue;
+            if ( Abc_ObjFaninNum(pNode) == 0 )
+                continue;
 //            fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id );
             if ( Abc_NtkIsStrash(pNtk) )
                 pSopString = "";
@@ -313,7 +315,7 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho
                 // check if the costant node is present
                 if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 )
                 {
-                    fprintf( pFile, "  Node%d [label = \"Const1\"", pNode->Id );
+                    fprintf( pFile, "  Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) );
                     fprintf( pFile, ", shape = ellipse" );
                     if ( pNode->fMarkB )
                         fprintf( pFile, ", style = filled" );
diff --git a/src/base/ver/ver.h b/src/base/ver/ver.h
index 0ba081db..cf2b7497 100644
--- a/src/base/ver/ver.h
+++ b/src/base/ver/ver.h
@@ -56,6 +56,7 @@ struct Ver_Man_t_
     ProgressBar *   pProgress;
     // current design
     Abc_Lib_t *     pDesign;
+    st_table *      tName2Suffix;
     // error handling
     FILE *          Output;
     int             fTopLevel;
@@ -67,6 +68,7 @@ struct Ver_Man_t_
     Vec_Int_t *     vStackOp;
 };
 
+
 ////////////////////////////////////////////////////////////////////////
 ///                      MACRO DEFINITIONS                           ///
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/base/ver/verCore.c b/src/base/ver/verCore.c
index 6c036288..89f9a689 100644
--- a/src/base/ver/verCore.c
+++ b/src/base/ver/verCore.c
@@ -61,18 +61,29 @@ static int  Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateT
 static int  Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate );
 static int  Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox );
 static int  Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox );
-static int  Vec_ParseAttachBoxes( Ver_Man_t * pMan );
+static int  Ver_ParseAttachBoxes( Ver_Man_t * pMan );
 
 static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName );
 static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName );
 static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO );
 static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet );
 
+static void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan );
+
 static inline int Ver_NtkIsDefined( Abc_Ntk_t * pNtkBox )  { assert( pNtkBox->pName );     return Abc_NtkPiNum(pNtkBox) || Abc_NtkPoNum(pNtkBox);  }
 static inline int Ver_ObjIsConnected( Abc_Obj_t * pObj )   { assert( Abc_ObjIsBox(pObj) ); return Abc_ObjFaninNum(pObj) || Abc_ObjFanoutNum(pObj); }
 
+//static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk )       { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );        }
+
 int glo_fMapped = 0; // this is bad!
 
+typedef struct Ver_Bundle_t_    Ver_Bundle_t;
+struct Ver_Bundle_t_
+{
+    char *          pNameFormal;   // the name of the formal net
+    Vec_Ptr_t *     vNetsActual;   // the vector of actual nets (MSB to LSB)
+};
+
 ////////////////////////////////////////////////////////////////////////
 ///                     FUNCTION DEFINITIONS                         ///
 ////////////////////////////////////////////////////////////////////////
@@ -201,7 +212,7 @@ void Ver_ParseInternal( Ver_Man_t * pMan )
     }
 
     // process defined and undefined boxes
-    if ( !Vec_ParseAttachBoxes( pMan ) )
+    if ( !Ver_ParseAttachBoxes( pMan ) )
         return;
 
     // connect the boxes and check
@@ -213,7 +224,7 @@ void Ver_ParseInternal( Ver_Man_t * pMan )
         if ( pMan->fCheck && !Abc_NtkCheckRead( pNtk ) )
         {
             pMan->fTopLevel = 1;
-            sprintf( pMan->sError, "The network check has failed.", pNtk->pName );
+            sprintf( pMan->sError, "The network check has failed for network %s.", pNtk->pName );
             Ver_ParsePrintErrorMessage( pMan );
             return;
         }
@@ -391,7 +402,7 @@ int Ver_ParseModule( Ver_Man_t * pMan )
     // make sure we stopped at the opening paranthesis
     if ( Ver_StreamPopChar(p) != '(' )
     {
-        sprintf( pMan->sError, "Cannot find \"(\" after \"module\".", pNtk->pName );
+        sprintf( pMan->sError, "Cannot find \"(\" after \"module\" in network %s.", pNtk->pName );
         Ver_ParsePrintErrorMessage( pMan );
         return 0;
     }
@@ -406,7 +417,12 @@ int Ver_ParseModule( Ver_Man_t * pMan )
     if ( !Ver_ParseSkipComments( pMan ) )
         return 0;
     Symbol = Ver_StreamPopChar(p);
-    assert( Symbol == ';' );
+    if ( Symbol != ';' )
+    {
+        sprintf( pMan->sError, "Expected closing paranthesis after \"module\"." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
 
     // parse the inputs/outputs/registers/wires/inouts
     while ( 1 )
@@ -508,12 +524,141 @@ int Ver_ParseModule( Ver_Man_t * pMan )
             }
         }
     }
+
+    // remove the table if needed
+    Ver_ParseRemoveSuffixTable( pMan );
     return 1;
 }
 
+
 /**Function*************************************************************
 
-  Synopsis    [Parses one directive.]
+  Synopsis    [Lookups the suffix of the signal of the form [m:n].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseLookupSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb )
+{
+    unsigned Value;
+    *pnMsb = *pnLsb = -1;
+    if ( pMan->tName2Suffix == NULL )
+        return 1;
+    if ( !st_lookup( pMan->tName2Suffix, (char *)pWord, (char **)&Value ) )
+        return 1;
+    *pnMsb = (Value >> 8) & 0xff;
+    *pnLsb = Value & 0xff;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Lookups the suffix of the signal of the form [m:n].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseInsertsSuffix( Ver_Man_t * pMan, char * pWord, int nMsb, int nLsb )
+{
+    unsigned Value;
+    if ( pMan->tName2Suffix == NULL )
+        pMan->tName2Suffix = st_init_table( strcmp, st_strhash );
+    if ( st_is_member( pMan->tName2Suffix, pWord ) )
+        return 1;
+    assert( nMsb >= 0 && nMsb < 128 );
+    assert( nLsb >= 0 && nLsb < 128 );
+    Value = (nMsb << 8) | nLsb;
+    st_insert( pMan->tName2Suffix, Extra_UtilStrsav(pWord), (char *)Value );
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Lookups the suffic of the signal of the form [m:n].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan )
+{
+    st_generator * gen;
+    char * pKey, * pValue;
+    if ( pMan->tName2Suffix == NULL )
+        return;
+    st_foreach_item( pMan->tName2Suffix, gen, (char **)&pKey, (char **)&pValue )
+        free( pKey );
+    st_free_table( pMan->tName2Suffix );
+    pMan->tName2Suffix = NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine signal prefix of the form [Beg:End].]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseSignalPrefix( Ver_Man_t * pMan, char ** ppWord, int * pnMsb, int * pnLsb )
+{
+    char * pWord = *ppWord;
+    int nMsb, nLsb;
+    assert( pWord[0] == '[' );
+    // get the beginning
+    nMsb = atoi( pWord + 1 );
+    // find the splitter
+    while ( *pWord && *pWord != ':' && *pWord != ']' )
+        pWord++;
+    if ( *pWord == 0 )
+    {
+        sprintf( pMan->sError, "Cannot find closing bracket in this line." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    if ( *pWord == ']' )
+        nLsb = nMsb;
+    else
+    {
+        assert( *pWord == ':' );
+        nLsb = atoi( pWord + 1 );
+        // find the closing paranthesis
+        while ( *pWord && *pWord != ']' )
+            pWord++;
+        if ( *pWord == 0 )
+        {
+            sprintf( pMan->sError, "Cannot find closing bracket in this line." );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        assert( *pWord == ']' );
+        pWord++;
+    }
+    assert( nMsb >= 0 && nLsb >= 0 );
+    // return
+    *ppWord = pWord;
+    *pnMsb = nMsb;
+    *pnLsb = nLsb;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Determine signal suffix of the form [m:n].]
 
   Description []
                
@@ -521,17 +666,120 @@ int Ver_ParseModule( Ver_Man_t * pMan )
 
   SeeAlso     []
 
+***********************************************************************/
+int Ver_ParseSignalSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb )
+{
+    char * pCur;
+    int Length;
+    Length = strlen(pWord);
+    assert( pWord[Length-1] == ']' );
+    // walk backward
+    for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- )
+        if ( *pCur == ':' || *pCur == '[' )
+            break;
+    if ( pCur == pWord )
+    {
+        sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    if ( *pCur == '[' )
+    {
+        *pnMsb = *pnLsb = atoi(pCur+1);
+        *pCur = 0;
+        return 1;
+    }
+    assert( *pCur == ':' );
+    // get the end of the interval
+    *pnLsb = atoi(pCur+1);
+    // find the beginning
+    for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- )
+        if ( *pCur == '[' )
+            break;
+    if ( pCur == pWord )
+    {
+        sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    assert( *pCur == '[' );
+    // get the beginning of the interval
+    *pnMsb = atoi(pCur+1);
+    // cut the word
+    *pCur = 0;
+    return 1;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the values of constant bits.]
+
+  Description [The resulting bits are in MSB to LSB order.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseConstant( Ver_Man_t * pMan, char * pWord )
+{
+    int nBits, i;
+    assert( pWord[0] >= '1' && pWord[1] <= '9' );
+    nBits = atoi(pWord);
+    // find the next symbol \'
+    while ( *pWord && *pWord != '\'' )
+        pWord++;
+    if ( *pWord == 0 )
+    {
+        sprintf( pMan->sError, "Cannot find symbol \' in the constant." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    assert( *pWord == '\'' );
+    pWord++;
+    if ( *pWord != 'b' )
+    {
+        sprintf( pMan->sError, "Currently can only handle binary constants." );
+        Ver_ParsePrintErrorMessage( pMan );
+        return 0;
+    }
+    pWord++;
+    // scan the bits
+    Vec_PtrClear( pMan->vNames );
+    for ( i = 0; i < nBits; i++ )
+    {
+        if ( pWord[i] != '0' && pWord[i] != '1' )
+        {
+            sprintf( pMan->sError, "Having problem parsing the binary constant." );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        Vec_PtrPush( pMan->vNames, (void *)(pWord[i]-'0') );
+    }
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Parses one directive.]
+
+  Description [The signals are added in the order from LSB to MSB.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
 ***********************************************************************/
 int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType )
 {
     Ver_Stream_t * p = pMan->pReader;
-    char Buffer[1000];
-    int Lower, Upper, i;
-    char * pWord;
-    char Symbol;
-    Lower = Upper = 0;
+    char Buffer[1000], Symbol, * pWord;
+    int nMsb, nLsb, Bit, Limit, i;
+    nMsb = nLsb = -1;
     while ( 1 )
     {
+        // get the next word
         pWord = Ver_ParseGetName( pMan );
         if ( pWord == NULL )
             return 0;
@@ -539,38 +787,10 @@ int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigTyp
         // check if the range is specified
         if ( pWord[0] == '[' && !pMan->fNameLast )
         {
-            Lower = atoi( pWord + 1 );
-            // find the splitter
-            while ( *pWord && *pWord != ':' && *pWord != ']' )
-                pWord++;
+            assert( nMsb == -1 && nLsb == -1 );
+            Ver_ParseSignalPrefix( pMan, &pWord, &nMsb, &nLsb );
+            // check the case when there is space between bracket and the next word
             if ( *pWord == 0 )
-            {
-                sprintf( pMan->sError, "Cannot find closing bracket in this line." );
-                Ver_ParsePrintErrorMessage( pMan );
-                return 0;
-            }
-            if ( *pWord == ']' )
-                Upper = Lower;
-            else
-            {
-                Upper = atoi( pWord + 1 );
-                if ( Lower > Upper )
-                    i = Lower, Lower = Upper, Upper = i;
-                // find the closing paranthesis
-                while ( *pWord && *pWord != ']' )
-                    pWord++;
-                if ( *pWord == 0 )
-                {
-                    sprintf( pMan->sError, "Cannot find closing bracket in this line." );
-                    Ver_ParsePrintErrorMessage( pMan );
-                    return 0;
-                }
-                assert( *pWord == ']' );
-            }
-            // check the case of no space between bracket and the next word
-            if ( *(pWord+1) != 0 )
-                pWord++;
-            else
             {
                 // get the signal name
                 pWord = Ver_ParseGetName( pMan );
@@ -580,7 +800,7 @@ int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigTyp
         }
 
         // create signals
-        if ( Lower == 0 && Upper == 0 )
+        if ( nMsb == -1 && nLsb == -1 )
         {
             if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
                 Ver_ParseCreatePi( pNtk, pWord );
@@ -591,9 +811,14 @@ int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigTyp
         }
         else
         {
-            for ( i = Lower; i <= Upper; i++ )
+            assert( nMsb >= 0 && nLsb >= 0 );
+            // add to the hash table
+            Ver_ParseInsertsSuffix( pMan, pWord, nMsb, nLsb );
+            // add signals from Lsb to Msb
+            Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1;
+            for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1  )
             {
-                sprintf( Buffer, "%s[%d]", pWord, i );
+                sprintf( Buffer, "%s[%d]", pWord, Bit );
                 if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
                     Ver_ParseCreatePi( pNtk, Buffer );
                 if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT )
@@ -823,12 +1048,14 @@ int Ver_ParseInitial( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
 ***********************************************************************/
 int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
 {
+    char Buffer[1000], Buffer2[1000];
     Ver_Stream_t * p = pMan->pReader;
     Abc_Obj_t * pNode, * pNet;
     char * pWord, * pName, * pEquation;
     Hop_Obj_t * pFunc;
     char Symbol;
-    int i, Length, fReduction;
+    int i, Bit, Limit, Length, fReduction;
+    int nMsb, nLsb;
 
 //    if ( Ver_StreamGetLineNumber(p) == 2756 )
 //    {
@@ -845,102 +1072,171 @@ int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk )
         pWord = Ver_ParseGetName( pMan );
         if ( pWord == NULL )
             return 0;
-        // consider the case of reduction operations
-        fReduction = 0;
-        if ( pWord[0] == '{' && !pMan->fNameLast )
-            fReduction = 1;
-        if ( fReduction )
-        {
-            pWord++;
-            pWord[strlen(pWord)-1] = 0;
-            assert( pWord[0] != '\\' );
-        }
-        // get the fanout net
-        pNet = Ver_ParseFindNet( pNtk, pWord );
-        if ( pNet == NULL )
-        {
-            sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
-            Ver_ParsePrintErrorMessage( pMan );
-            return 0;
-        }
-        // get the equality sign
-        if ( Ver_StreamPopChar(p) != '=' )
-        {
-            sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
-            Ver_ParsePrintErrorMessage( pMan );
-            return 0;
-        }
-        // skip the comments
-        if ( !Ver_ParseSkipComments( pMan ) )
+        // check for vector-inputs
+        if ( !Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ) )
             return 0;
-        // get the second name
-        if ( fReduction )
-            pEquation = Ver_StreamGetWord( p, ";" );
-        else
-            pEquation = Ver_StreamGetWord( p, ",;" );
-        if ( pEquation == NULL )
+        // handle special case of constant assignment
+        if ( nMsb >= 0 && nLsb >= 0 )
         {
-            sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) );
-            Ver_ParsePrintErrorMessage( pMan );
-            return 0;
-        }
+            // save the fanout name
+            strcpy( Buffer, pWord );
+            // get the equality sign
+            if ( Ver_StreamPopChar(p) != '=' )
+            {
+                sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            // get the constant
+            pWord = Ver_ParseGetName( pMan );
+            if ( pWord == NULL )
+                return 0;
+            // check if it is indeed a constant
+            if ( !(pWord[0] >= '0' && pWord[0] <= '9') )
+            {
+                sprintf( pMan->sError, "Currently can only assign vector-signal \"%s\" to be a constant.", Buffer );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
 
-        // consider the case of mapped network
-        if ( pMan->fMapped )
-        {
-            Vec_PtrClear( pMan->vNames );
-            if ( !strcmp( pEquation, "1\'b0" ) )
-                pFunc = (Hop_Obj_t *)Mio_LibraryReadConst0(Abc_FrameReadLibGen());
-            else if ( !strcmp( pEquation, "1\'b1" ) )
-                pFunc = (Hop_Obj_t *)Mio_LibraryReadConst1(Abc_FrameReadLibGen());
-            else
+            // set individual bits of the constant
+            if ( !Ver_ParseConstant( pMan, pWord ) )
+                return 0;
+            // check that the constant has the same size
+            Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1;
+            if ( Limit != Vec_PtrSize(pMan->vNames) )
+            {
+                sprintf( pMan->sError, "The constant size (%d) is different from the signal\"%s\" size (%d).", 
+                    Vec_PtrSize(pMan->vNames), Buffer, Limit );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            // iterate through the bits
+            for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1  )
             {
-                if ( Ver_ParseFindNet(pNtk, pEquation) == NULL )
+                // get the fanin net
+                if ( Vec_PtrEntry( pMan->vNames, Limit-1-i ) )
+                    pNet = Ver_ParseFindNet( pNtk, "1\'b1" );
+                else
+                    pNet = Ver_ParseFindNet( pNtk, "1\'b0" );
+                assert( pNet != NULL );
+
+                // create the buffer
+                pNode = Abc_NtkCreateNodeBuf( pNtk, pNet );
+
+                // get the fanout net
+                sprintf( Buffer2, "%s[%d]", Buffer, Bit );
+                pNet = Ver_ParseFindNet( pNtk, Buffer2 );
+                if ( pNet == NULL )
                 {
-                    sprintf( pMan->sError, "Cannot read Verilog with non-trivail assignments in the mapped netlist.", pEquation );
+                    sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
                     Ver_ParsePrintErrorMessage( pMan );
                     return 0;
                 }
-                Vec_PtrPush( pMan->vNames, (void *)strlen(pEquation) );
-                Vec_PtrPush( pMan->vNames, pEquation );
-                // get the buffer
-                pFunc = (Hop_Obj_t *)Mio_LibraryReadBuf(Abc_FrameReadLibGen());
+                Abc_ObjAddFanin( pNet, pNode );
             }
+            // go to the end of the line
+            Ver_ParseSkipComments( pMan );
         }
         else
         {
-            // parse the formula
+            // consider the case of reduction operations
+            fReduction = 0;
+            if ( pWord[0] == '{' && !pMan->fNameLast )
+                fReduction = 1;
             if ( fReduction )
-                pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError );  
-            else
-                pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError );  
-            if ( pFunc == NULL )
             {
+                pWord++;
+                pWord[strlen(pWord)-1] = 0;
+                assert( pWord[0] != '\\' );
+            }
+            // get the fanout net
+            pNet = Ver_ParseFindNet( pNtk, pWord );
+            if ( pNet == NULL )
+            {
+                sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
                 Ver_ParsePrintErrorMessage( pMan );
                 return 0;
             }
-        }
-
-        // create the node with the given inputs
-        pNode = Abc_NtkCreateNode( pNtk );
-        pNode->pData = pFunc;
-        Abc_ObjAddFanin( pNet, pNode );
-        // connect to fanin nets
-        for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ )
-        {
-            // get the name of this signal
-            Length = (int)Vec_PtrEntry( pMan->vNames, 2*i );
-            pName  = Vec_PtrEntry( pMan->vNames, 2*i + 1 );
-            pName[Length] = 0;
-            // find the corresponding net
-            pNet = Ver_ParseFindNet( pNtk, pName );
-            if ( pNet == NULL )
+            // get the equality sign
+            if ( Ver_StreamPopChar(p) != '=' )
             {
-                sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %d is not defined).", pWord, pName );
+                sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
                 Ver_ParsePrintErrorMessage( pMan );
                 return 0;
             }
-            Abc_ObjAddFanin( pNode, pNet );
+            // skip the comments
+            if ( !Ver_ParseSkipComments( pMan ) )
+                return 0;
+            // get the second name
+            if ( fReduction )
+                pEquation = Ver_StreamGetWord( p, ";" );
+            else
+                pEquation = Ver_StreamGetWord( p, ",;" );
+            if ( pEquation == NULL )
+            {
+                sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+
+            // consider the case of mapped network
+            if ( pMan->fMapped )
+            {
+                Vec_PtrClear( pMan->vNames );
+                if ( !strcmp( pEquation, "1\'b0" ) )
+                    pFunc = (Hop_Obj_t *)Mio_LibraryReadConst0(Abc_FrameReadLibGen());
+                else if ( !strcmp( pEquation, "1\'b1" ) )
+                    pFunc = (Hop_Obj_t *)Mio_LibraryReadConst1(Abc_FrameReadLibGen());
+                else
+                {
+                    if ( Ver_ParseFindNet(pNtk, pEquation) == NULL )
+                    {
+                        sprintf( pMan->sError, "Cannot read Verilog with non-trivial assignments in the mapped netlist." );
+                        Ver_ParsePrintErrorMessage( pMan );
+                        return 0;
+                    }
+                    Vec_PtrPush( pMan->vNames, (void *)strlen(pEquation) );
+                    Vec_PtrPush( pMan->vNames, pEquation );
+                    // get the buffer
+                    pFunc = (Hop_Obj_t *)Mio_LibraryReadBuf(Abc_FrameReadLibGen());
+                }
+            }
+            else
+            {
+                // parse the formula
+                if ( fReduction )
+                    pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError );  
+                else
+                    pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError );  
+                if ( pFunc == NULL )
+                {
+                    Ver_ParsePrintErrorMessage( pMan );
+                    return 0;
+                }
+            }
+
+            // create the node with the given inputs
+            pNode = Abc_NtkCreateNode( pNtk );
+            pNode->pData = pFunc;
+            Abc_ObjAddFanin( pNet, pNode );
+            // connect to fanin nets
+            for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ )
+            {
+                // get the name of this signal
+                Length = (int)Vec_PtrEntry( pMan->vNames, 2*i );
+                pName  = Vec_PtrEntry( pMan->vNames, 2*i + 1 );
+                pName[Length] = 0;
+                // find the corresponding net
+                pNet = Ver_ParseFindNet( pNtk, pName );
+                if ( pNet == NULL )
+                {
+                    sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %s is not defined).", pWord, pName );
+                    Ver_ParsePrintErrorMessage( pMan );
+                    return 0;
+                }
+                Abc_ObjAddFanin( pNode, pNet );
+            }
         }
 
         Symbol = Ver_StreamPopChar(p);
@@ -1229,19 +1525,21 @@ int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate )
 ***********************************************************************/
 int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
 {
+    char Buffer[1000];
     Ver_Stream_t * p = pMan->pReader;
-    Vec_Ptr_t * vNetPairs;
-    Abc_Obj_t * pNetFormal, * pNetActual;
+    Ver_Bundle_t * pBundle;
+    Vec_Ptr_t * vBundles;
+    Abc_Obj_t * pNetActual; 
     Abc_Obj_t * pNode;
     char * pWord, Symbol;
-    int fCompl;
+    int fCompl, fFormalIsGiven;
 
-    // parse the directive and set the pointers to the PIs/POs of the gate
+    // gate the name of the box
     pWord = Ver_ParseGetName( pMan );
     if ( pWord == NULL )
         return 0;
 
-    // create box to represent this gate
+    // create a box with this name
     pNode = Abc_NtkCreateBlackbox( pNtk );
     pNode->pData = pNtkBox;
     Abc_ObjAssignName( pNode, pWord, NULL );
@@ -1253,50 +1551,174 @@ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
         Ver_ParsePrintErrorMessage( pMan );
         return 0;
     }
-
+    Ver_ParseSkipComments( pMan );
+ 
     // parse pairs of formal/actural inputs
-    vNetPairs = Vec_PtrAlloc( 16 );
-    pNode->pCopy = (Abc_Obj_t *)vNetPairs;
+    vBundles = Vec_PtrAlloc( 16 );
+    pNode->pCopy = (Abc_Obj_t *)vBundles;
     while ( 1 )
     {
+        // allocate the bundle (formal name + array of actual nets)
+        pBundle = ALLOC( Ver_Bundle_t, 1 );
+        pBundle->pNameFormal = NULL;
+        pBundle->vNetsActual = Vec_PtrAlloc( 4 );
+        Vec_PtrPush( vBundles, pBundle );
+
         // process one pair of formal/actual parameters
-        if ( Ver_StreamPopChar(p) != '.' )
+        fFormalIsGiven = 0;
+        if ( Ver_StreamScanChar(p) == '.' )
         {
-            sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Abc_ObjName(pNode) );
-            Ver_ParsePrintErrorMessage( pMan );
-            return 0;
-        }
+            fFormalIsGiven = 1;
+            if ( Ver_StreamPopChar(p) != '.' )
+            {
+                sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Abc_ObjName(pNode) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
 
-        // parse the formal name
-        pWord = Ver_ParseGetName( pMan );
-        if ( pWord == NULL )
-            return 0;
-        // get the formal net
-        pNetFormal = Abc_NtkFindOrCreateNet( pNtkBox, pWord );
-        Vec_PtrPush( vNetPairs, pNetFormal );
+            // parse the formal name
+            pWord = Ver_ParseGetName( pMan );
+            if ( pWord == NULL )
+                return 0;
 
-        // open the paranthesis
-        if ( Ver_StreamPopChar(p) != '(' )
-        {
-            sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, Abc_ObjName(pNode));
-            Ver_ParsePrintErrorMessage( pMan );
-            return 0;
+            // save the name
+            pBundle->pNameFormal = Extra_UtilStrsav( pWord );
+
+            // open the paranthesis
+            if ( Ver_StreamPopChar(p) != '(' )
+            {
+                sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, Abc_ObjName(pNode));
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            Ver_ParseSkipComments( pMan );
         }
 
-        // parse the actual name
-        pWord = Ver_ParseGetName( pMan );
-        if ( pWord == NULL )
-            return 0;
-        // consider the case of empty name
-        fCompl = 0;
-        if ( pWord[0] == 0 )
+        // check if this is the beginning of {} expression
+        Symbol = Ver_StreamScanChar(p);
+
+        // consider the case of vector-inputs
+        if ( Symbol == '{' )
         {
-            // remove the formal net
-//            Vec_PtrPop( vNetPairs );
-            pNetActual = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
+            int i, k, Bit, Limit, nMsb, nLsb, fQuit;
+
+            // skip this char
+            Ver_ParseSkipComments( pMan );
+            Ver_StreamPopChar(p);
+
+            // read actual names
+            i = 0;
+            fQuit = 0;
+            while ( 1 )
+            {
+                // parse the formal name
+                Ver_ParseSkipComments( pMan );
+                pWord = Ver_ParseGetName( pMan );
+                if ( pWord == NULL )
+                    return 0;
+
+                // check if the last char is a closing brace
+                if ( pWord[strlen(pWord)-1] == '}' )
+                {
+                    pWord[strlen(pWord)-1] = 0;
+                    fQuit = 1;
+                }
+                if ( pWord[0] == 0 )
+                    break;
+
+                // check for constant
+                if ( pWord[0] >= '1' && pWord[0] <= '9' )
+                {
+                    if ( !Ver_ParseConstant( pMan, pWord ) )
+                        return 0;
+                    // add constant MSB to LSB
+                    for ( k = 0; k < Vec_PtrSize(pMan->vNames); k++, i++ )
+                    {
+                        // get the actual net
+                        sprintf( Buffer, "1\'b%d", (int)(Vec_PtrEntry(pMan->vNames,k) != NULL) );
+                        pNetActual = Ver_ParseFindNet( pNtk, Buffer );
+                        if ( pNetActual == NULL )
+                        {
+                            sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) );
+                            Ver_ParsePrintErrorMessage( pMan );
+                            return 0;
+                        }
+                        Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+                    }
+                }
+                else
+                {
+                    // get the suffix of the form [m:n]
+                    if ( pWord[strlen(pWord)-1] == ']' && !pMan->fNameLast )
+                        Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb );
+                    else
+                        Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb );
+
+                    // generate signals
+                    if ( nMsb == -1 && nLsb == -1 )
+                    {
+                        // get the actual net
+                        pNetActual = Ver_ParseFindNet( pNtk, pWord );
+                        if ( pNetActual == NULL )
+                        {
+                            sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", pWord, Abc_ObjName(pNode) );
+                            Ver_ParsePrintErrorMessage( pMan );
+                            return 0;
+                        }
+                        Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+                        i++;
+                    }
+                    else
+                    {
+                        // go from MSB to LSB
+                        assert( nMsb >= 0 && nLsb >= 0 );
+                        Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1;  
+                        for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--, i++ )
+                        {
+                            // get the actual net
+                            sprintf( Buffer, "%s[%d]", pWord, Bit );
+                            pNetActual = Ver_ParseFindNet( pNtk, Buffer );
+                            if ( pNetActual == NULL )
+                            {
+                                sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) );
+                                Ver_ParsePrintErrorMessage( pMan );
+                                return 0;
+                            }
+                            Vec_PtrPush( pBundle->vNetsActual, pNetActual );
+                        }
+                    }
+                }
+
+                if ( fQuit )
+                    break;
+
+                // skip comma
+                Ver_ParseSkipComments( pMan );
+                Symbol = Ver_StreamPopChar(p);
+                if ( Symbol == '}' )
+                    break;
+                if ( Symbol != ',' )
+                {
+                    sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) );
+                    Ver_ParsePrintErrorMessage( pMan );
+                    return 0;
+                }
+            }
         }
         else
         {
+            // get the next word
+            pWord = Ver_ParseGetName( pMan );
+            if ( pWord == NULL )
+                return 0;
+            // consider the case of empty name
+            fCompl = 0;
+            if ( pWord[0] == 0 )
+            {
+                pNetActual = Abc_NtkCreateNet( pNtk );
+            }
+            else
+            {
 /*
             // check if the name is complemented
             fCompl = (pWord[0] == '~');
@@ -1307,34 +1729,39 @@ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
                     pNtk->pData = Extra_MmFlexStart();
             }
 */
-            // get the actual net
-            pNetActual = Ver_ParseFindNet( pNtk, pWord );
-            if ( pNetActual == NULL )
-            {
-                sprintf( pMan->sError, "Actual net is missing in gate %s.", Abc_ObjName(pNode) );
-                Ver_ParsePrintErrorMessage( pMan );
-                return 0;
+                // get the actual net
+                pNetActual = Ver_ParseFindNet( pNtk, pWord );
+                if ( pNetActual == NULL )
+                {
+                    sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", pWord, Abc_ObjName(pNode) );
+                    Ver_ParsePrintErrorMessage( pMan );
+                    return 0;
+                }
             }
+            Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) );
         }
-        Vec_PtrPush( vNetPairs, Abc_ObjNotCond( pNetActual, fCompl ) );
 
-        // close the paranthesis
-        if ( Ver_StreamPopChar(p) != ')' )
+        if ( fFormalIsGiven )
         {
-            sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) );
-            Ver_ParsePrintErrorMessage( pMan );
-            return 0;
+            // close the paranthesis
+            Ver_ParseSkipComments( pMan );
+            if ( Ver_StreamPopChar(p) != ')' )
+            {
+                sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            Ver_ParseSkipComments( pMan );
         }
 
         // check if it is the end of gate
-        Ver_ParseSkipComments( pMan );
         Symbol = Ver_StreamPopChar(p);
         if ( Symbol == ')' )
             break;
         // skip comma
         if ( Symbol != ',' )
         {
-            sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) );
+            sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) );
             Ver_ParsePrintErrorMessage( pMan );
             return 0;
         }
@@ -1353,6 +1780,24 @@ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
     return 1;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Connects one box to the network]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseFreeBundle( Ver_Bundle_t * pBundle )
+{
+    FREE( pBundle->pNameFormal );
+    Vec_PtrFree( pBundle->vNetsActual );
+    free( pBundle );
+}
+
 /**Function*************************************************************
 
   Synopsis    [Connects one box to the network]
@@ -1366,256 +1811,693 @@ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox )
 ***********************************************************************/
 int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox )
 {
-    Vec_Ptr_t * vNetPairs = (Vec_Ptr_t *)pBox->pCopy;
+    Vec_Ptr_t * vBundles = (Vec_Ptr_t *)pBox->pCopy;
     Abc_Ntk_t * pNtk = pBox->pNtk;
     Abc_Ntk_t * pNtkBox = pBox->pData;
-    Abc_Obj_t * pNet, * pTerm, * pTermNew;
-    int i;
+    Abc_Obj_t * pTerm, * pTermNew, * pNetAct;
+    Ver_Bundle_t * pBundle;
+    char * pNameFormal;
+    int i, k, j, iBundle, Length;
 
     assert( !Ver_ObjIsConnected(pBox) );
     assert( Ver_NtkIsDefined(pNtkBox) );
     assert( !Abc_NtkHasBlackbox(pNtkBox) || Abc_NtkBoxNum(pNtkBox) == 1 );
-
+/*
     // clean the PI/PO nets
     Abc_NtkForEachPi( pNtkBox, pTerm, i )
         Abc_ObjFanout0(pTerm)->pCopy = NULL;
     Abc_NtkForEachPo( pNtkBox, pTerm, i )
         Abc_ObjFanin0(pTerm)->pCopy = NULL;
-
-    // map formal nets into actual nets
-    Vec_PtrForEachEntry( vNetPairs, pNet, i )
+*/
+    // check if some of them do not have formal names
+    Vec_PtrForEachEntry( vBundles, pBundle, k )
+        if ( pBundle->pNameFormal == NULL )
+            break;
+    if ( k < Vec_PtrSize(vBundles) )
     {
-        // get the actual net corresponding to this formal net (pNet)
-        pNet->pCopy = Vec_PtrEntry( vNetPairs, ++i );
-        // make sure the actual net is not complemented (otherwise need to use polarity)
-        assert( !Abc_ObjIsComplement(pNet->pCopy) );
+        printf( "Warning: The instance %s of network %s will be connected without using formal names.\n", pNtkBox->pName, Abc_ObjName(pBox) );
+        // add all actual nets in the bundles
+        iBundle = 0;
+        Vec_PtrForEachEntry( vBundles, pBundle, j )
+            iBundle += Vec_PtrSize(pBundle->vNetsActual);
+
+        // check the number of actual nets is the same as the number of formal nets
+        if ( iBundle != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) )
+        {
+            sprintf( pMan->sError, "The number of actual IOs (%d) is different from the number of formal IOs (%d) when instantiating network %s in box %s.", 
+                Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) );
+            Ver_ParsePrintErrorMessage( pMan );
+            return 0;
+        }
+        // connect bundles in the natural order
+        iBundle = 0;
+        Abc_NtkForEachPi( pNtkBox, pTerm, i )
+        {
+            pBundle = Vec_PtrEntry( vBundles, iBundle++ );
+            // the bundle is found - add the connections - using order LSB to MSB
+            Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
+            {
+                pTermNew = Abc_NtkCreateBi( pNtk );
+                Abc_ObjAddFanin( pBox, pTermNew );
+                Abc_ObjAddFanin( pTermNew, pNetAct );
+                i++;
+            }
+            i--;
+        }
+        // create fanins of the box
+        Abc_NtkForEachPo( pNtkBox, pTerm, i )
+        {
+            pBundle = Vec_PtrEntry( vBundles, iBundle++ );
+            // the bundle is found - add the connections - using order LSB to MSB
+            Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
+            {
+                pTermNew = Abc_NtkCreateBo( pNtk );
+                Abc_ObjAddFanin( pTermNew, pBox );
+                Abc_ObjAddFanin( pNetAct, pTermNew );
+                i++;
+            }
+            i--;
+        }
+
+        // free the bundling
+        Vec_PtrForEachEntry( vBundles, pBundle, k )
+            Ver_ParseFreeBundle( pBundle );
+        Vec_PtrFree( vBundles );
+        pBox->pCopy = NULL;
+        return 1;
     }
 
-    // make sure all PI nets are assigned
+    // bundles arrive in any order - but inside each bundle the order is MSB to LSB
+    // make sure every formal PI has a corresponding net
     Abc_NtkForEachPi( pNtkBox, pTerm, i )
     {
-        if ( Abc_ObjFanout0(pTerm)->pCopy == NULL )
+        // get the name of this formal net
+        pNameFormal = Abc_ObjName( Abc_ObjFanout0(pTerm) );
+        // try to find the bundle with this formal net
+        pBundle = NULL;
+        Vec_PtrForEachEntry( vBundles, pBundle, k )
+            if ( !strcmp(pBundle->pNameFormal, pNameFormal) )
+                break;
+        assert( pBundle != NULL );
+        // if the bundle is not found, try without parantheses
+        if ( k == Vec_PtrSize(vBundles) )
         {
-            sprintf( pMan->sError, "Input formal net %s of network %s is not driven in box %s.", 
-                Abc_ObjName(Abc_ObjFanout0(pTerm)), pNtkBox->pName, Abc_ObjName(pBox) );
-            Ver_ParsePrintErrorMessage( pMan );
-            return 0;
+            pBundle = NULL;
+            Length = strlen(pNameFormal);
+            if ( pNameFormal[Length-1] == ']' )
+            {
+                // find the opening brace
+                for ( Length--; Length >= 0; Length-- )
+                    if ( pNameFormal[Length] == '[' )
+                        break;
+                // compare names before brace
+                if ( Length > 0 )
+                {
+                    Vec_PtrForEachEntry( vBundles, pBundle, j )
+                        if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) )
+                            break;
+                    if ( j == Vec_PtrSize(vBundles) )
+                        pBundle = NULL;
+                }
+            }
+            if ( pBundle == NULL )
+            {
+                sprintf( pMan->sError, "Cannot find an actual net for the formal net %s when instantiating network %s in box %s.", 
+                    pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+        }
+        // the bundle is found - add the connections - using order LSB to MSB
+        Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
+        {
+            pTermNew = Abc_NtkCreateBi( pNtk );
+            Abc_ObjAddFanin( pBox, pTermNew );
+            Abc_ObjAddFanin( pTermNew, pNetAct );
+            i++;
         }
-        pTermNew = Abc_NtkCreateBi( pNtk );
-        Abc_ObjAddFanin( pBox, pTermNew );
-        Abc_ObjAddFanin( pTermNew, Abc_ObjFanout0(pTerm)->pCopy );
+        i--;
     }
 
-    // create fanins of the box
+    // connect those formal POs that do have nets
     Abc_NtkForEachPo( pNtkBox, pTerm, i )
     {
-        if ( Abc_ObjFanin0(pTerm)->pCopy == NULL )
-            Abc_ObjFanin0(pTerm)->pCopy = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
-        pTermNew = Abc_NtkCreateBo( pNtk );
-        Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, pTermNew );
-        Abc_ObjAddFanin( pTermNew, pBox );
+        // get the name of this PI
+        pNameFormal = Abc_ObjName( Abc_ObjFanin0(pTerm) );
+        // try to find this formal net in the bundle
+        pBundle = NULL;
+        Vec_PtrForEachEntry( vBundles, pBundle, k )
+            if ( !strcmp(pBundle->pNameFormal, pNameFormal) )
+                break;
+        assert( pBundle != NULL );
+        // if the name is not found, try without parantheses
+        if ( k == Vec_PtrSize(vBundles) )
+        {
+            pBundle = NULL;
+            Length = strlen(pNameFormal);
+            if ( pNameFormal[Length-1] == ']' )
+            {
+                // find the opening brace
+                for ( Length--; Length >= 0; Length-- )
+                    if ( pNameFormal[Length] == '[' )
+                        break;
+                // compare names before brace
+                if ( Length > 0 )
+                {
+                    Vec_PtrForEachEntry( vBundles, pBundle, j )
+                        if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) )
+                            break;
+                    if ( j == Vec_PtrSize(vBundles) )
+                        pBundle = NULL;
+                }
+            }
+            if ( pBundle == NULL )
+            {
+                printf( "Warning: The formal output %s is not driven when instantiating network %s in box %s.", 
+                    pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) );
+                continue;
+            }
+        }
+        // the bundle is found - add the connections
+        Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k )
+        {
+            if ( !strcmp(Abc_ObjName(pNetAct), "1\'b0") || !strcmp(Abc_ObjName(pNetAct), "1\'b1") )
+            {
+                sprintf( pMan->sError, "It looks like formal output %s is driving a constant net (%s) when instantiating network %s in box %s.", 
+                    pBundle->pNameFormal, Abc_ObjName(pNetAct), pNtkBox->pName, Abc_ObjName(pBox) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
+            pTermNew = Abc_NtkCreateBo( pNtk );
+            Abc_ObjAddFanin( pTermNew, pBox );
+            Abc_ObjAddFanin( pNetAct, pTermNew );
+            i++;
+        }
+        i--;
     }
 
-    // free the mapping
-    Vec_PtrFree( vNetPairs );
+    // free the bundling
+    Vec_PtrForEachEntry( vBundles, pBundle, k )
+        Ver_ParseFreeBundle( pBundle );
+    Vec_PtrFree( vBundles );
     pBox->pCopy = NULL;
     return 1;
 }
 
+
 /**Function*************************************************************
 
-  Synopsis    [Attaches the boxes to the network.]
+  Synopsis    [Connects the defined boxes.]
 
-  Description [Makes sure that the undefined boxes are connected correctly.]
+  Description [Returns 2 if there are any undef boxes.]
                
   SideEffects []
 
   SeeAlso     []
 
 ***********************************************************************/
-int Vec_ParseAttachBoxes( Ver_Man_t * pMan )
+int Ver_ParseConnectDefBoxes( Ver_Man_t * pMan )
 {
-    Abc_Ntk_t * pNtk, * pNtkBox;
-    Vec_Ptr_t * vEnvoys, * vNetPairs, * vPivots;
-    Abc_Obj_t * pBox, * pTerm, * pNet, * pNetDr, * pNetAct;
-    int i, k, m, nBoxes;
-
-    // connect defined boxes
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pBox;
+    int i, k, RetValue = 1;
+    // go through all the modules
     Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
     {
-        Abc_NtkForEachBlackbox( pNtk, pBox, k )
+        // go through all the boxes of this module
+        Abc_NtkForEachBox( pNtk, pBox, k )
         {
-            if ( pBox->pData && Ver_NtkIsDefined(pBox->pData) )
-                if ( !Ver_ParseConnectBox( pMan, pBox ) )
-                    return 0;
+            if ( Abc_ObjIsLatch(pBox) )
+                continue;
+            // skip internal boxes of the blackboxes
+            if ( pBox->pData == NULL )
+                continue;
+            // if the network is undefined, it will be connected later
+            if ( !Ver_NtkIsDefined(pBox->pData) )
+            {
+                RetValue = 2;
+                continue;
+            }
+            // connect the box
+            if ( !Ver_ParseConnectBox( pMan, pBox ) )
+                return 0;
+            // if the network is a true blackbox, skip
+            if ( Abc_NtkHasBlackbox(pBox->pData) )
+                continue;
+            // convert the box to the whitebox
+            Abc_ObjBlackboxToWhitebox( pBox );
         }
     }
+    return RetValue;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Collects the undef boxes and maps them into their instances.]
+
+  Description []
+               
+  SideEffects []
 
-    // convert blackboxes to whiteboxes
+  SeeAlso     []
+
+***********************************************************************/
+Vec_Ptr_t * Ver_ParseCollectUndefBoxes( Ver_Man_t * pMan )
+{
+    Vec_Ptr_t * vUndefs;
+    Abc_Ntk_t * pNtk, * pNtkBox;
+    Abc_Obj_t * pBox;
+    int i, k;
+    // clear the module structures
+    Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+        pNtk->pData = NULL;
+    // go through all the blackboxes
+    vUndefs = Vec_PtrAlloc( 16 );
     Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+    {
         Abc_NtkForEachBlackbox( pNtk, pBox, k )
         {
             pNtkBox = pBox->pData;
             if ( pNtkBox == NULL )
                 continue;
-
-            if ( !strcmp( pNtkBox->pName, "ADDHX1" ) )
+            if ( Ver_NtkIsDefined(pNtkBox) )
+                continue;
+            if ( pNtkBox->pData == NULL )
             {
-                int x = 0;
+                // save the box
+                Vec_PtrPush( vUndefs, pNtkBox );
+                pNtkBox->pData = Vec_PtrAlloc( 16 );
             }
+            // save the instance
+            Vec_PtrPush( pNtkBox->pData, pBox );
+        }
+    }
+    return vUndefs;
+}
 
-            if ( pBox->pData && !Abc_NtkHasBlackbox(pBox->pData) )
-                Abc_ObjBlackboxToWhitebox( pBox );
-        }   
+/**Function*************************************************************
 
+  Synopsis    [Reports how many times each type of undefined box occurs.]
 
-    // search for undefined boxes
-    nBoxes = 0;
-    Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
-        nBoxes += !Ver_NtkIsDefined(pNtk);
-    // quit if no undefined boxes are found
-    if ( nBoxes == 0 )
-        return 1;
+  Description []
+               
+  SideEffects []
 
-    // count how many times each box occurs
+  SeeAlso     []
+
+***********************************************************************/
+void Ver_ParseReportUndefBoxes( Ver_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pBox;
+    int i, k, nBoxes;
+    // clean 
+    nBoxes = 0;
     Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
     {
-        assert( pNtk->pData == NULL );
-        pNtk->pData = NULL;
+        pNtk->fHiePath = 0;
+        if ( !Ver_NtkIsDefined(pNtk) )
+            nBoxes++;
     }
+    // count
     Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
         Abc_NtkForEachBlackbox( pNtk, pBox, k )
-        {
-            if ( pBox->pData == NULL )
-                continue;
-            pNtkBox = pBox->pData;
-            pNtkBox->pData = (void *)((int)pNtkBox->pData + 1);
-        }
-
-    // print the boxes
+            if ( pBox->pData && !Ver_NtkIsDefined(pBox->pData) )
+                ((Abc_Ntk_t *)pBox->pData)->fHiePath++;
+    // print the stats
     printf( "Warning: The design contains %d undefined objects interpreted as blackboxes:\n", nBoxes );
     Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
         if ( !Ver_NtkIsDefined(pNtk) )
-            printf( "%s (%d)  ", Abc_NtkName(pNtk), (int)pNtk->pData );
+            printf( "%s (%d)  ", Abc_NtkName(pNtk), pNtk->fHiePath );
     printf( "\n" );
-
-    // clean the boxes
+    // clean 
     Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
-        pNtk->pData = NULL;
+        pNtk->fHiePath = 0;
+}
 
+/**Function*************************************************************
 
-    // map actual nets into formal nets belonging to the undef boxes
-    vPivots = Vec_PtrAlloc( 100 );
-    Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
-    {
-        Abc_NtkForEachBlackbox( pNtk, pBox, k )
-        {
-            if ( pBox->pData == NULL || Ver_NtkIsDefined(pBox->pData) )
-                continue;
-            vNetPairs = (Vec_Ptr_t *)pBox->pCopy;
-            Vec_PtrForEachEntry( vNetPairs, pNet, m )
-            {
-                pNetAct = Vec_PtrEntry( vNetPairs, ++m );
-                // skip already driven nets and constants
-                if ( Abc_ObjFaninNum(pNetAct) == 1 )
-                    continue;
-                if ( !(strcmp(Abc_ObjName(pNetAct), "1\'b0") && strcmp(Abc_ObjName(pNetAct), "1\'b1")) ) // constant
-                    continue;
-                // add this net
-                if ( pNetAct->pData == NULL )
+  Synopsis    [Returns 1 if there are non-driven nets.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseCheckNondrivenNets( Vec_Ptr_t * vUndefs )
+{
+    Abc_Ntk_t * pNtk;
+    Ver_Bundle_t * pBundle;
+    Abc_Obj_t * pBox, * pNet;
+    int i, k, j, m;
+    // go through undef box types
+    Vec_PtrForEachEntry( vUndefs, pNtk, i )
+        // go through instances of this type
+        Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+            // go through the bundles of this instance
+            Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+                // go through the actual nets of this bundle
+                if ( pBundle )
+                Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
                 {
-                    pNetAct->pData = Vec_PtrAlloc( 16 );
-                    Vec_PtrPush( vPivots, pNetAct );
+                    char * pName = Abc_ObjName(pNet);
+                    if ( Abc_ObjFaninNum(pNet) == 0 ) // non-driven
+                        if ( strcmp(Abc_ObjName(pNet), "1\'b0") && strcmp(Abc_ObjName(pNet), "1\'b1") ) // diff from a const
+                            return 1;
                 }
-                vEnvoys = pNetAct->pData;
-                Vec_PtrPush( vEnvoys, pNet );
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Checks if formal nets with the given name are driven in any of the instances of undef boxes.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseFormalNetsAreDriven( Abc_Ntk_t * pNtk, char * pNameFormal )
+{
+    Ver_Bundle_t * pBundle;
+    Abc_Obj_t * pBox, * pNet;
+    int k, j, m;
+    // go through instances of this type
+    Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+    {
+        // find a bundle with the given name in this instance
+        Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+            if ( pBundle && !strcmp( pBundle->pNameFormal, pNameFormal ) )
+                break;
+        // skip non-driven bundles
+        if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+            continue;
+        // check if all nets are driven in this bundle
+        Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
+            if ( Abc_ObjFaninNum(pNet) > 0 )
+                return 1;
+    }
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Returns the non-driven bundle that is given distance from the end.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+Ver_Bundle_t * Ver_ParseGetNondrivenBundle( Abc_Ntk_t * pNtk, int Counter )
+{
+    Ver_Bundle_t * pBundle;
+    Abc_Obj_t * pBox, * pNet;
+    int k, m;
+    // go through instances of this type
+    Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+    {
+        if ( Counter >= Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+            continue;
+        // get the bundle given distance away
+        pBundle = Vec_PtrEntry( (Vec_Ptr_t *)pBox->pCopy, Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) - 1 - Counter );
+        if ( pBundle == NULL )
+            continue;
+        // go through the actual nets of this bundle
+        Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m )
+            if ( !Abc_ObjFaninNum(pNet) && !Ver_ParseFormalNetsAreDriven(pNtk, pBundle->pNameFormal) ) // non-driven
+                return pBundle;
+    }
+    return NULL;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Drives the bundle in the given undef box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseDriveFormal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_Bundle_t * pBundle0 )
+{
+    char Buffer[200];
+    char * pName;
+    Ver_Bundle_t * pBundle;
+    Abc_Obj_t * pBox, * pTerm, * pTermNew, * pNetAct, * pNetFormal;
+    int k, j, m;
+
+    // drive this net in the undef box
+    Vec_PtrForEachEntry( pBundle0->vNetsActual, pNetAct, m )
+    {
+        // create the formal net
+        if ( Vec_PtrSize(pBundle0->vNetsActual) == 1 )
+            sprintf( Buffer, "%s", pBundle0->pNameFormal );
+        else
+            sprintf( Buffer, "%s[%d]", pBundle0->pNameFormal, m );
+        assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL );
+        pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer );
+        // connect it to the box
+        pTerm = Abc_NtkCreateBo( pNtk );
+        assert( Abc_NtkBoxNum(pNtk) <= 1 );
+        pBox = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk);
+        Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNetFormal );
+        Abc_ObjAddFanin( pNetFormal, pTerm );
+        Abc_ObjAddFanin( pTerm, pBox );
+    }
+
+    // go through instances of this type
+    pName = Extra_UtilStrsav(pBundle0->pNameFormal);
+    Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+    {
+        // find a bundle with the given name in this instance
+        Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+            if ( pBundle && !strcmp( pBundle->pNameFormal, pName ) )
+                break;
+        // skip non-driven bundles
+        if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+            continue;
+        // check if any nets are driven in this bundle
+        Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m )
+            if ( Abc_ObjFaninNum(pNetAct) > 0 )
+            {
+                sprintf( pMan->sError, "Internal error while trying to connect undefined boxes. It is likely that the algorithm currently used has its limitations." );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
             }
+        // drive the nets by the undef box
+        Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m )
+        {
+            pTermNew = Abc_NtkCreateBo( pNetAct->pNtk );
+            Abc_ObjAddFanin( pTermNew, pBox );
+            Abc_ObjAddFanin( pNetAct, pTermNew );
         }
+        // remove the bundle
+        Ver_ParseFreeBundle( pBundle );
+        Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL );
     }
+    free( pName );
+    return 1;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Drives the bundle in the given undef box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
 
-    // for each pivot net, find the driver
-    Vec_PtrForEachEntry( vPivots, pNetAct, i )
+***********************************************************************/
+int Ver_ParseDriveInputs( Ver_Man_t * pMan, Vec_Ptr_t * vUndefs )
+{
+    char Buffer[200];
+    Ver_Bundle_t * pBundle;
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pBox, * pBox2, * pTerm, * pTermNew, * pNetFormal, * pNetAct;
+    int i, k, j, m, CountCur, CountTotal = -1;
+    // iterate through the undef boxes
+    Vec_PtrForEachEntry( vUndefs, pNtk, i )
     {
-        char * pName = Abc_ObjName(pNetAct);
-/*
-        if ( !strcmp( Abc_ObjName(pNetAct), "dma_fifo_ff_cnt[2]" ) )
+        // count the number of unconnected bundles for instances of this type of box
+        CountTotal = -1;
+        Vec_PtrForEachEntry( pNtk->pData, pBox, k )
         {
-            int x = 0;
+            CountCur = 0;
+            Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+                CountCur += (pBundle != NULL);
+            if ( CountTotal == -1 )
+                CountTotal = CountCur;
+            else if ( CountTotal != CountCur )
+            {
+                sprintf( pMan->sError, "The number of formal inputs (%d) is different from the expected one (%d) when instantiating network %s in box %s.", 
+                    CountCur, CountTotal, pNtk->pName, Abc_ObjName(pBox) );
+                Ver_ParsePrintErrorMessage( pMan );
+                return 0;
+            }
         }
-*/
-        assert( Abc_ObjFaninNum(pNetAct) == 0 );
-        assert( strcmp(Abc_ObjName(pNetAct), "1\'b0") && strcmp(Abc_ObjName(pNetAct), "1\'b1") );
-        vEnvoys = pNetAct->pData; pNetAct->pData = NULL;
-        // find the driver starting from the last nets
-        pNetDr = NULL;
-        for ( m = 0; m < 64; m++ )
+
+        // create formals
+        pBox = Vec_PtrEntry( pNtk->pData, 0 );
+        Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
         {
-            Vec_PtrForEachEntry( vEnvoys, pNet, k )
+            if ( pBundle == NULL )
+                continue;
+            Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m )
             {
-                if ( Abc_ObjId(pNet) == 0 )
+                // find create the formal net
+                if ( Vec_PtrSize(pBundle->vNetsActual) == 1 )
+                    sprintf( Buffer, "%s", pBundle->pNameFormal );
+                else
+                    sprintf( Buffer, "%s[%d]", pBundle->pNameFormal, m );
+                assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL );
+                pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer );
+                // connect
+                pTerm = Abc_NtkCreateBi( pNtk );
+                assert( Abc_NtkBoxNum(pNtk) <= 1 );
+                pBox2 = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk);
+                Abc_ObjAddFanin( pNetFormal, Abc_NtkCreatePi(pNtk) );
+                Abc_ObjAddFanin( pTerm, pNetFormal );
+                Abc_ObjAddFanin( pBox2, pTerm );
+            }
+        }
+
+        // go through all the boxes
+        Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+        {
+            // go through all the bundles
+            Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j )
+            {
+                if ( pBundle == NULL )
                     continue;
-                if ( (int)Abc_ObjId(pNet) == Abc_NtkObjNumMax(pNet->pNtk) - 1 - m )
+                // drive the nets by the undef box
+                Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m )
                 {
-                    pNetDr = pNet;
-                    break;
+                    pTermNew = Abc_NtkCreateBi( pNetAct->pNtk );
+                    Abc_ObjAddFanin( pBox, pTermNew );
+                    Abc_ObjAddFanin( pTermNew, pNetAct );
                 }
+                // remove the bundle
+                Ver_ParseFreeBundle( pBundle );
+                Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL );
             }
-            if ( pNetDr )
-                break;
+
+            // free the bundles
+            Vec_PtrFree( (Vec_Ptr_t *)pBox->pCopy );
+            pBox->pCopy = NULL;
         }
-        assert( pNetDr != NULL );
-        Vec_PtrWriteEntry( vPivots, i, pNetDr );
-        Vec_PtrFree( vEnvoys );
     }
+    return 1;
+}
 
-    // for each pivot net, create driver
-    Vec_PtrForEachEntry( vPivots, pNetDr, i )
-    {
-        if ( pNetDr == NULL )
-            continue;
-        assert( Abc_ObjFaninNum(pNetDr) <= 1 );
-        if ( Abc_ObjFaninNum(pNetDr) == 1 )
-            continue;
-        // drive this net with the box
-        pTerm = Abc_NtkCreateBo( pNetDr->pNtk );
-        assert( Abc_NtkBoxNum(pNetDr->pNtk) <= 1 );
-        pBox = Abc_NtkBoxNum(pNetDr->pNtk)? Abc_NtkBox(pNetDr->pNtk,0) : Abc_NtkCreateBlackbox(pNetDr->pNtk);
-        Abc_ObjAddFanin( Abc_NtkCreatePo(pNetDr->pNtk), pNetDr );
-        Abc_ObjAddFanin( pNetDr, pTerm );
-        Abc_ObjAddFanin( pTerm, pBox );
-    }
-    Vec_PtrFree( vPivots );
 
-    // connect the remaining boxes
-    Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+/**Function*************************************************************
+
+  Synopsis    [Returns the max size of any undef box.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseMaxBoxSize( Vec_Ptr_t * vUndefs )
+{
+    Abc_Ntk_t * pNtk;
+    Abc_Obj_t * pBox;
+    int i, k, nMaxSize = 0;
+    // go through undef box types
+    Vec_PtrForEachEntry( vUndefs, pNtk, i )
+        // go through instances of this type
+        Vec_PtrForEachEntry( pNtk->pData, pBox, k )
+            // check the number of bundles of this instance
+            if ( nMaxSize < Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) )
+                nMaxSize = Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy);
+    return nMaxSize;
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    [Attaches the boxes to the network.]
+
+  Description [This procedure is called after the design is parsed. 
+  At that point, all the defined models have their PIs present. 
+  They are connected first. Next undef boxes are processed (if present).
+  Iteratively, one bundle is selected to be driven by the undef boxes in such 
+  a way that there is no conflict (if it is driven by an instance of the box,
+  no other net will be driven twice by the same formal net of some other instance 
+  of the same box). In the end, all the remaining nets that cannot be driven 
+  by the undef boxes are connected to the undef boxes as inputs.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Ver_ParseAttachBoxes( Ver_Man_t * pMan )
+{
+    Abc_Ntk_t * pNtk;
+    Ver_Bundle_t * pBundle;
+    Vec_Ptr_t * vUndefs;
+    int i, RetValue, Counter, nMaxBoxSize;
+
+    // connect defined boxes
+    RetValue = Ver_ParseConnectDefBoxes( pMan );
+    if ( RetValue < 2 )
+        return RetValue;
+
+    // report the boxes
+    Ver_ParseReportUndefBoxes( pMan );
+
+    // collect undef box types and their actual instances
+    vUndefs = Ver_ParseCollectUndefBoxes( pMan );
+    assert( Vec_PtrSize( vUndefs ) > 0 );
+
+    // go through all undef box types
+    Counter = 0;
+    nMaxBoxSize = Ver_ParseMaxBoxSize( vUndefs );
+    while ( Ver_ParseCheckNondrivenNets(vUndefs) && Counter < nMaxBoxSize )
     {
-        if ( Abc_NtkPiNum(pNtk) )
-            continue;
-        Abc_NtkForEachNet( pNtk, pNet, k )
+        // go through undef box types
+        pBundle = NULL;
+        Vec_PtrForEachEntry( vUndefs, pNtk, i )
+            if ( pBundle = Ver_ParseGetNondrivenBundle( pNtk, Counter ) )
+                break;
+        if ( pBundle == NULL )
         {
-            if ( Abc_ObjFaninNum(pNet) )
-                continue;
-            // drive this net
-            pTerm = Abc_NtkCreateBi( pNet->pNtk );
-            assert( Abc_NtkBoxNum(pNet->pNtk) <= 1 );
-            pBox = Abc_NtkBoxNum(pNet->pNtk)? Abc_NtkBox(pNet->pNtk,0) : Abc_NtkCreateBlackbox(pNet->pNtk);
-            Abc_ObjAddFanin( pBox, pTerm );
-            Abc_ObjAddFanin( pTerm, pNet );
-            Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(pNet->pNtk) );
+            Counter++;
+            continue;
         }
+        // drive this bundle by this box
+        if ( !Ver_ParseDriveFormal( pMan, pNtk, pBundle ) )
+            return 0;
     }
 
-    // connect the remaining boxes
-    Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i )
+    // make all the remaining bundles the drivers of undefs
+    if ( !Ver_ParseDriveInputs( pMan, vUndefs ) )
+        return 0;
+
+    // cleanup
+    Vec_PtrForEachEntry( vUndefs, pNtk, i )
     {
-        Abc_NtkForEachBlackbox( pNtk, pBox, k )
-        {
-            char * pName = Abc_ObjName(pBox);
-            if ( !Ver_ObjIsConnected(pBox) )
-                if ( !Ver_ParseConnectBox( pMan, pBox ) )
-                    return 0;
-        }
+        Vec_PtrFree( pNtk->pData );
+        pNtk->pData = NULL;
     }
+    Vec_PtrFree( vUndefs ); 
     return 1;
 }
 
@@ -1716,55 +2598,12 @@ Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet )
 {
     Abc_Obj_t * pObj;
     pObj = Abc_NtkCreateNodeInv( pNtk, pNet );
-    pNet = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
+    pNet = Abc_NtkCreateNet( pNtk );
     Abc_ObjAddFanin( pNet, pObj );
     return pNet;
 }
 
 
-
-/*
-    // allocate memory to remember the phase
-    pPolarity = NULL;
-    if ( fComplUsed )
-    {
-        int nBytes = 4 * Abc_BitWordNum( Abc_NtkPiNum(pNtkBox) );
-        pPolarity = (unsigned *)Extra_MmFlexEntryFetch( pNtk->pData, nBytes );
-        memset( pPolarity, 0, nBytes );
-    }
-    // create box to represent this gate
-    if ( Abc_NtkHasBlackbox(pNtkBox) )
-        pNode = Abc_NtkCreateBlackbox( pNtk );
-    else
-        pNode = Abc_NtkCreateWhitebox( pNtk );
-    pNode->pNext = (Abc_Obj_t *)pPolarity;
-    pNode->pData = pNtkBox;
-    // connect to fanin nets
-    Abc_NtkForEachPi( pNtkBox, pObj, i )
-    {
-        if ( pPolarity && Abc_ObjIsComplement(pObj->pCopy) )
-        {
-            Abc_InfoSetBit( pPolarity, i );
-            pObj->pCopy = Abc_ObjRegular( pObj->pCopy );
-        }
-        assert( !Abc_ObjIsComplement(pObj->pCopy) );
-//        Abc_ObjAddFanin( pNode, pObj->pCopy );
-        pTerm = Abc_NtkCreateBi( pNtk );
-        Abc_ObjAddFanin( pTerm, pObj->pCopy );
-        Abc_ObjAddFanin( pNode, pTerm );
-    }
-    // connect to fanout nets
-    Abc_NtkForEachPo( pNtkBox, pObj, i )
-    {
-        if ( pObj->pCopy == NULL )
-            pObj->pCopy = Abc_NtkFindOrCreateNet(pNtk, NULL);
-//        Abc_ObjAddFanin( pObj->pCopy, pNode );
-        pTerm = Abc_NtkCreateBo( pNtk );
-        Abc_ObjAddFanin( pTerm, pNode );
-        Abc_ObjAddFanin( pObj->pCopy, pTerm );
-    }
-*/
-
 ////////////////////////////////////////////////////////////////////////
 ///                       END OF FILE                                ///
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/base/ver/verCore.zip b/src/base/ver/verCore.zip
new file mode 100644
index 00000000..481f7e6a
Binary files /dev/null and b/src/base/ver/verCore.zip differ
diff --git a/src/base/ver/verFormula.c b/src/base/ver/verFormula.c
index 253754ae..19a2c523 100644
--- a/src/base/ver/verFormula.c
+++ b/src/base/ver/verFormula.c
@@ -120,7 +120,7 @@ void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_
         case '\r':
         case '\n':
             continue;
-
+/*
         // treat Constant 0 as a variable
         case VER_PARSE_SYM_CONST0:
             Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) );  // Cudd_Ref( Hop_ManConst0(pMan) );
@@ -144,7 +144,7 @@ void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_
             }
             Flag = VER_PARSE_FLAG_VAR; 
             break;
-
+*/
         case VER_PARSE_SYM_NEGBEF1:
         case VER_PARSE_SYM_NEGBEF2:
             if ( Flag == VER_PARSE_FLAG_VAR )
diff --git a/src/bdd/cas/module.make b/src/bdd/cas/module.make
index a563e96d..7830e47f 100644
--- a/src/bdd/cas/module.make
+++ b/src/bdd/cas/module.make
@@ -1,2 +1,3 @@
 SRC +=    src/bdd/cas/casCore.c \
-    src/bdd/cas/casDec
+    src/bdd/cas/casDec.c
+
diff --git a/src/map/if/if.h b/src/map/if/if.h
index 81d4007c..7e22707f 100644
--- a/src/map/if/if.h
+++ b/src/map/if/if.h
@@ -46,7 +46,9 @@ extern "C" {
 // the largest possible number of LUT inputs when funtionality of the LUTs are computed
 #define IF_MAX_FUNC_LUTSIZE  15
 // a very large number
-#define IF_INFINITY          100000000   
+#define IF_INFINITY          100000000  
+// the largest possible user cut cost
+#define IF_COST_MAX          ((1<<14)-1)
 
 // object types
 typedef enum { 
@@ -55,10 +57,7 @@ typedef enum {
     IF_CI,       // 2: combinational input
     IF_CO,       // 3: combinational output
     IF_AND,      // 4: AND node
-    IF_BI,       // 5: box input
-    IF_BO,       // 6: box output
-    IF_BOX,      // 7: box
-    IF_VOID      // 8: unused object
+    IF_VOID      // 5: unused object
 } If_Type_t;
 
 ////////////////////////////////////////////////////////////////////////
@@ -70,6 +69,7 @@ typedef struct If_Par_t_     If_Par_t;
 typedef struct If_Lib_t_     If_Lib_t;
 typedef struct If_Obj_t_     If_Obj_t;
 typedef struct If_Cut_t_     If_Cut_t;
+typedef struct If_Set_t_     If_Set_t;
 
 // parameters
 struct If_Par_t_
@@ -88,11 +88,13 @@ struct If_Par_t_
     int                fSeqMap;       // sequential mapping
     int                fVerbose;      // the verbosity flag
     // internal parameters
+    int                fAreaOnly;     // area only mode
     int                fTruth;        // truth table computation enabled
     int                fUsePerm;      // use permutation (delay info)
-    int                fUseBdds;      // sets local BDDs at the nodes
-    int                fUseSops;      // sets local SOPs at the nodes
-    int                fUseCnfs;      // sets local CNFs at the nodes
+    int                fUseBdds;      // use local BDDs as a cost function
+    int                fUseSops;      // use local SOPs as a cost function
+    int                fUseCnfs;      // use local CNFs as a cost function
+    int                fUseMv;        // use local MV-SOPs as a cost function
     int                nLatches;      // the number of latches in seq mapping
     int                fLiftLeaves;   // shift the leaves for seq mapping
     If_Lib_t *         pLutLib;       // the LUT library
@@ -129,11 +131,14 @@ struct If_Man_t_
     int                nLevelMax;     // the max number of AIG levels
     float              fEpsilon;      // epsilon used for comparison
     float              RequiredGlo;   // global required times
+    float              RequiredGlo2;  // global required times
     float              AreaGlo;       // global area
     int                nNets;         // the sum total of fanins of all LUTs in the mapping
     int                nCutsUsed;     // the number of cuts currently used
     int                nCutsMerged;   // the total number of cuts merged
     unsigned *         puTemp[4];     // used for the truth table computation
+    int                SortMode;      // one of the three sorting modes
+    int                fNextRound;    // set to 1 after the first round
     // sequential mapping
     Vec_Ptr_t *        vLatchOrder;   // topological ordering of latches
     Vec_Int_t *        vLags;         // sequentail lags of all nodes
@@ -141,15 +146,16 @@ struct If_Man_t_
     int                nMaxIters;     // the maximum number of iterations
     int                Period;        // the current value of the clock period (for seq mapping)
     // memory management
-    Mem_Fixed_t *      pMem;          // memory manager
-    int                nEntrySize;    // the size of the entry
-    int                nEntryBase;    // the size of the entry minus cut leaf arrays
-    int                nTruthSize;    // the size of the truth table if allocated
-    int                nPermSize;     // the size of the permutation array (in words)
-    int                nCutSize;      // the size of the cut
-    // temporary cut storage
-    int                nCuts;         // the number of cuts used
-    If_Cut_t **        ppCuts;        // the storage space for cuts
+    int                nTruthWords;   // the size of the truth table if allocated
+    int                nPermWords;    // the size of the permutation array (in words)
+    int                nObjBytes;     // the size of the object
+    int                nCutBytes;     // the size of the cut
+    int                nSetBytes;     // the size of the cut set
+    Mem_Fixed_t *      pMemObj;       // memory manager for objects (entrysize = nEntrySize)
+    Mem_Fixed_t *      pMemSet;       // memory manager for sets of cuts (entrysize = nCutSize*(nCutsMax+1))
+    If_Set_t *         pMemCi;        // memory for CI cutsets
+    If_Set_t *         pMemAnd;       // memory for AND cutsets
+    If_Set_t *         pFreeList;     // the list of free cutsets
 };
 
 // priority cut
@@ -169,6 +175,15 @@ struct If_Cut_t_
     unsigned *         pTruth;        // the truth table
 };
 
+// set of priority cut
+struct If_Set_t_
+{
+    short              nCutsMax;      // the max number of cuts
+    short              nCuts;         // the current number of cuts
+    If_Set_t *         pNext;         // next cutset in the free list
+    If_Cut_t **        ppCuts;        // the array of pointers to the cuts
+};
+
 // node extension
 struct If_Obj_t_
 {
@@ -182,36 +197,37 @@ struct If_Obj_t_
     unsigned           Level   : 22;  // logic level of the node
     int                Id;            // integer ID
     int                nRefs;         // the number of references
-    int                nCuts;         // the number of cuts
+    int                nVisits;       // the number of visits to this node
+    int                nVisitsCopy;   // the number of visits to this node
     If_Obj_t *         pFanin0;       // the first fanin 
     If_Obj_t *         pFanin1;       // the second fanin
     If_Obj_t *         pEquiv;        // the choice node
     float              EstRefs;       // estimated reference counter
     float              Required;      // required time of the onde
-    void *             pCopy;         // used for duplication
-    If_Cut_t           Cuts[0];       // the cuts of the node
+    float              LValue;        // sequential arrival time of the node
+    void *             pCopy;         // used for object duplication
+    If_Set_t *         pCutSet;       // the pointer to the cutset
+    If_Cut_t           CutBest;       // the best cut selected 
 };
 
-static inline If_Obj_t * If_ManConst1( If_Man_t * p )                        { return p->pConst1;                              }
-static inline If_Obj_t * If_ManCi( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i );  }
-static inline If_Obj_t * If_ManCo( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i );  }
-static inline If_Obj_t * If_ManObj( If_Man_t * p, int i )                    { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); }
-static inline If_Cut_t * If_ManCut( If_Man_t * p, int i )                    { return p->ppCuts[i];                            }
-
 static inline int        If_ManCiNum( If_Man_t * p )                         { return p->nObjs[IF_CI];               }
 static inline int        If_ManCoNum( If_Man_t * p )                         { return p->nObjs[IF_CO];               }
 static inline int        If_ManAndNum( If_Man_t * p )                        { return p->nObjs[IF_AND];              }
 static inline int        If_ManObjNum( If_Man_t * p )                        { return Vec_PtrSize(p->vObjs);         }
 
+static inline If_Obj_t * If_ManConst1( If_Man_t * p )                        { return p->pConst1;                              }
+static inline If_Obj_t * If_ManCi( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i );  }
+static inline If_Obj_t * If_ManCo( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i );  }
+static inline If_Obj_t * If_ManLi( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCos, If_ManCoNum(p) - p->pPars->nLatches + i );  }
+static inline If_Obj_t * If_ManLo( If_Man_t * p, int i )                     { return (If_Obj_t *)Vec_PtrEntry( p->vCis, If_ManCiNum(p) - p->pPars->nLatches + i );  }
+static inline If_Obj_t * If_ManObj( If_Man_t * p, int i )                    { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); }
+
 static inline int        If_ObjIsConst1( If_Obj_t * pObj )                   { return pObj->Type == IF_CONST1;       }
 static inline int        If_ObjIsCi( If_Obj_t * pObj )                       { return pObj->Type == IF_CI;           }
 static inline int        If_ObjIsCo( If_Obj_t * pObj )                       { return pObj->Type == IF_CO;           }
 static inline int        If_ObjIsPi( If_Obj_t * pObj )                       { return If_ObjIsCi(pObj) && pObj->pFanin0 == NULL; }
 static inline int        If_ObjIsLatch( If_Obj_t * pObj )                    { return If_ObjIsCi(pObj) && pObj->pFanin0 != NULL; }
 static inline int        If_ObjIsAnd( If_Obj_t * pObj )                      { return pObj->Type == IF_AND;          }
-static inline int        If_ObjIsBi( If_Obj_t * pObj )                       { return pObj->Type == IF_BI;           }
-static inline int        If_ObjIsBo( If_Obj_t * pObj )                       { return pObj->Type == IF_BO;           }
-static inline int        If_ObjIsBox( If_Obj_t * pObj )                      { return pObj->Type == IF_BOX;          }
 
 static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj )                     { return pObj->pFanin0;                 }
 static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj )                     { return pObj->pFanin1;                 }
@@ -221,13 +237,14 @@ static inline void *     If_ObjCopy( If_Obj_t * pObj )                       { r
 static inline void       If_ObjSetCopy( If_Obj_t * pObj, void * pCopy )      { pObj->pCopy = pCopy;                  }
 static inline void       If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu;                  }
 
-static inline If_Cut_t * If_ObjCut( If_Obj_t * pObj, int iCut )              { return pObj->Cuts + iCut;             }
-static inline If_Cut_t * If_ObjCutTriv( If_Obj_t * pObj )                    { return pObj->Cuts;                    }
-static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj )                    { return pObj->Cuts + (int)(pObj->nCuts > 1); }
+static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj )                    { return &pObj->CutBest;                }
 static inline unsigned   If_ObjCutSign( unsigned ObjId )                     { return (1 << (ObjId % 31));           }
 
-static inline float      If_ObjLValue( If_Obj_t * pObj )                     { return If_ObjCutTriv(pObj)->Delay;    }
-static inline void       If_ObjSetLValue( If_Obj_t * pObj, float LValue )    { If_ObjCutTriv(pObj)->Delay = LValue;  }
+static inline float      If_ObjArrTime( If_Obj_t * pObj )                    { return If_ObjCutBest(pObj)->Delay;    }
+static inline void       If_ObjSetArrTime( If_Obj_t * pObj, float ArrTime )  { If_ObjCutBest(pObj)->Delay = ArrTime; }
+
+static inline float      If_ObjLValue( If_Obj_t * pObj )                     { return pObj->LValue;                  }
+static inline void       If_ObjSetLValue( If_Obj_t * pObj, float LValue )    { pObj->LValue = LValue;                }
 
 static inline void *     If_CutData( If_Cut_t * pCut )                       { return *(void **)pCut;                }
 static inline void       If_CutSetData( If_Cut_t * pCut, void * pData )      { *(void **)pCut = pData;               }
@@ -264,20 +281,19 @@ static inline float      If_CutLutArea( If_Man_t * p, If_Cut_t * pCut )      { r
 #define If_ManForEachPo( p, pObj, i )                                          \
     Vec_PtrForEachEntryStop( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches )
 // iterator over the latches 
-#define If_ManForEachLatch( p, pObj, i )                                       \
+#define If_ManForEachLatchInput( p, pObj, i )                                  \
     Vec_PtrForEachEntryStart( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches )
+#define If_ManForEachLatchOutput( p, pObj, i )                                 \
+    Vec_PtrForEachEntryStart( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches )
 // iterator over all objects, including those currently not used
 #define If_ManForEachObj( p, pObj, i )                                         \
     Vec_PtrForEachEntry( p->vObjs, pObj, i )
-// iterator over logic nodes (AND and EXOR gates)
+// iterator over logic nodes 
 #define If_ManForEachNode( p, pObj, i )                                        \
     If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else
 // iterator over cuts of the node
 #define If_ObjForEachCut( pObj, pCut, i )                                      \
-    for ( i = 0; (i < (int)(pObj)->nCuts) && ((pCut) = (pObj)->Cuts + i); i++ )
-// iterator over cuts of the node
-#define If_ObjForEachCutStart( pObj, pCut, i, Start )                          \
-    for ( i = Start; (i < (int)(pObj)->nCuts) && ((pCut) = (pObj)->Cuts + i); i++ )
+    for ( i = 0; (i < (pObj)->pCutSet->nCuts) && ((pCut) = (pObj)->pCutSet->ppCuts[i]); i++ )
 // iterator over the leaves of the cut
 #define If_CutForEachLeaf( p, pCut, pLeaf, i )                                 \
     for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ )
@@ -295,6 +311,7 @@ static inline float      If_CutLutArea( If_Man_t * p, If_Cut_t * pCut )      { r
 
 /*=== ifCore.c ===========================================================*/
 extern int             If_ManPerformMapping( If_Man_t * p );
+extern int             If_ManPerformMappingComb( If_Man_t * p );
 /*=== ifCut.c ============================================================*/
 extern float           If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels );
 extern float           If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels );
@@ -304,10 +321,11 @@ extern void            If_CutPrint( If_Man_t * p, If_Cut_t * pCut );
 extern void            If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut );
 extern float           If_CutFlow( If_Man_t * p, If_Cut_t * pCut );
 extern float           If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut );
-extern int             If_CutFilter( If_Man_t * p, If_Cut_t * pCut );
+extern int             If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut );
+extern void            If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut );
 extern int             If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut );
 extern void            If_CutLift( If_Cut_t * pCut );
-extern void            If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
+extern void            If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
 extern void            If_ManSortCuts( If_Man_t * p, int Mode );
 /*=== ifMan.c =============================================================*/
 extern If_Man_t *      If_ManStart( If_Par_t * pPars );
@@ -316,12 +334,16 @@ extern If_Obj_t *      If_ManCreateCi( If_Man_t * p );
 extern If_Obj_t *      If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver, int fCompl0 );
 extern If_Obj_t *      If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_t * pFan1, int fCompl1 );
 extern void            If_ManCreateChoice( If_Man_t * p, If_Obj_t * pRepr );
+extern void            If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId );
+extern void            If_ManSetupCiCutSets( If_Man_t * p );
+extern If_Set_t *      If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void            If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void            If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj );
+extern void            If_ManSetupSetAll( If_Man_t * p );
 /*=== ifMap.c =============================================================*/
-extern void            If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode );
-extern void            If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode );
-extern int             If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fRequired, char * pLabel );
-/*=== ifPrepro.c ==========================================================*/
-extern void            If_ManPerformMappingPreprocess( If_Man_t * p );
+extern void            If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );
+extern void            If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess );
+extern int             If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel );
 /*=== ifReduce.c ==========================================================*/
 extern void            If_ManImproveMapping( If_Man_t * p );
 /*=== ifSeq.c =============================================================*/
@@ -336,9 +358,11 @@ extern void            If_ManCleanNodeCopy( If_Man_t * p );
 extern void            If_ManCleanCutData( If_Man_t * p );
 extern void            If_ManCleanMarkV( If_Man_t * p );
 extern float           If_ManDelayMax( If_Man_t * p, int fSeq );
-extern void            If_ManComputeRequired( If_Man_t * p, int fFirstTime );
+extern void            If_ManComputeRequired( If_Man_t * p );
 extern float           If_ManScanMapping( If_Man_t * p );
 extern float           If_ManScanMappingSeq( If_Man_t * p );
+extern void            If_ManResetOriginalRefs( If_Man_t * p );
+extern int             If_ManCrossCut( If_Man_t * p );
 
 #ifdef __cplusplus
 }
diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c
index be2c7e33..60ddcbe1 100644
--- a/src/map/if/ifCore.c
+++ b/src/map/if/ifCore.c
@@ -41,54 +41,98 @@
 ***********************************************************************/
 int If_ManPerformMapping( If_Man_t * p )
 {
-    If_Obj_t * pObj;
-    int clkTotal = clock();
-    int RetValue, i;
+    p->pPars->fAreaOnly = p->pPars->fArea; // temporary
+
+    // create the CI cutsets
+    If_ManSetupCiCutSets( p );
+    // allocate memory for other cutsets
+    If_ManSetupSetAll( p );
 
     // try sequential mapping
     if ( p->pPars->fSeqMap )
     {
+        int RetValue;
+//        printf( "Currently sequential mapping is not performed.\n" );
         RetValue = If_ManPerformMappingSeq( p );
-        if ( p->pPars->fVerbose )
-        {
-            PRT( "Total time", clock() - clkTotal );
-        }
         return RetValue;
+//        return 1;
     }
 
-    // set arrival times and trivial cuts at const 1 and PIs
-    If_ManConst1(p)->Cuts[0].Delay = 0.0;
-    If_ManForEachCi( p, pObj, i )
-        pObj->Cuts[0].Delay = p->pPars->pTimesArr[i];
-    // set the fanout estimates of the PIs
+    return If_ManPerformMappingComb( p );
+}
+
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManPerformMappingComb( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int clkTotal = clock();
+    int i;
+
+    // set arrival times and fanout estimates
     If_ManForEachCi( p, pObj, i )
+    {
+        If_ObjSetArrTime( pObj, p->pPars->pTimesArr[i] );
         pObj->EstRefs = (float)1.0;
+    }
+
     // delay oriented mapping
-    if ( p->pPars->fPreprocess && !p->pPars->fArea && p->pPars->nCutsMax >= 4  )
-        If_ManPerformMappingPreprocess( p );
-    else
+    if ( p->pPars->fPreprocess && !p->pPars->fArea )
+    {
+        // map for delay
         If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay" );
+        // map for delay second option
+        p->pPars->fFancy = 1;
+        If_ManResetOriginalRefs( p );
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay-2" );
+        p->pPars->fFancy = 0;
+        // map for area
+        p->pPars->fArea = 1;
+        If_ManResetOriginalRefs( p );
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Area" );
+        p->pPars->fArea = 0;
+    }
+    else
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, "Delay" );
+
     // try to improve area by expanding and reducing the cuts
     if ( p->pPars->fExpRed && !p->pPars->fTruth )
         If_ManImproveMapping( p );
+
     // area flow oriented mapping
     for ( i = 0; i < p->pPars->nFlowIters; i++ )
     {
-        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 1, "Flow" );
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, "Flow" );
         if ( p->pPars->fExpRed && !p->pPars->fTruth )
             If_ManImproveMapping( p );
     }
+
     // area oriented mapping
     for ( i = 0; i < p->pPars->nAreaIters; i++ )
     {
-        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 1, "Area" );
+        If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, "Area" );
         if ( p->pPars->fExpRed && !p->pPars->fTruth )
             If_ManImproveMapping( p );
     }
+
     if ( p->pPars->fVerbose )
     {
+//        printf( "Total memory = %7.2f Mb. Peak cut memory = %7.2f Mb.  ", 
+//            1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), 
+//            1.0 * p->nSetBytes * Mem_FixedReadMaxEntriesUsed(p->pMemSet) / (1<<20) );
         PRT( "Total time", clock() - clkTotal );
     }
+//    printf( "Cross cut memory = %d.\n", Mem_FixedReadMaxEntriesUsed(p->pMemSet) );
     return 1;
 }
 
diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c
index f0663f7f..57dd2c41 100644
--- a/src/map/if/ifCut.c
+++ b/src/map/if/ifCut.c
@@ -87,13 +87,14 @@ static inline int If_CutCheckEquality( If_Cut_t * pDom, If_Cut_t * pCut )
   SeeAlso     []
 
 ***********************************************************************/
-int If_CutFilter( If_Man_t * p, If_Cut_t * pCut )
-{
+int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut )
+{ 
     If_Cut_t * pTemp;
-    int i;
-    for ( i = 0; i < p->nCuts; i++ )
+    int i, k;
+    assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut );
+    for ( i = 0; i < pCutSet->nCuts; i++ )
     {
-        pTemp = p->ppCuts[i];
+        pTemp = pCutSet->ppCuts[i];
         if ( pTemp->nLeaves > pCut->nLeaves )
         {
             // do not fiter the first cut
@@ -105,10 +106,15 @@ int If_CutFilter( If_Man_t * p, If_Cut_t * pCut )
             // check containment seriously
             if ( If_CutCheckDominance( pCut, pTemp ) )
             {
-                // removed contained cut
-                p->ppCuts[i] = p->ppCuts[p->nCuts-1];
-                p->ppCuts[p->nCuts-1] = pTemp;
-                p->nCuts--;
+//                p->ppCuts[i] = p->ppCuts[p->nCuts-1];
+//                p->ppCuts[p->nCuts-1] = pTemp;
+//                p->nCuts--;
+//                i--;
+                // remove contained cut
+                for ( k = i; k < pCutSet->nCuts; k++ )
+                    pCutSet->ppCuts[k] = pCutSet->ppCuts[k+1];
+                pCutSet->ppCuts[pCutSet->nCuts] = pTemp;
+                pCutSet->nCuts--;
                 i--;
             }
          }
@@ -290,6 +296,7 @@ int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut )
         if ( !If_CutMergeOrdered( pCut0, pCut1, pCut ) )
             return 0;
     }
+    pCut->uSign = pCut0->uSign | pCut1->uSign;
     return 1;
 }
 
@@ -400,6 +407,7 @@ int If_CutCompareArea( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
 ***********************************************************************/
 void If_ManSortCuts( If_Man_t * p, int Mode )
 {
+/*
     // sort the cuts
     if ( Mode || p->pPars->fArea ) // area
         qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea );
@@ -407,6 +415,115 @@ void If_ManSortCuts( If_Man_t * p, int Mode )
         qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelayOld );
     else
         qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay );
+*/
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Comparison function for two cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 )
+{
+    if ( p->SortMode == 1 ) // area
+    {
+        if ( pC0->Area < pC1->Area - 0.0001 )
+            return -1;
+        if ( pC0->Area > pC1->Area + 0.0001 )
+            return 1;
+        if ( pC0->AveRefs > pC1->AveRefs )
+            return -1;
+        if ( pC0->AveRefs < pC1->AveRefs )
+            return 1;
+        if ( pC0->nLeaves < pC1->nLeaves )
+            return -1;
+        if ( pC0->nLeaves > pC1->nLeaves )
+            return 1;
+        if ( pC0->Delay < pC1->Delay - 0.0001 )
+            return -1;
+        if ( pC0->Delay > pC1->Delay + 0.0001 )
+            return 1;
+        return 0;
+    }
+    if ( p->SortMode == 0 ) // delay
+    {
+        if ( pC0->Delay < pC1->Delay - 0.0001 )
+            return -1;
+        if ( pC0->Delay > pC1->Delay + 0.0001 )
+            return 1;
+        if ( pC0->nLeaves < pC1->nLeaves )
+            return -1;
+        if ( pC0->nLeaves > pC1->nLeaves )
+            return 1;
+        if ( pC0->Area < pC1->Area - 0.0001 )
+            return -1;
+        if ( pC0->Area > pC1->Area + 0.0001 )
+            return 1;
+        return 0;
+    }
+    assert( p->SortMode == 2 ); // delay old
+    if ( pC0->Delay < pC1->Delay - 0.0001 )
+        return -1;
+    if ( pC0->Delay > pC1->Delay + 0.0001 )
+        return 1;
+    if ( pC0->Area < pC1->Area - 0.0001 )
+        return -1;
+    if ( pC0->Area > pC1->Area + 0.0001 )
+        return 1;
+    if ( pC0->nLeaves < pC1->nLeaves )
+        return -1;
+    if ( pC0->nLeaves > pC1->nLeaves )
+        return 1;
+    return 0;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Performs incremental sorting of cuts.]
+
+  Description [Currently only the trivial sorting is implemented.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut )
+{
+//    int Counter = 0;
+    int i;
+
+    // the new cut is the last one
+    assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut );
+    assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+
+    // cut structure is empty
+    if ( pCutSet->nCuts == 0 )
+    {
+        pCutSet->nCuts++;
+        return;
+    }
+
+    // the cut will be added - find its place
+    for ( i = pCutSet->nCuts-1; i >= 0; i-- )
+    {
+//        Counter++;
+        if ( If_ManSortCompare( p, pCutSet->ppCuts[i], pCut ) <= 0 )
+            break;
+        pCutSet->ppCuts[i+1] = pCutSet->ppCuts[i];
+        pCutSet->ppCuts[i] = pCut;
+    }
+//    printf( "%d ", Counter );
+
+    // update the number of cuts
+    if ( pCutSet->nCuts < pCutSet->nCutsMax )
+        pCutSet->nCuts++;
 }
 
 /**Function*************************************************************
@@ -635,7 +752,7 @@ void If_CutLift( If_Cut_t * pCut )
   SeeAlso     []
 
 ***********************************************************************/
-void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
+void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
 {
     int * pLeaves;
     char * pPerm;
@@ -645,17 +762,11 @@ void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
     pPerm   = pCutDest->pPerm;
     pTruth  = pCutDest->pTruth;
     // copy the cut info
-    *pCutDest = *pCutSrc;
+    memcpy( pCutDest, pCutSrc, p->nCutBytes );
     // restore the arrays
     pCutDest->pLeaves = pLeaves;
     pCutDest->pPerm   = pPerm;
     pCutDest->pTruth  = pTruth;
-    // copy the array data
-    memcpy( pCutDest->pLeaves, pCutSrc->pLeaves, sizeof(int) * pCutSrc->nLeaves );
-    if ( pCutSrc->pPerm )
-        memcpy( pCutDest->pPerm, pCutSrc->pPerm, sizeof(unsigned) * If_CutPermWords(pCutSrc->nLimit) );
-    if ( pCutSrc->pTruth )
-        memcpy( pCutDest->pTruth, pCutSrc->pTruth, sizeof(unsigned) * If_CutTruthWords(pCutSrc->nLimit) );
 }
 
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c
index 84a0c52f..20b2657f 100644
--- a/src/map/if/ifMan.c
+++ b/src/map/if/ifMan.c
@@ -25,7 +25,9 @@
 ////////////////////////////////////////////////////////////////////////
 
 static If_Obj_t * If_ManSetupObj( If_Man_t * p );
-static If_Cut_t ** If_ManSetupCuts( If_Man_t * p );
+
+static void       If_ManCutSetRecycle( If_Man_t * p, If_Set_t * pSet ) { pSet->pNext = p->pFreeList; p->pFreeList = pSet;                            }
+static If_Set_t * If_ManCutSetFetch( If_Man_t * p )                    { If_Set_t * pTemp = p->pFreeList; p->pFreeList = p->pFreeList->pNext; return pTemp; }
 
 ////////////////////////////////////////////////////////////////////////
 ///                     FUNCTION DEFINITIONS                         ///
@@ -57,27 +59,26 @@ If_Man_t * If_ManStart( If_Par_t * pPars )
     p->vMapped = Vec_PtrAlloc( 100 );
     p->vTemp   = Vec_PtrAlloc( 100 );
     // prepare the memory manager
-    p->nTruthSize = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0;
-    p->nPermSize  = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0;
-    p->nCutSize   = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermSize + p->nTruthSize);
-    p->nEntrySize = sizeof(If_Obj_t) + p->pPars->nCutsMax * p->nCutSize;
-    p->nEntryBase = sizeof(If_Obj_t) + p->pPars->nCutsMax * sizeof(If_Cut_t);
-    p->pMem = Mem_FixedStart( p->nEntrySize );
+    p->nTruthWords = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0;
+    p->nPermWords  = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0;
+    p->nObjBytes   = sizeof(If_Obj_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords);
+    p->nCutBytes   = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords);
+    p->nSetBytes   = sizeof(If_Set_t) + (sizeof(If_Cut_t *) + p->nCutBytes) * (p->pPars->nCutsMax + 1);
+    p->pMemObj     = Mem_FixedStart( p->nObjBytes );
+//    p->pMemSet     = Mem_FixedStart( p->nSetBytes );
     // report expected memory usage
     if ( p->pPars->fVerbose )
-        printf( "Memory (bytes): Truth = %3d. Cut = %3d. Entry = %4d. Total = %.2f Mb / 1K AIG nodes\n", 
-            4 * p->nTruthSize, p->nCutSize, p->nEntrySize, 1000.0 * p->nEntrySize / (1<<20) );
+        printf( "Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d.\n", 
+            4 * p->nTruthWords, p->nCutBytes, p->nObjBytes, p->nSetBytes );
     // room for temporary truth tables
-    p->puTemp[0] = p->pPars->fTruth? ALLOC( unsigned, 4 * p->nTruthSize ) : NULL;
-    p->puTemp[1] = p->puTemp[0] + p->nTruthSize;
-    p->puTemp[2] = p->puTemp[1] + p->nTruthSize;
-    p->puTemp[3] = p->puTemp[2] + p->nTruthSize;
+    p->puTemp[0] = p->pPars->fTruth? ALLOC( unsigned, 4 * p->nTruthWords ) : NULL;
+    p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
+    p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
+    p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
     // create the constant node
     p->pConst1 = If_ManSetupObj( p );
     p->pConst1->Type = IF_CONST1;
     p->pConst1->fPhase = 1;
-    // create temporary cuts
-    p->ppCuts = If_ManSetupCuts( p );
     return p;
 }
 
@@ -94,8 +95,6 @@ If_Man_t * If_ManStart( If_Par_t * pPars )
 ***********************************************************************/
 void If_ManStop( If_Man_t * p )
 {
-    If_Cut_t * pTemp;
-    int i;
     Vec_PtrFree( p->vCis );
     Vec_PtrFree( p->vCos );
     Vec_PtrFree( p->vObjs );
@@ -103,20 +102,16 @@ void If_ManStop( If_Man_t * p )
     Vec_PtrFree( p->vTemp );
     if ( p->vLatchOrder ) Vec_PtrFree( p->vLatchOrder );
     if ( p->vLags ) Vec_IntFree( p->vLags );
-    Mem_FixedStop( p->pMem, 0 );
+    Mem_FixedStop( p->pMemObj, 0 );
+//    Mem_FixedStop( p->pMemSet, 0 );
+    FREE( p->pMemCi );
+    FREE( p->pMemAnd );
+    FREE( p->puTemp[0] );
     // free pars memory
     if ( p->pPars->pTimesArr )
         FREE( p->pPars->pTimesArr );
     if ( p->pPars->pTimesReq )
         FREE( p->pPars->pTimesReq );
-    // free temporary cut memory
-    pTemp = p->ppCuts[0];
-    for ( i = 1; i < 1 + p->pPars->nCutsMax * p->pPars->nCutsMax; i++ )
-        if ( pTemp > p->ppCuts[i] )
-            pTemp = p->ppCuts[i];
-    FREE( p->puTemp[0] );
-    free( pTemp );
-    free( p->ppCuts );
     free( p );
 }
 
@@ -159,7 +154,7 @@ If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver, int fCompl0 )
     pObj->Type = IF_CO;
     pObj->fCompl0 = fCompl0;
     Vec_PtrPush( p->vCos, pObj );
-    pObj->pFanin0 = pDriver; pDriver->nRefs++;
+    pObj->pFanin0 = pDriver; pDriver->nRefs++; 
     p->nObjs[IF_CO]++;
     return pObj;
 }
@@ -183,8 +178,8 @@ If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_
     pObj->Type    = IF_AND;
     pObj->fCompl0 = fCompl0;
     pObj->fCompl1 = fCompl1;
-    pObj->pFanin0 = pFan0; pFan0->nRefs++;
-    pObj->pFanin1 = pFan1; pFan1->nRefs++;
+    pObj->pFanin0 = pFan0; pFan0->nRefs++; pFan0->nVisits++; pFan0->nVisitsCopy++;
+    pObj->pFanin1 = pFan1; pFan1->nRefs++; pFan1->nVisits++; pFan1->nVisitsCopy++;
     pObj->fPhase  = (fCompl0 ^ pFan0->fPhase) & (fCompl1 ^ pFan1->fPhase);
     pObj->Level   = 1 + IF_MAX( pFan0->Level, pFan1->Level );
     if ( p->nLevelMax < (int)pObj->Level )
@@ -211,8 +206,11 @@ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj )
     assert( pObj->fRepr == 0 );
     pObj->fRepr = 1;
     // update the level of this node (needed for correct required time computation)
-    for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv )
+    for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+    {
         pObj->Level = IF_MAX( pObj->Level, pTemp->Level );
+        pTemp->nVisits++; pTemp->nVisitsCopy++;
+    }
     // mark the largest level
     if ( p->nLevelMax < (int)pObj->Level )
         p->nLevelMax = (int)pObj->Level;
@@ -220,7 +218,7 @@ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj )
 
 /**Function*************************************************************
 
-  Synopsis    [Prepares memory for the node with cuts.]
+  Synopsis    [Prepares memory for one cut.]
 
   Description []
                
@@ -229,49 +227,102 @@ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj )
   SeeAlso     []
 
 ***********************************************************************/
-If_Obj_t * If_ManSetupObj( If_Man_t * p )
+void If_ManSetupCut( If_Man_t * p, If_Cut_t * pCut )
 {
-    If_Cut_t * pCut;
-    If_Obj_t * pObj;
-    int i, * pArrays, nTruthWords;
-    // get memory for the object
-    pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMem );
-    memset( pObj, 0, p->nEntryBase );
-    // organize memory
-    pArrays = (int *)((char *)pObj + p->nEntryBase);
-    for ( i = 0; i < p->pPars->nCutsMax; i++ )
+    memset( pCut, 0, sizeof(If_Cut_t) );
+    pCut->nLimit  = p->pPars->nLutSize;
+    pCut->pLeaves = (int *)(pCut + 1);
+    if ( p->pPars->fUsePerm )
+        pCut->pPerm  = (char *)(pCut->pLeaves + p->pPars->nLutSize);
+    if ( p->pPars->fTruth )
+        pCut->pTruth = pCut->pLeaves + p->pPars->nLutSize + p->nPermWords;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares memory for one cutset.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSetupSet( If_Man_t * p, If_Set_t * pSet )
+{
+    char * pArray;
+    int i;
+    pSet->nCuts = 0;
+    pSet->nCutsMax = p->pPars->nCutsMax;
+    pSet->ppCuts = (If_Cut_t **)(pSet + 1);
+    pArray = (char *)pSet->ppCuts + sizeof(If_Cut_t *) * (pSet->nCutsMax+1);
+    for ( i = 0; i <= pSet->nCutsMax; i++ )
     {
-        pCut = pObj->Cuts + i;
-        pCut->nLimit  = p->pPars->nLutSize;
-        pCut->pLeaves = pArrays + i * p->pPars->nLutSize;
-        pCut->pPerm   = (char *)(p->pPars->fUsePerm? pArrays + p->pPars->nCutsMax * p->pPars->nLutSize + i * p->nPermSize : NULL);
-        pCut->pTruth  = p->pPars->fTruth? pArrays + p->pPars->nCutsMax * (p->pPars->nLutSize + p->nPermSize) + i * p->nTruthSize : NULL;
+        pSet->ppCuts[i] = (If_Cut_t *)(pArray + i * p->nCutBytes); 
+        If_ManSetupCut( p, pSet->ppCuts[i] );
     }
-    // assign ID and save 
-    pObj->Id = Vec_PtrSize(p->vObjs);
-    Vec_PtrPush( p->vObjs, pObj );
-    // assign elementary cut
-    pCut = pObj->Cuts;
+//    pArray += (pSet->nCutsMax + 1) * p->nCutBytes;
+//    assert( ((char *)pArray) - ((char *)pSet) == p->nSetBytes );
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares memory for one cut.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId )
+{
+    pCut->fCompl     = 0;
+    pCut->nLimit     = p->pPars->nLutSize;
     pCut->nLeaves    = 1;
-    pCut->pLeaves[0] = p->pPars->fLiftLeaves? (pObj->Id << 8) : pObj->Id;
+    pCut->pLeaves[0] = p->pPars->fLiftLeaves? (ObjId << 8) : ObjId;
     pCut->uSign      = If_ObjCutSign( pCut->pLeaves[0] );
-    // set the number of cuts
-    pObj->nCuts = 1;
-    // set the required times
-    pObj->Required = IF_FLOAT_LARGE;
     // set up elementary truth table of the unit cut
     if ( p->pPars->fTruth )
     {
+        int i, nTruthWords;
         nTruthWords = Extra_TruthWordNum( pCut->nLimit );
         for ( i = 0; i < nTruthWords; i++ )
             If_CutTruth(pCut)[i] = 0xAAAAAAAA;
     }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Prepares memory for the node with cuts.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Obj_t * If_ManSetupObj( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    // get memory for the object
+    pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMemObj );
+    memset( pObj, 0, sizeof(If_Obj_t) );
+    If_ManSetupCut( p, &pObj->CutBest );
+    // assign ID and save 
+    pObj->Id = Vec_PtrSize(p->vObjs);
+    Vec_PtrPush( p->vObjs, pObj );
+    // set the required times
+    pObj->Required = IF_FLOAT_LARGE;
     return pObj;
 }
 
 /**Function*************************************************************
 
-  Synopsis    [Prepares memory for additional cuts of the manager.]
+  Synopsis    [Prepares memory for one cut.]
 
   Description []
                
@@ -280,31 +331,162 @@ If_Obj_t * If_ManSetupObj( If_Man_t * p )
   SeeAlso     []
 
 ***********************************************************************/
-If_Cut_t ** If_ManSetupCuts( If_Man_t * p )
+void If_ManSetupCiCutSets( If_Man_t * p )
 {
-    If_Cut_t ** pCutStore;
-    int * pArrays, nCutsTotal, i;
-    // decide how many cuts to alloc
-    nCutsTotal = 1 + p->pPars->nCutsMax * p->pPars->nCutsMax;
-    // allocate and clean space for cuts
-    pCutStore = (If_Cut_t **)ALLOC( If_Cut_t *, (nCutsTotal + 1) );
-    memset( pCutStore, 0, sizeof(If_Cut_t *) * (nCutsTotal + 1) );
-    pCutStore[0] = (If_Cut_t *)ALLOC( char, p->nCutSize * nCutsTotal );
-    memset( pCutStore[0], 0, p->nCutSize * nCutsTotal );
-    // assign cut paramters and space for the cut leaves
-    assert( sizeof(int) == sizeof(unsigned) );
-    pArrays = (int *)((char *)pCutStore[0] + sizeof(If_Cut_t) * nCutsTotal);
-    for ( i = 0; i < nCutsTotal; i++ )
+    If_Obj_t * pObj;
+    int i;
+    assert( p->pMemCi == NULL );
+    // create elementary cuts for the CIs
+    If_ManForEachCi( p, pObj, i )
+        If_ManSetupCutTriv( p, &pObj->CutBest, pObj->Id );
+    // create elementary cutsets for the CIs
+    p->pMemCi = (If_Set_t *)malloc( If_ManCiNum(p) * (sizeof(If_Set_t) + sizeof(void *)) );
+    If_ManForEachCi( p, pObj, i )
     {
-        pCutStore[i] = (If_Cut_t *)((char *)pCutStore[0] + sizeof(If_Cut_t) * i);
-        pCutStore[i]->nLimit  = p->pPars->nLutSize;
-        pCutStore[i]->pLeaves = pArrays + i * p->pPars->nLutSize;
-        pCutStore[i]->pPerm   = (char *)(p->pPars->fUsePerm? pArrays + nCutsTotal * p->pPars->nLutSize + i * p->nPermSize : NULL);
-        pCutStore[i]->pTruth  = p->pPars->fTruth? pArrays + nCutsTotal * (p->pPars->nLutSize + p->nPermSize) + i * p->nTruthSize : NULL;
+        pObj->pCutSet = (If_Set_t *)((char *)p->pMemCi + i * (sizeof(If_Set_t) + sizeof(void *)));
+        pObj->pCutSet->nCuts = 1;
+        pObj->pCutSet->nCutsMax = p->pPars->nCutsMax;
+        pObj->pCutSet->ppCuts = (If_Cut_t **)(pObj->pCutSet + 1);
+        pObj->pCutSet->ppCuts[0] = &pObj->CutBest;
     }
-    return pCutStore;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Prepares cutset of the node.]
+
+  Description [Elementary cutset will be added last.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+    assert( If_ObjIsAnd(pObj) );
+    assert( pObj->pCutSet == NULL );
+//    pObj->pCutSet = (If_Set_t *)Mem_FixedEntryFetch( p->pMemSet );
+//    If_ManSetupSet( p, pObj->pCutSet );
+
+    pObj->pCutSet = If_ManCutSetFetch( p );
+    pObj->pCutSet->nCuts = 0;
+    pObj->pCutSet->nCutsMax = p->pPars->nCutsMax;
+
+    return pObj->pCutSet;
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences cutset of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+    If_Obj_t * pFanin;
+    assert( If_ObjIsAnd(pObj) );
+    // consider the node
+    assert( pObj->nVisits >= 0 );
+    if ( pObj->nVisits == 0 )
+    {
+//        Mem_FixedEntryRecycle( p->pMemSet, (char *)pObj->pCutSet );
+        If_ManCutSetRecycle( p, pObj->pCutSet );
+        pObj->pCutSet = NULL;
+    }
+    // consider the first fanin
+    pFanin = If_ObjFanin0(pObj);
+    assert( pFanin->nVisits > 0 );
+    if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+    {
+//        Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet );
+        If_ManCutSetRecycle( p, pFanin->pCutSet );
+        pFanin->pCutSet = NULL;
+    }
+    // consider the second fanin
+    pFanin = If_ObjFanin1(pObj);
+    assert( pFanin->nVisits > 0 );
+    if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+    {
+//        Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet );
+        If_ManCutSetRecycle( p, pFanin->pCutSet );
+        pFanin->pCutSet = NULL;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences cutset of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj )
+{
+    If_Obj_t * pTemp;
+    assert( If_ObjIsAnd(pObj) );
+    assert( pObj->fRepr );
+    assert( pObj->nVisits > 0 );
+    // consider the nodes in the choice class
+    for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+    {
+        assert( pTemp == pObj || pTemp->nVisits == 1 );
+        if ( --pTemp->nVisits == 0 )
+        {
+//            Mem_FixedEntryRecycle( p->pMemSet, (char *)pTemp->pCutSet );
+            If_ManCutSetRecycle( p, pTemp->pCutSet );
+            pTemp->pCutSet = NULL;
+        }
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Dereferences cutset of the node.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManSetupSetAll( If_Man_t * p )
+{
+    If_Set_t * pCutSet;
+    int i, nCrossCut, nCutSets;
+    nCrossCut = If_ManCrossCut( p );
+    nCutSets = 128 + nCrossCut;
+    p->pFreeList = p->pMemAnd = pCutSet = (If_Set_t *)malloc( nCutSets * p->nSetBytes );
+    for ( i = 0; i < nCutSets; i++ )
+    {
+        If_ManSetupSet( p, pCutSet );
+        if ( i == nCutSets - 1 )
+            pCutSet->pNext = NULL;
+        else
+            pCutSet->pNext = (If_Set_t *)( (char *)pCutSet + p->nSetBytes );
+        pCutSet = pCutSet->pNext;
+    }
+    assert( pCutSet == NULL );
+
+    if ( p->pPars->fVerbose )
+    {
+        printf( "Total memory = %7.2f Mb. Peak cut memory = %7.2f Mb.  \n", 
+            1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), 
+            1.0 * p->nSetBytes * nCrossCut / (1<<20) );
+    }
+//    printf( "Cross cut = %d.\n", nCrossCut );
+
+}
 
 ////////////////////////////////////////////////////////////////////////
 ///                       END OF FILE                                ///
diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c
index 2d04d780..90d7b4e8 100644
--- a/src/map/if/ifMap.c
+++ b/src/map/if/ifMap.c
@@ -24,16 +24,6 @@
 ///                        DECLARATIONS                              ///
 ////////////////////////////////////////////////////////////////////////
 
-/*
-  Ideas to try:
-  - reverse order of area recovery
-  - ordering of the outputs by size
-  - merging Delay, Delay2, and Area
-  - expand/reduce area recovery
-  - use average nrefs for tie-breaking
-
-*/
-
 ////////////////////////////////////////////////////////////////////////
 ///                     FUNCTION DEFINITIONS                         ///
 ////////////////////////////////////////////////////////////////////////
@@ -69,13 +59,14 @@ static inline int If_WordCountOnes( unsigned uWord )
   SeeAlso     []
 
 ***********************************************************************/
-void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
+void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess )
 {
+    If_Set_t * pCutSet;
     If_Cut_t * pCut0, * pCut1, * pCut;
-    int i, k, iCut;
+    int i, k;
 
-    assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->nCuts > 1 );
-    assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->nCuts > 1 );
+    assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 1 );
+    assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 1 );
 
     // prepare
     if ( !p->pPars->fSeqMap )
@@ -88,40 +79,41 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
     if ( Mode && pObj->nRefs > 0 )
         If_CutDeref( p, If_ObjCutBest(pObj), IF_INFINITY );
 
-    // save the best cut as one of the candidate cuts
-    p->nCuts = 0;
-    p->nCutsMerged++;
-    if ( Mode )
+    // prepare the cutset
+    pCutSet = If_ManSetupNodeCutSet( p, pObj );
+
+    // get the current assigned best cut
+    pCut = If_ObjCutBest(pObj);
+    if ( pCut->nLeaves > 0 )
     {
         // recompute the parameters of the best cut
-        pCut = If_ObjCutBest(pObj);
         pCut->Delay = If_CutDelay( p, pCut );
         assert( pCut->Delay <= pObj->Required + p->fEpsilon );
-        pCut->Area  = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut );
+        pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut );
         // save the best cut from the previous iteration
-        If_CutCopy( p->ppCuts[p->nCuts++], pCut );
-        p->nCutsMerged++;
+        if ( !fPreprocess )
+            If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut );
     }
 
-    // prepare room for the next cut
-    iCut = p->nCuts;
-    pCut = p->ppCuts[iCut];
     // generate cuts
     If_ObjForEachCut( pObj->pFanin0, pCut0, i )
     If_ObjForEachCut( pObj->pFanin1, pCut1, k )
     {
+        // get the next free cut
+        assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+        pCut = pCutSet->ppCuts[pCutSet->nCuts];
         // make sure K-feasible cut exists
         if ( If_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->pPars->nLutSize )
             continue;
         // merge the nodes
         if ( !If_CutMerge( pCut0, pCut1, pCut ) )
             continue;
+        assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+        p->nCutsMerged++;
         // check if this cut is contained in any of the available cuts
-        pCut->uSign = pCut0->uSign | pCut1->uSign;
 //        if ( p->pPars->pFuncCost == NULL && If_CutFilter( p, pCut ) ) // do not filter functionality cuts
-        if ( If_CutFilter( p, pCut ) )
+        if ( If_CutFilter( pCutSet, pCut ) )
             continue;
-        // the cuts have been successfully merged
         // compute the truth table
         pCut->fCompl = 0;
         if ( p->pPars->fTruth )
@@ -129,6 +121,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
         // compute the application-specific cost and depth
         pCut->fUser = (p->pPars->pFuncCost != NULL);
         pCut->Cost = p->pPars->pFuncCost? p->pPars->pFuncCost(pCut) : 0;
+        if ( pCut->Cost == IF_COST_MAX )
+            continue;
         // check if the cut satisfies the required times
         pCut->Delay = If_CutDelay( p, pCut );
 //        printf( "%.2f ", pCut->Delay );
@@ -137,30 +131,26 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
         // compute area of the cut (this area may depend on the application specific cost)
         pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut );
         pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
-        // make sure the cut is the last one (after filtering it may not be so)
-        assert( pCut == p->ppCuts[iCut] );
-        p->ppCuts[iCut] = p->ppCuts[p->nCuts];
-        p->ppCuts[p->nCuts] = pCut;
-        // count the cut
-        p->nCuts++;
-        p->nCutsMerged++;
-        // prepare room for the next cut
-        iCut = p->nCuts;
-        pCut = p->ppCuts[iCut];
+        // insert the cut into storage
+        If_CutSort( p, pCutSet, pCut );
     } 
-    assert( p->nCuts > 0 );
-    // sort if we have more cuts
-    If_ManSortCuts( p, Mode );
-    // decide how many cuts to use
-    pObj->nCuts = IF_MIN( p->nCuts + 1, p->nCutsUsed );
-//printf( "%d(%d) ", p->nCuts, pObj->nCuts );
-    // take the first
-    If_ObjForEachCutStart( pObj, pCut, i, 1 )
-        If_CutCopy( pCut, p->ppCuts[i-1] );
+    assert( pCutSet->nCuts > 0 );
+
+    // add the trivial cut to the set
+    If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id );
+    assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 );
+
+    // update the best cut
+    if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
+        If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
     assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 );
+
     // ref the selected cut
     if ( Mode && pObj->nRefs > 0 )
         If_CutRef( p, If_ObjCutBest(pObj), IF_INFINITY );
+
+    // free the cuts
+    If_ManDerefNodeCutSet( p, pObj );
 }
 
 /**Function*************************************************************
@@ -174,70 +164,73 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode )
   SeeAlso     []
 
 ***********************************************************************/
-void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode )
+void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess )
 {
+    If_Set_t * pCutSet;
     If_Obj_t * pTemp;
     If_Cut_t * pCutTemp, * pCut;
-    int i, iCut;
+    int i;
     assert( pObj->pEquiv != NULL );
+
     // prepare
     if ( Mode && pObj->nRefs > 0 )
         If_CutDeref( p, If_ObjCutBest(pObj), IF_INFINITY );
-    // prepare room for the next cut
-    p->nCuts = 0;
-    iCut = p->nCuts;
-    pCut = p->ppCuts[iCut];
-    // generate cuts
+
+    // remove elementary cuts
     for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv )
+        pTemp->pCutSet->nCuts--;
+
+    // update the cutset of the node
+    pCutSet = pObj->pCutSet;
+
+    // generate cuts
+    for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv )
     {
-        If_ObjForEachCutStart( pTemp, pCutTemp, i, 1 )
+        assert( pTemp->nRefs == 0 );
+        assert( p->pPars->fSeqMap || pTemp->pCutSet->nCuts > 0 );
+        // go through the cuts of this node
+        If_ObjForEachCut( pTemp, pCutTemp, i )
         {
-            assert( pTemp->nCuts > 1 );
-            assert( pTemp == pObj || pTemp->nRefs == 0 );
+            assert( p->pPars->fSeqMap || pCutTemp->nLeaves > 1 );
+            // get the next free cut
+            assert( pCutSet->nCuts <= pCutSet->nCutsMax );
+            pCut = pCutSet->ppCuts[pCutSet->nCuts];
             // copy the cut into storage
-            If_CutCopy( pCut, pCutTemp );
+            If_CutCopy( p, pCut, pCutTemp );
             // check if this cut is contained in any of the available cuts
-            if ( If_CutFilter( p, pCut ) )
+            if ( If_CutFilter( pCutSet, pCut ) )
                 continue;
-            // the cuts have been successfully merged
             // check if the cut satisfies the required times
             assert( pCut->Delay == If_CutDelay( p, pCut ) );
             if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon )
                 continue;
             // set the phase attribute
-            pCut->fCompl ^= (pObj->fPhase ^ pTemp->fPhase);
+            assert( pCut->fCompl == 0 );
+            pCut->fCompl ^= (pObj->fPhase ^ pTemp->fPhase); // why ^= ?
             // compute area of the cut (this area may depend on the application specific cost)
             pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut );
             pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
-            // make sure the cut is the last one (after filtering it may not be so)
-            assert( pCut == p->ppCuts[iCut] );
-            p->ppCuts[iCut] = p->ppCuts[p->nCuts];
-            p->ppCuts[p->nCuts] = pCut;
-            // count the cut
-            p->nCuts++;
-            // prepare room for the next cut
-            iCut = p->nCuts;
-            pCut = p->ppCuts[iCut];
-            // quit if we exceeded the number of cuts
-            if ( p->nCuts >= p->pPars->nCutsMax * p->pPars->nCutsMax )
-                break;
+            // insert the cut into storage
+            If_CutSort( p, pCutSet, pCut );
         }
-        // quit if we exceeded the number of cuts
-        if ( p->nCuts >= p->pPars->nCutsMax * p->pPars->nCutsMax )
-            break;
     }
-    assert( p->nCuts > 0 );
-    // sort if we have more cuts
-    If_ManSortCuts( p, Mode );
-    // decide how many cuts to use
-    pObj->nCuts = IF_MIN( p->nCuts + 1, p->nCutsUsed );
-    // take the first
-    If_ObjForEachCutStart( pObj, pCut, i, 1 )
-        If_CutCopy( pCut, p->ppCuts[i-1] );
+    assert( pCutSet->nCuts > 0 );
+
+    // add the trivial cut to the set
+    If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id );
+    assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 );
+
+    // update the best cut
+    if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon )
+        If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] );
     assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 );
+
     // ref the selected cut
     if ( Mode && pObj->nRefs > 0 )
         If_CutRef( p, If_ObjCutBest(pObj), IF_INFINITY );
+
+    // free the cuts
+    If_ManDerefChoiceCutSet( p, pObj );
 }
 
 /**Function*************************************************************
@@ -251,12 +244,19 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode )
   SeeAlso     []
 
 ***********************************************************************/
-int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fRequired, char * pLabel )
+int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel )
 {
 //    ProgressBar * pProgress;
     If_Obj_t * pObj;
     int i, clk = clock();
     assert( Mode >= 0 && Mode <= 2 );
+    // set the sorting function
+    if ( Mode || p->pPars->fArea ) // area
+        p->SortMode = 1;
+    else if ( p->pPars->fFancy )
+        p->SortMode = 2;
+    else
+        p->SortMode = 0;
     // set the cut number
     p->nCutsUsed   = nCutsUsed;
     p->nCutsMerged = 0;
@@ -265,24 +265,24 @@ int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fRequi
     If_ManForEachNode( p, pObj, i )
     {
 //        Extra_ProgressBarUpdate( pProgress, i, pLabel );
-        If_ObjPerformMappingAnd( p, pObj, Mode );
+        If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess );
         if ( pObj->fRepr )
-            If_ObjPerformMappingChoice( p, pObj, Mode );
+            If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess );
     }
 //    Extra_ProgressBarStop( pProgress );
+    // make sure the visit counters are all zero
+    If_ManForEachNode( p, pObj, i )
+        assert( pObj->nVisits == 0 );
     // compute required times and stats
-    if ( fRequired )
+    If_ManComputeRequired( p );
+    if ( p->pPars->fVerbose )
     {
-        If_ManComputeRequired( p, Mode==0 );
-        if ( p->pPars->fVerbose )
-        {
-            char Symb = (Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A');
-            printf( "%c:  Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", 
-                Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
-            PRT( "T", clock() - clk );
+        char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A'));
+        printf( "%c:  Del = %6.2f. Ar = %8.2f. Net = %6d. Cut = %8d. ", 
+            Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged );
+        PRT( "T", clock() - clk );
 //    printf( "Max number of cuts = %d. Average number of cuts = %5.2f.\n", 
 //        p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
-        }
     }
     return 1;
 }
diff --git a/src/map/if/ifPrepro.c b/src/map/if/ifPrepro.c
deleted file mode 100644
index 32146e91..00000000
--- a/src/map/if/ifPrepro.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/**CFile****************************************************************
-
-  FileName    [ifPrepro.c]
-
-  SystemName  [ABC: Logic synthesis and verification system.]
-
-  PackageName [FPGA mapping based on priority cuts.]
-
-  Synopsis    [Selects the starting mapping.]
-
-  Author      [Alan Mishchenko]
-  
-  Affiliation [UC Berkeley]
-
-  Date        [Ver. 1.0. Started - November 21, 2006.]
-
-  Revision    [$Id: ifPrepro.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "if.h"
-
-////////////////////////////////////////////////////////////////////////
-///                        DECLARATIONS                              ///
-////////////////////////////////////////////////////////////////////////
-
-static void If_ManPerformMappingMoveBestCut( If_Man_t * p, int iPosNew, int iPosOld );
-static void If_ManPerformMappingAdjust( If_Man_t * p, int nCuts );
-
-////////////////////////////////////////////////////////////////////////
-///                     FUNCTION DEFINITIONS                         ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
-  Synopsis    [Merges the results of delay, relaxed delay and area-based mapping.]
-
-  Description [Delay target may be different from minimum delay!!!]
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-void If_ManPerformMappingPreprocess( If_Man_t * p )
-{
-    float delayArea, delayDelay, delayPure;
-    int clk = clock();
-    assert( p->pPars->nCutsMax >= 4 );
-
-    // perform min-area mapping and move the cut to the end
-    p->pPars->fArea = 1;
-    If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, "Start delay" );
-    p->pPars->fArea = 0;
-    delayArea = If_ManDelayMax( p, 0 );
-    if ( p->pPars->DelayTarget != -1 && delayArea < p->pPars->DelayTarget - p->fEpsilon )
-        delayArea = p->pPars->DelayTarget;
-    If_ManPerformMappingMoveBestCut( p, p->pPars->nCutsMax - 1, 1 );
-
-    // perfrom min-delay mapping and move the cut to the end
-    p->pPars->fFancy = 1;
-    If_ManPerformMappingRound( p, p->pPars->nCutsMax - 1, 0, 0, "Start delay-2" );
-    p->pPars->fFancy = 0;
-    delayDelay = If_ManDelayMax( p, 0 );
-    if ( p->pPars->DelayTarget != -1 && delayDelay < p->pPars->DelayTarget - p->fEpsilon )
-        delayDelay = p->pPars->DelayTarget;
-    If_ManPerformMappingMoveBestCut( p, p->pPars->nCutsMax - 2, 1 );
-
-    // perform min-delay mapping
-    If_ManPerformMappingRound( p, p->pPars->nCutsMax - 2, 0, 0, "Start flow" );
-    delayPure = If_ManDelayMax( p, 0 );
-    if ( p->pPars->DelayTarget != -1 && delayPure < p->pPars->DelayTarget - p->fEpsilon )
-        delayPure = p->pPars->DelayTarget;
-
-    // decide what to do
-    if ( delayPure < delayDelay - p->fEpsilon && delayPure < delayArea - p->fEpsilon )
-    {
-        // copy the remaining two cuts
-        if ( p->pPars->nCutsMax > 4 )
-        {
-            If_ManPerformMappingMoveBestCut( p, 2, p->pPars->nCutsMax - 2 );
-            If_ManPerformMappingMoveBestCut( p, 3, p->pPars->nCutsMax - 1 );
-        }
-        If_ManComputeRequired( p, 1 );
-        If_ManPerformMappingAdjust( p, 4 );
-    }
-    else if ( delayDelay < delayArea - p->fEpsilon )
-    {
-        If_ManPerformMappingMoveBestCut( p, 1, p->pPars->nCutsMax - 2 );
-        If_ManPerformMappingMoveBestCut( p, 2, p->pPars->nCutsMax - 1 );
-        If_ManComputeRequired( p, 1 );
-        If_ManPerformMappingAdjust( p, 3 );
-    }
-    else
-    {
-        If_ManPerformMappingMoveBestCut( p, 1, p->pPars->nCutsMax - 1 );
-        If_ManComputeRequired( p, 1 );
-        If_ManPerformMappingAdjust( p, 2 );
-    }
-    If_ManComputeRequired( p, 1 );
-    if ( p->pPars->fVerbose )
-    {
-        printf( "S:  Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", 
-            p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
-        PRT( "T", clock() - clk );
-    }
-}
-
-/**Function*************************************************************
-
-  Synopsis    [Moves the best cut to the given position.]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-void If_ManPerformMappingMoveBestCut( If_Man_t * p, int iPosNew, int iPosOld )
-{
-    If_Obj_t * pObj;
-    int i;
-    assert( iPosOld != iPosNew );
-    assert( iPosOld > 0 && iPosOld < p->pPars->nCutsMax );
-    assert( iPosNew > 0 && iPosNew < p->pPars->nCutsMax );
-    If_ManForEachNode( p, pObj, i )
-        If_CutCopy( pObj->Cuts + iPosNew, pObj->Cuts + iPosOld );
-}
-
-/**Function*************************************************************
-
-  Synopsis    [Adjusts mapping for the given cuts.]
-
-  Description []
-               
-  SideEffects []
-
-  SeeAlso     []
-
-***********************************************************************/
-void If_ManPerformMappingAdjust( If_Man_t * p, int nCuts )
-{
-    If_Cut_t * pCut, * pCutBest;
-    If_Obj_t * pObj;
-    int i, c;
-    assert( nCuts >= 2 && nCuts <= 4 );
-    If_ManForEachNode( p, pObj, i )
-    {
-        pCutBest = NULL;
-        for ( c = 1; c < nCuts; c++ )
-        {
-            pCut = pObj->Cuts + c;
-            pCut->Delay = If_CutDelay( p, pCut );
-            pCut->Area  = If_CutFlow( p, pCut );
-            assert( pCutBest || pCut->Delay < pObj->Required + p->fEpsilon );
-            if ( pCutBest == NULL || 
-                (pCut->Delay < pObj->Required + p->fEpsilon && 
-                 pCut->Area < pCutBest->Area - p->fEpsilon) )
-                pCutBest = pCut;
-        }
-        assert( pCutBest != NULL );
-        // check if we need to move
-        if ( pCutBest != pObj->Cuts + 1 )
-            If_CutCopy( pObj->Cuts + 1, pCutBest );
-        // set the number of cuts
-        pObj->nCuts = 2;
-    }
-}
-
-////////////////////////////////////////////////////////////////////////
-///                       END OF FILE                                ///
-////////////////////////////////////////////////////////////////////////
-
-
diff --git a/src/map/if/ifReduce.c b/src/map/if/ifReduce.c
index 26989b8c..1b23b883 100644
--- a/src/map/if/ifReduce.c
+++ b/src/map/if/ifReduce.c
@@ -52,11 +52,11 @@ void If_ManImproveMapping( If_Man_t * p )
 
     clk = clock();
     If_ManImproveExpand( p, p->pPars->nLutSize );
-    If_ManComputeRequired( p, 0 );
+    If_ManComputeRequired( p );
     if ( p->pPars->fVerbose )
     {
-        printf( "E:  Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", 
-            p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
+        printf( "E:  Del = %6.2f. Ar = %8.2f. Net = %6d. Cut = %8d. ", 
+            p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged );
         PRT( "T", clock() - clk );
     }
 
@@ -488,6 +488,7 @@ void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, V
 ***********************************************************************/
 void If_ManImproveNodeReduce( If_Man_t * p, If_Obj_t * pObj, int nLimit )
 {
+/*
     If_Cut_t * pCut, * pCut0, * pCut1, * pCutR;
     If_Obj_t * pFanin0, * pFanin1;
     float AreaBef, AreaAft;
@@ -537,13 +538,14 @@ void If_ManImproveNodeReduce( If_Man_t * p, If_Obj_t * pObj, int nLimit )
         AreaAft = If_CutAreaDerefed( p, pCutR, IF_INFINITY );
         // update the best cut
         if ( AreaAft < AreaBef - p->fEpsilon && pCutR->Delay < pObj->Required + p->fEpsilon )
-            If_CutCopy( pCut, pCutR );
+            If_CutCopy( p, pCut, pCutR );
     }
     // recompute the delay of the best cut
     pCut->Delay = If_CutDelay( p, pCut );
     // ref the cut if the node is refed
     if ( pObj->nRefs > 0 )
         If_CutRef( p, pCut, IF_INFINITY );
+*/
 }
 
 /**Function*************************************************************
@@ -562,13 +564,7 @@ void If_ManImproveReduce( If_Man_t * p, int nLimit )
     If_Obj_t * pObj;
     int i;
     If_ManForEachNode( p, pObj, i )
-    {
-        if ( 278 == i )
-        {
-            int s = 0;
-        }
         If_ManImproveNodeReduce( p, pObj, nLimit );
-    }
 }
 
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/map/if/ifSeq.c b/src/map/if/ifSeq.c
index cd90a313..e6528233 100644
--- a/src/map/if/ifSeq.c
+++ b/src/map/if/ifSeq.c
@@ -24,19 +24,13 @@
 ///                        DECLARATIONS                              ///
 ////////////////////////////////////////////////////////////////////////
 
-static int  If_ManBinarySearchPeriod( If_Man_t * p, int Mode );
-static int  If_ManBinarySearch_rec( If_Man_t * p, int Mode, int FiMin, int FiMax );
-static int  If_ManPerformMappingRoundSeq( If_Man_t * p, int Mode, int nIter, char * pLabel );
-static int  If_ManPrepareMappingSeq( If_Man_t * p );
-static int  If_ObjPerformMappingLatch( If_Man_t * p, If_Obj_t * pObj );
-
 ////////////////////////////////////////////////////////////////////////
 ///                     FUNCTION DEFINITIONS                         ///
 ////////////////////////////////////////////////////////////////////////
 
 /**Function*************************************************************
 
-  Synopsis    [Performs sequential mapping.]
+  Synopsis    [Prepares for sequential mapping by linking the latches.]
 
   Description []
                
@@ -45,102 +39,46 @@ static int  If_ObjPerformMappingLatch( If_Man_t * p, If_Obj_t * pObj );
   SeeAlso     []
 
 ***********************************************************************/
-int If_ManPerformMappingSeq( If_Man_t * p )
+void If_ManPrepareMappingSeq( If_Man_t * p )
 {
-    int PeriodBest, Mode = 0;
-
-    // collect nodes in the sequential order
-    If_ManPrepareMappingSeq( p );
-
-    // perform combinational mapping to get the upper bound on the clock period
-    If_ManPerformMappingRound( p, 2, 0, 0, NULL );
-    p->RequiredGlo = If_ManDelayMax( p, 0 );
-
-    // set parameters
-    p->nCutsUsed = p->pPars->nCutsMax;
-    p->nAttempts = 0;
-    p->nMaxIters = 50;
-    p->Period    = (int)p->RequiredGlo;
-
-    // make sure the clock period words
-    if ( !If_ManBinarySearchPeriod( p, Mode ) )
-    {
-        printf( "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" );
-        return 0;
-    }
-
-    // perform binary search
-    PeriodBest = If_ManBinarySearch_rec( p, Mode, 0, p->Period );
+    If_Obj_t * pObjLi, * pObjLo;
+    int i;
 
-    // recompute the best l-values
-    if ( p->Period != PeriodBest )
-    {
-        p->Period = PeriodBest;
-        if ( !If_ManBinarySearchPeriod( p, Mode ) )
-        {
-            printf( "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" );
-            return 0;
-        }
-    }
-/*
-    // fix the problem with non-converged delays
-    If_ManForEachNode( p, pObj, i )
-        if ( pObj->LValue < -ABC_INFINITY/2 )
-            pObj->LValue = (float)0.0;
-    // write the retiming lags
-    p->vLags = Vec_IntStart( If_ManObjNum(p) + 1 );
-    If_ManForEachNode( p, pObj, i )
-        Vec_IntWriteEntry( vLags, i, Abc_NodeComputeLag(pObj->LValue, p->Period) );
-*/
-/*
-    // print the statistic into a file
-    {
-        FILE * pTable;
-        pTable = fopen( "iscas/seqmap__stats.txt", "a+" );
-        fprintf( pTable, "%d ", p->Period );
-        fprintf( pTable, "\n" );
-        fclose( pTable );
-    }
-*/
-    // print the result
-    if ( p->pPars->fLiftLeaves )
+    // link the latch outputs (CIs) directly to the drivers of latch inputs (COs)
+    for ( i = 0; i < p->pPars->nLatches; i++ )
     {
-//        if ( p->pPars->fVerbose )   
-            printf( "The best clock period is %3d. (Currently, network is not modified, so mapping will fail.)\n", p->Period );
-        return 0;
+        pObjLi = If_ManLi( p, i );
+        pObjLo = If_ManLo( p, i );
+        pObjLo->pFanin0 = If_ObjFanin0( pObjLi );
+        pObjLo->fCompl0 = If_ObjFaninC0( pObjLi );
     }
-//    if ( p->pPars->fVerbose )   
-        printf( "The best clock period is %3d.\n", p->Period );
-    return 1;
 }
 
 /**Function*************************************************************
 
-  Synopsis    [Performs binary search for the optimal clock period.]
+  Synopsis    [Collects latches in the topological order.]
 
-  Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+  Description []
                
   SideEffects []
 
   SeeAlso     []
-
+ 
 ***********************************************************************/
-int If_ManBinarySearch_rec( If_Man_t * p, int Mode, int FiMin, int FiMax )
+void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches )
 {
-    assert( FiMin < FiMax );
-    if ( FiMin + 1 == FiMax )
-        return FiMax;
-    // compute the median
-    p->Period = FiMin + (FiMax - FiMin)/2;
-    if ( If_ManBinarySearchPeriod( p, Mode ) )
-        return If_ManBinarySearch_rec( p, Mode, FiMin, p->Period ); // Median is feasible
-    else 
-        return If_ManBinarySearch_rec( p, Mode, p->Period, FiMax ); // Median is infeasible
+    if ( !If_ObjIsLatch(pObj) )
+        return;
+    if ( pObj->fMark )
+        return;
+    pObj->fMark = 1;
+    If_ManCollectLatches_rec( pObj->pFanin0, vLatches );
+    Vec_PtrPush( vLatches, pObj );
 }
 
 /**Function*************************************************************
 
-  Synopsis    [Returns 1 if retiming with this clock period is feasible.]
+  Synopsis    [Collects latches in the topological order.]
 
   Description []
                
@@ -149,66 +87,20 @@ int If_ManBinarySearch_rec( If_Man_t * p, int Mode, int FiMin, int FiMax )
   SeeAlso     []
 
 ***********************************************************************/
-int If_ManBinarySearchPeriod( If_Man_t * p, int Mode )
+Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
 {
+    Vec_Ptr_t * vLatches;
     If_Obj_t * pObj;
-    int i, c, fConverged;
-    int fResetRefs = 0;
-
-    p->nAttempts++;
-
-    // set l-values of all nodes to be minus infinity, except PIs and constants
-    If_ManForEachObj( p, pObj, i )
-    {
-        pObj->nCuts = 1;
-        If_ObjSetLValue( pObj, -IF_FLOAT_LARGE );
-        if ( fResetRefs )
-            pObj->nRefs = 0;
-    }
-    If_ObjSetLValue( If_ManConst1(p), (float)0.0 );
-    If_ManForEachPi( p, pObj, i )
-        If_ObjSetLValue( pObj, (float)0.0 );
-
-    // reset references to their original state
-    if ( fResetRefs )
-    {
-        If_ManForEachObj( p, pObj, i )
-        {
-            if ( If_ObjIsCo(pObj) )
-                continue;
-            if ( pObj->pFanin0 ) pObj->pFanin0->nRefs++;
-            if ( pObj->pFanin1 ) pObj->pFanin1->nRefs++;
-        }
-    }
-
-    // update all values iteratively
-    fConverged = 0;
-    for ( c = 1; c <= p->nMaxIters; c++ )
-    {
-        if ( !If_ManPerformMappingRoundSeq( p, Mode, c, NULL ) )
-        {
-            fConverged = 1;
-            break;
-        }
-        p->RequiredGlo = If_ManDelayMax( p, 1 );
-        if ( p->RequiredGlo > p->Period + p->fEpsilon )
-            break; 
-    }
-
-    // report the results
-    if ( p->pPars->fVerbose )
-    {
-        p->AreaGlo = p->pPars->fLiftLeaves? 0/*If_ManScanMappingSeq(p)*/ : If_ManScanMapping(p);
-        printf( "Attempt = %2d.  Iters = %3d.  Area = %10.2f.  Fi = %6.2f.  ", p->nAttempts, c, p->AreaGlo, (float)p->Period );
-        if ( fConverged )
-            printf( "  Feasible" );
-        else if ( c > p->nMaxIters )
-            printf( "Infeasible (timeout)" );
-        else
-            printf( "Infeasible" );
-        printf( "\n" );
-    }
-    return fConverged;
+    int i;
+    // collect latches 
+    vLatches = Vec_PtrAlloc( p->pPars->nLatches );
+    If_ManForEachLatchOutput( p, pObj, i )
+        If_ManCollectLatches_rec( pObj, vLatches );
+    // clean marks
+    Vec_PtrForEachEntry( vLatches, pObj, i )
+        pObj->fMark = 0;
+    assert( Vec_PtrSize(vLatches) == p->pPars->nLatches );
+    return vLatches;
 }
 
 /**Function*************************************************************
@@ -223,49 +115,53 @@ int If_ManBinarySearchPeriod( If_Man_t * p, int Mode )
   SeeAlso     []
 
 ***********************************************************************/
-int If_ManPerformMappingRoundSeq( If_Man_t * p, int Mode, int nIter, char * pLabel )
+int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter )
 {
-    ProgressBar * pProgress;
     If_Obj_t * pObj;
     int i, clk = clock();
     int fVeryVerbose = 0;
     int fChange = 0;
-    assert( Mode >= 0 && Mode <= 2 );
-    if ( !p->pPars->fVerbose )
-        pProgress = Extra_ProgressBarStart( stdout, If_ManObjNum(p) );
+
     // map the internal nodes
     p->nCutsMerged = 0;
     If_ManForEachNode( p, pObj, i )
     {
-        if ( !p->pPars->fVerbose )
-            Extra_ProgressBarUpdate( pProgress, i, pLabel );
-        // consider the camse of an AND gate
-        assert( If_ObjIsAnd(pObj) );
-        If_ObjPerformMappingAnd( p, pObj, Mode );
+        If_ObjPerformMappingAnd( p, pObj, 0, 0 );
         if ( pObj->fRepr )
-            If_ObjPerformMappingChoice( p, pObj, Mode );
-        // check if updating happens
+            If_ObjPerformMappingChoice( p, pObj, 0, 0 );
+    }
+
+    // postprocess the mapping
+//printf( "Itereation %d: \n", nIter );
+    If_ManForEachNode( p, pObj, i )
+    {
+        // update the LValues stored separately
         if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon )
         {
             If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay );
             fChange = 1;
         }
-//if ( If_ObjLValue(pObj) > -1000.0 )
-//printf( "Node %d %.2f  ", pObj->Id, If_ObjLValue(pObj) );
+//printf( "%d ", (int)If_ObjLValue(pObj) );
+        // reset the visit counters
+        assert( pObj->nVisits == 0 );
+        pObj->nVisits = pObj->nVisitsCopy;
     }
-    if ( !p->pPars->fVerbose )
-        Extra_ProgressBarStop( pProgress );
-    // propagate arrival times from the registers
+//printf( "\n" );
+
+    // propagate LValues over the registers
     Vec_PtrForEachEntry( p->vLatchOrder, pObj, i )
-        fChange |= If_ObjPerformMappingLatch( p, pObj );
-//printf( "\n\n" );
+    {
+        If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period );
+        If_ObjSetArrTime( pObj, If_ObjLValue(pObj) );
+    }
+
     // compute area and delay
     if ( fVeryVerbose )
     {
         p->RequiredGlo = If_ManDelayMax( p, 1 );
-        p->AreaGlo = p->pPars->fLiftLeaves? If_ManScanMappingSeq(p) : If_ManScanMapping(p);
-        printf( "S%d:  Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", 
-             nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
+        p->AreaGlo = If_ManScanMapping(p);
+        printf( "S%d:  Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ", 
+             nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged );
         PRT( "T", clock() - clk );
     }
     return fChange;
@@ -273,56 +169,96 @@ int If_ManPerformMappingRoundSeq( If_Man_t * p, int Mode, int nIter, char * pLab
 
 /**Function*************************************************************
 
-  Synopsis    [Collects latches in the topological order.]
+  Synopsis    [Returns 1 if retiming with this clock period is feasible.]
 
   Description []
                
   SideEffects []
 
   SeeAlso     []
- 
+
 ***********************************************************************/
-void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches )
+int If_ManBinarySearchPeriod( If_Man_t * p )
 {
-    if ( !If_ObjIsLatch(pObj) )
-        return;
-    if ( pObj->fMark )
-        return;
-    pObj->fMark = 1;
-    If_ManCollectLatches_rec( pObj->pFanin0, vLatches );
-    Vec_PtrPush( vLatches, pObj );
+    If_Obj_t * pObj;
+    int i, c, fConverged;
+    int fResetRefs = 0;
+
+    p->nAttempts++;
+
+    // set LValues of of PIs to be 0 and other nodes to be -infinity
+    // LValues of the PIs are already set to 0
+    // undo any previous mapping, except for CIs
+    If_ManForEachObj( p, pObj, i )
+    {
+        if ( If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) )
+            If_ObjSetLValue( pObj, (float)0.0 );
+        else
+            If_ObjSetLValue( pObj, (float)-IF_INFINITY );
+        if ( If_ObjIsAnd(pObj) )
+            If_ObjCutBest(pObj)->nLeaves = 0;
+    }
+
+    // update all values iteratively
+    fConverged = 0;
+    for ( c = 1; c <= p->nMaxIters; c++ )
+    {
+        if ( !If_ManPerformMappingRoundSeq( p, c ) )
+        {
+            p->RequiredGlo = If_ManDelayMax( p, 1 );
+            fConverged = 1;
+            break;
+        }
+        p->RequiredGlo = If_ManDelayMax( p, 1 );
+//printf( "Global = %d \n", (int)p->RequiredGlo );
+        if ( p->RequiredGlo > p->Period + p->fEpsilon )
+            break; 
+    }
+
+    // report the results
+    if ( p->pPars->fVerbose )
+    {
+        p->AreaGlo = If_ManScanMapping(p);
+        printf( "Attempt = %2d.  Iters = %3d.  Area = %10.2f.  Fi = %6.2f.  ", p->nAttempts, c, p->AreaGlo, (float)p->Period );
+        if ( fConverged )
+            printf( "  Feasible" );
+        else if ( c > p->nMaxIters )
+            printf( "Infeasible (timeout)" );
+        else
+            printf( "Infeasible" );
+        printf( "\n" );
+    }
+    return fConverged;
 }
 
+
 /**Function*************************************************************
 
-  Synopsis    [Collects latches in the topological order.]
+  Synopsis    [Performs binary search for the optimal clock period.]
 
-  Description []
+  Description [Assumes that FiMin is infeasible while FiMax is feasible.]
                
   SideEffects []
 
   SeeAlso     []
 
 ***********************************************************************/
-Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
+int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax )
 {
-    Vec_Ptr_t * vLatches;
-    If_Obj_t * pObj;
-    int i;
-    // collect latches 
-    vLatches = Vec_PtrAlloc( p->pPars->nLatches );
-    Vec_PtrForEachEntryStart( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches )
-        If_ManCollectLatches_rec( pObj, vLatches );
-    // clean marks
-    Vec_PtrForEachEntry( vLatches, pObj, i )
-        pObj->fMark = 0;
-    assert( Vec_PtrSize(vLatches) == p->pPars->nLatches );
-    return vLatches;
+    assert( FiMin < FiMax );
+    if ( FiMin + 1 == FiMax )
+        return FiMax;
+    // compute the median
+    p->Period = FiMin + (FiMax - FiMin)/2;
+    if ( If_ManBinarySearchPeriod( p ) )
+        return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible
+    else 
+        return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible
 }
 
 /**Function*************************************************************
 
-  Synopsis    [Prepares for sequential mapping by linking the latches.]
+  Synopsis    [Performs sequential mapping.]
 
   Description []
                
@@ -331,45 +267,53 @@ Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p )
   SeeAlso     []
 
 ***********************************************************************/
-int If_ManPrepareMappingSeq( If_Man_t * p )
+void If_ManPerformMappingSeqPost( If_Man_t * p )
 {
-    If_Obj_t * pObj, * pObjLi, * pObjLo, * pTemp;
-    If_Cut_t * pCut;
+    If_Obj_t * pObjLi, * pObjLo, * pObj;
     int i;
-    // link the latch outputs (PIs) directly to the drivers of latch inputs (POs)
+
+    // link the latch outputs (CIs) directly to the drivers of latch inputs (COs)
     for ( i = 0; i < p->pPars->nLatches; i++ )
     {
-        pObjLo = If_ManCi( p, If_ManCiNum(p) - p->pPars->nLatches + i );
-        pObjLi = If_ManCo( p, If_ManCoNum(p) - p->pPars->nLatches + i );
-        pObjLo->pFanin0 = If_ObjFanin0( pObjLi );
-        pObjLo->fCompl0 = If_ObjFaninC0( pObjLi );
-//        pObjLo->pFanin0 = pObjLi;
+        pObjLi = If_ManLi( p, i );
+        pObjLo = If_ManLo( p, i );
+//        printf( "%3d : %2d -> %2d   \n", i, 
+//            (int)If_ObjLValue(If_ObjFanin0(pObjLo)), (int)If_ObjLValue(pObjLo) );
     }
-    // collect latches
-    p->vLatchOrder = If_ManCollectLatches( p );
-    // propagate elementary cuts 
-    if ( p->pPars->fLiftLeaves )
+
+    // set arrival times
+    assert( p->pPars->pTimesArr != NULL );
+    If_ManForEachLatchOutput( p, pObjLo, i )
+        p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo);
+
+    // set the required times
+    assert( p->pPars->pTimesReq == NULL );
+    p->pPars->pTimesReq = ALLOC( float, If_ManCoNum(p) );
+    If_ManForEachPo( p, pObj, i )
     {
-        Vec_PtrForEachEntry( p->vLatchOrder, pObj, i )
-        {
-            pCut = If_ObjCutTriv(pObj);
-            If_CutCopy( pCut, If_ObjFanin0(pObj)->Cuts );
-            If_CutLift( pCut );
-            pCut->Delay  -= p->Period;
-            pCut->fCompl ^= pObj->fCompl0;
-
-            // there is a bug here, which shows when there are choices...
-//            pTemp = If_ManObj(p, pCut->pLeaves[0] >> 8);
-            pTemp = If_ManObj(p, pCut->pLeaves[0]);
-            assert( !If_ObjIsLatch(pTemp) );
-        }
+        p->pPars->pTimesReq[i] = p->RequiredGlo2;
+//        printf( "Out %3d : %2d   \n", i, (int)p->pPars->pTimesReq[i] );
     }
-    return 1;
+    If_ManForEachLatchInput( p, pObjLi, i )
+    {
+        p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi));
+//        printf( "Out %3d : %2d   \n", i, (int)p->pPars->pTimesReq[i] );
+    }
+
+    // undo previous mapping
+    If_ManForEachObj( p, pObj, i )
+        if ( If_ObjIsAnd(pObj) )
+            If_ObjCutBest(pObj)->nLeaves = 0;
+
+    // map again combinationally
+    p->pPars->fSeqMap = 0;
+    If_ManPerformMappingComb( p );
+    p->pPars->fSeqMap = 1;
 }
 
 /**Function*************************************************************
 
-  Synopsis    [Performs mapping of the latches.]
+  Synopsis    [Performs sequential mapping.]
 
   Description []
                
@@ -378,34 +322,60 @@ int If_ManPrepareMappingSeq( If_Man_t * p )
   SeeAlso     []
 
 ***********************************************************************/
-int If_ObjPerformMappingLatch( If_Man_t * p, If_Obj_t * pObj )
+int If_ManPerformMappingSeq( If_Man_t * p )
 {
-    If_Obj_t * pFanin;
-    If_Cut_t * pCut;
-    float LValueOld;
-    int i;
-    assert( If_ObjIsLatch(pObj) );
-    // save old l-value
-    LValueOld = If_ObjLValue(pObj);
-    pFanin = If_ObjFanin0(pObj);
-    assert( pFanin->nCuts > 0 );
-    if ( !p->pPars->fLiftLeaves )
+    int clkTotal = clock();
+    int PeriodBest;
+
+    p->SortMode = 0;
+
+    // perform combinational mapping to get the upper bound on the clock period
+    If_ManPerformMappingRound( p, 1, 0, 0, NULL );
+    p->RequiredGlo = If_ManDelayMax( p, 0 );
+    p->RequiredGlo2 = p->RequiredGlo;
+
+    // set direct linking of latches with their inputs
+    If_ManPrepareMappingSeq( p );
+
+    // collect latches
+    p->vLatchOrder = If_ManCollectLatches( p );
+
+    // set parameters
+    p->nCutsUsed = p->pPars->nCutsMax;
+    p->nAttempts = 0;
+    p->nMaxIters = 50;
+    p->Period    = (int)p->RequiredGlo;
+
+    // make sure the clock period works
+    if ( !If_ManBinarySearchPeriod( p ) )
     {
-        pObj->nCuts = 1;
-        If_ObjSetLValue( pObj, If_ObjLValue(pFanin) - p->Period );
+        printf( "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" );
+        return 0;
     }
-    else
+
+    // perform binary search
+    PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period );
+
+    // recompute the best l-values
+    if ( p->Period != PeriodBest )
     {
-        pObj->nCuts = pFanin->nCuts;
-        If_ObjForEachCut( pObj, pCut, i )
+        p->Period = PeriodBest;
+        if ( !If_ManBinarySearchPeriod( p ) )
         {
-            If_CutCopy( pCut, pFanin->Cuts + i );
-            If_CutLift( pCut );
-            pCut->Delay  -= p->Period;
-            pCut->fCompl ^= pObj->fCompl0;
+            printf( "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" );
+            return 0;
         }
     }
-    return LValueOld != If_ObjLValue(pObj);
+    if ( p->pPars->fVerbose )
+    {
+        printf( "The best clock period is %3d.  ", p->Period );
+        PRT( "Sequential time", clock() - clkTotal );
+    }
+    p->RequiredGlo = (float)PeriodBest;
+
+    // postprocess it using combinational mapping
+    If_ManPerformMappingSeqPost( p );
+    return 1;
 }
 
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/map/if/ifUtil.c b/src/map/if/ifUtil.c
index 1fd3229d..4fdb4d31 100644
--- a/src/map/if/ifUtil.c
+++ b/src/map/if/ifUtil.c
@@ -61,11 +61,9 @@ void If_ManCleanNodeCopy( If_Man_t * p )
 void If_ManCleanCutData( If_Man_t * p )
 {
     If_Obj_t * pObj;
-    If_Cut_t * pCut;
-    int i, k;
+    int i;
     If_ManForEachObj( p, pObj, i )
-        If_ObjForEachCut( pObj, pCut, k )
-            If_CutSetData( pCut, NULL );
+        If_CutSetData( If_ObjCutBest(pObj), NULL );
 }
 
 /**Function*************************************************************
@@ -113,20 +111,20 @@ float If_ManDelayMax( If_Man_t * p, int fSeq )
     {
         assert( p->pPars->nLatches > 0 );
         If_ManForEachPo( p, pObj, i )
-            if ( DelayBest < If_ObjCutBest( If_ObjFanin0(pObj) )->Delay )
-                 DelayBest = If_ObjCutBest( If_ObjFanin0(pObj) )->Delay;
+            if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+                 DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
     }
     else if ( p->pPars->fLatchPaths )
     {
-        If_ManForEachLatch( p, pObj, i )
-            if ( DelayBest < If_ObjCutBest( If_ObjFanin0(pObj) )->Delay )
-                 DelayBest = If_ObjCutBest( If_ObjFanin0(pObj) )->Delay;
+        If_ManForEachLatchInput( p, pObj, i )
+            if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+                 DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
     }
     else 
     {
         If_ManForEachCo( p, pObj, i )
-            if ( DelayBest < If_ObjCutBest( If_ObjFanin0(pObj) )->Delay )
-                 DelayBest = If_ObjCutBest( If_ObjFanin0(pObj) )->Delay;
+            if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) )
+                 DelayBest = If_ObjArrTime(If_ObjFanin0(pObj));
     }
     return DelayBest;
 }
@@ -142,40 +140,67 @@ float If_ManDelayMax( If_Man_t * p, int fSeq )
   SeeAlso     []
 
 ***********************************************************************/
-void If_ManComputeRequired( If_Man_t * p, int fFirstTime )
+void If_ManComputeRequired( If_Man_t * p )
 {
     If_Obj_t * pObj;
     int i;
+
     // compute area, clean required times, collect nodes used in the mapping
     p->nNets = 0;
     p->AreaGlo = If_ManScanMapping( p );
-    // get the global required times
-    p->RequiredGlo = If_ManDelayMax( p, 0 );
-    // update the required times according to the target
-    if ( p->pPars->DelayTarget != -1 )
+
+    // consider the case when the required times are given
+    if ( p->pPars->pTimesReq )
     {
-        if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon )
-        {
-            if ( fFirstTime )
-                printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget );
-        }
-        else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon )
+        assert( !p->pPars->fAreaOnly );
+        // make sure that the required time hold
+        If_ManForEachCo( p, pObj, i )
         {
-            if ( fFirstTime )
-                printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget );
-            p->RequiredGlo = p->pPars->DelayTarget;
+            if ( If_ObjArrTime(If_ObjFanin0(pObj)) > p->pPars->pTimesReq[i] + p->fEpsilon )
+                printf( "Required times are violated for output %d (arr = %d; req = %d).\n", 
+                    i, (int)If_ObjArrTime(If_ObjFanin0(pObj)), (int)p->pPars->pTimesReq[i] );
+            If_ObjFanin0(pObj)->Required = p->pPars->pTimesReq[i];
         }
     }
-    // set the required times for the POs
-    if ( p->pPars->fLatchPaths )
-    {
-        If_ManForEachLatch( p, pObj, i )
-            If_ObjFanin0(pObj)->Required = p->RequiredGlo;
-    }
     else
     {
-        If_ManForEachCo( p, pObj, i )
-            If_ObjFanin0(pObj)->Required = p->RequiredGlo;
+        // get the global required times
+        p->RequiredGlo = If_ManDelayMax( p, 0 );
+        // update the required times according to the target
+        if ( p->pPars->DelayTarget != -1 )
+        {
+            if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon )
+            {
+                if ( p->fNextRound == 0 )
+                {
+                    p->fNextRound = 1;
+                    printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget );
+                }
+            }
+            else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon )
+            {
+                if ( p->fNextRound == 0 )
+                {
+                    p->fNextRound = 1;
+                    printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget );
+                }
+                p->RequiredGlo = p->pPars->DelayTarget;
+            }
+        }
+        // do not propagate required times if area minimization is requested
+        if ( p->pPars->fAreaOnly ) 
+            return;
+        // set the required times for the POs
+        if ( p->pPars->fLatchPaths )
+        {
+            If_ManForEachLatchInput( p, pObj, i )
+                If_ObjFanin0(pObj)->Required = p->RequiredGlo;
+        }
+        else 
+        {
+            If_ManForEachCo( p, pObj, i )
+                If_ObjFanin0(pObj)->Required = p->RequiredGlo;
+        }
     }
     // go through the nodes in the reverse topological order
     Vec_PtrForEachEntry( p->vMapped, pObj, i )
@@ -236,7 +261,8 @@ float If_ManScanMapping( If_Man_t * p )
     If_ManForEachObj( p, pObj, i )
     {
         pObj->Required = IF_FLOAT_LARGE;
-        pObj->nRefs = 0;
+        pObj->nVisits  = pObj->nVisitsCopy;
+        pObj->nRefs    = 0;
     }
     // allocate place to store the nodes
     ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 );
@@ -318,6 +344,83 @@ float If_ManScanMappingSeq( If_Man_t * p )
     return aArea;
 }
 
+/**Function*************************************************************
+
+  Synopsis    [Computes area, references, and nodes used in the mapping.]
+
+  Description [Collects the nodes in reverse topological order in array 
+  p->vMapping.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+void If_ManResetOriginalRefs( If_Man_t * p )
+{
+    If_Obj_t * pObj;
+    int i;
+    If_ManForEachObj( p, pObj, i )
+        pObj->nRefs = 0;
+    If_ManForEachObj( p, pObj, i )
+    {
+        if ( If_ObjIsAnd(pObj) )
+        {
+            pObj->pFanin0->nRefs++;
+            pObj->pFanin1->nRefs++;
+        }
+        else if ( If_ObjIsCo(pObj) )
+            pObj->pFanin0->nRefs++;
+    }
+}
+
+/**Function*************************************************************
+
+  Synopsis    [Computes cross-cut of the circuit.]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int If_ManCrossCut( If_Man_t * p )
+{
+    If_Obj_t * pObj, * pFanin;
+    int i, nCutSize = 0, nCutSizeMax = 0;
+    If_ManForEachObj( p, pObj, i )
+    {
+        if ( !If_ObjIsAnd(pObj) )
+            continue;
+        // consider the node
+        if ( nCutSizeMax < ++nCutSize )
+            nCutSizeMax = nCutSize;
+        if ( pObj->nVisits == 0 )
+            nCutSize--;
+        // consider the fanins
+        pFanin = If_ObjFanin0(pObj);
+        if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+            nCutSize--;
+        pFanin = If_ObjFanin1(pObj);
+        if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+            nCutSize--;
+        // consider the choice class
+        if ( pObj->fRepr )
+            for ( pFanin = pObj; pFanin; pFanin = pFanin->pEquiv )
+                if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 )
+                    nCutSize--;
+    }
+    If_ManForEachObj( p, pObj, i )
+    {
+        assert( If_ObjIsCi(pObj) || pObj->fVisit == 0 );
+        pObj->nVisits = pObj->nVisitsCopy;
+    }
+    assert( nCutSize == 0 );
+//    printf( "Max cross cut size = %6d.\n", nCutSizeMax );
+    return nCutSizeMax;
+}
+
 ////////////////////////////////////////////////////////////////////////
 ///                       END OF FILE                                ///
 ////////////////////////////////////////////////////////////////////////
diff --git a/src/map/if/module.make b/src/map/if/module.make
index c4fa56cb..f3d189be 100644
--- a/src/map/if/module.make
+++ b/src/map/if/module.make
@@ -2,7 +2,6 @@ SRC +=  src/map/if/ifCore.c \
     src/map/if/ifCut.c \
     src/map/if/ifMan.c \
     src/map/if/ifMap.c \
-    src/map/if/ifPrepro.c \
     src/map/if/ifReduce.c \
     src/map/if/ifSeq.c \
     src/map/if/ifTime.c \
diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c
index 847acc27..13c2cdcd 100644
--- a/src/map/mio/mioRead.c
+++ b/src/map/mio/mioRead.c
@@ -49,7 +49,7 @@ extern int          isspace( int c );  // to silence the warning in VS
   SeeAlso     []
 
 ***********************************************************************/
-Mio_Library_t * Mio_LibraryRead( Abc_Frame_t * pAbc, char * FileName, char * ExcludeFile, int fVerbose )
+Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose )
 {
     Mio_Library_t * pLib;
     int num;
@@ -486,7 +486,7 @@ void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
   SeeAlso     []
 
 ***********************************************************************/
-int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * tExcludeGate )
+int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate )
 {
     int nDel = 0;
     FILE *pEx;
diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h
index 6937a8d4..1fff12d5 100644
--- a/src/misc/extra/extra.h
+++ b/src/misc/extra/extra.h
@@ -349,6 +349,7 @@ extern char *      Extra_MmFixedEntryFetch( Extra_MmFixed_t * p );
 extern void        Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry );
 extern void        Extra_MmFixedRestart( Extra_MmFixed_t * p );
 extern int         Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p );
+extern int         Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p );
 // flexible-size-block memory manager
 extern Extra_MmFlex_t * Extra_MmFlexStart();
 extern void        Extra_MmFlexStop( Extra_MmFlex_t * p );
diff --git a/src/misc/extra/extraUtilMemory.c b/src/misc/extra/extraUtilMemory.c
index fff80ecf..6eccf015 100644
--- a/src/misc/extra/extraUtilMemory.c
+++ b/src/misc/extra/extraUtilMemory.c
@@ -310,6 +310,21 @@ int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p )
     return p->nMemoryAlloc;
 }
 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p )
+{
+    return p->nEntriesMax;
+}
 
 
 /**Function*************************************************************
@@ -326,7 +341,7 @@ int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p )
 Extra_MmFlex_t * Extra_MmFlexStart()
 {
     Extra_MmFlex_t * p;
-
+//printf( "allocing flex\n" );
     p = ALLOC( Extra_MmFlex_t, 1 );
     memset( p, 0, sizeof(Extra_MmFlex_t) );
 
@@ -379,6 +394,7 @@ void Extra_MmFlexStop( Extra_MmFlex_t * p )
     int i;
     if ( p == NULL )
         return;
+//printf( "deleting flex\n" );
     for ( i = 0; i < p->nChunks; i++ )
         free( p->pChunks[i] );
     free( p->pChunks );
diff --git a/src/misc/vec/vecStr.h b/src/misc/vec/vecStr.h
index a03eb51e..38ac171d 100644
--- a/src/misc/vec/vecStr.h
+++ b/src/misc/vec/vecStr.h
@@ -401,6 +401,59 @@ static inline void Vec_StrPush( Vec_Str_t * p, char Entry )
     p->pArray[p->nSize++] = Entry;
 }
 
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num )
+{
+    int i, nDigits;
+    if ( Num < 0 )
+    {
+        Vec_StrPush( p, '-' );
+        Num = -Num;
+    }
+    if ( Num < 10 )
+    {
+        Vec_StrPush( p, (char)('0' + Num) );
+        return;
+    }
+    nDigits = Extra_Base10Log( Num );
+    Vec_StrGrow( p, p->nSize + nDigits );
+    for ( i = nDigits - 1; i >= 0; i-- )
+    {
+        Vec_StrWriteEntry( p, p->nSize + i, (char)('0' + Num % 10) );
+        Num /= 10;
+    }
+    assert( Num == 0 );
+    p->nSize += nDigits;
+}
+
+/**Function*************************************************************
+
+  Synopsis    []
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+***********************************************************************/
+static inline void Vec_StrPrintStr( Vec_Str_t * p, char * pStr )
+{
+    int i, Length = strlen(pStr);
+    for ( i = 0; i < Length; i++ )
+        Vec_StrPush( p, pStr[i] );
+}
+
 /**Function*************************************************************
 
   Synopsis    [Appends the string to the char vector.]
diff --git a/src/phys/place/libhmetis.h b/src/phys/place/libhmetis.h
index 60b9c12e..051079d4 100644
--- a/src/phys/place/libhmetis.h
+++ b/src/phys/place/libhmetis.h
@@ -3,7 +3,7 @@
 #ifndef LIBHMETIS_H_
 #define LIBHMETIS_H_
 
-void HMETIS_PartRecursive(int nvtxs, 
+static void HMETIS_PartRecursive(int nvtxs, 
               int nhedges, 
               int *vwgts, 
               int *eptr,
@@ -13,10 +13,10 @@ void HMETIS_PartRecursive(int nvtxs,
               int nbfactor, 
               int *options, 
               int *part, 
-              int *edgecnt );
+              int *edgecnt ) {} //;
 
 
-void HMETIS_PartKway(int nvtxs, 
+static void HMETIS_PartKway(int nvtxs, 
              int nhedges, 
              int *vwgts, 
              int *eptr, 
@@ -26,6 +26,6 @@ void HMETIS_PartKway(int nvtxs,
              int nbfactor, 
              int *options, 
              int *part, 
-             int *edgecnt );
+             int *edgecnt ) {} //;
 
 #endif
-- 
cgit v1.2.3