summaryrefslogtreecommitdiffstats
path: root/src/base
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2010-11-28 22:30:15 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2010-11-28 22:30:15 -0800
commita17a4e5ca4d01220912fd3e85f9db2f6dc119254 (patch)
treed2b746fc725b3f51d7470762e92374cb3498860b /src/base
parent98257daa82043256cea4da4fd4bcc65d5ff130ca (diff)
downloadabc-a17a4e5ca4d01220912fd3e85f9db2f6dc119254.tar.gz
abc-a17a4e5ca4d01220912fd3e85f9db2f6dc119254.tar.bz2
abc-a17a4e5ca4d01220912fd3e85f9db2f6dc119254.zip
NPN class computation.
Diffstat (limited to 'src/base')
-rw-r--r--src/base/abci/abcCut.c20
-rw-r--r--src/base/abci/abcNpnSave.c739
-rw-r--r--src/base/abci/module.make1
3 files changed, 752 insertions, 8 deletions
diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c
index e80ddb92..f8b27c32 100644
--- a/src/base/abci/abcCut.c
+++ b/src/base/abci/abcCut.c
@@ -122,7 +122,8 @@ void Abc_NtkCutsAddFanunt( Abc_Ntk_t * pNtk )
Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
{
ProgressBar * pProgress;
- Cut_Man_t * p;
+ Cut_Man_t * p;
+ Cut_Cut_t * pList;
Abc_Obj_t * pObj, * pNode;
Vec_Ptr_t * vNodes;
Vec_Int_t * vChoices;
@@ -172,7 +173,15 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
// continue;
Extra_ProgressBarUpdate( pProgress, i, NULL );
// compute the cuts to the internal node
- Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree );
+ pList = Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree );
+ if ( pParams->fNpnSave && pList )
+ {
+ extern void Npn_ManSaveOne( unsigned * puTruth, int nVars );
+ Cut_Cut_t * pCut;
+ for ( pCut = pList; pCut; pCut = pCut->pNext )
+ if ( pCut->nLeaves >= 4 )
+ Npn_ManSaveOne( Cut_CutReadTruth(pCut), pCut->nLeaves );
+ }
// consider dropping the fanins cuts
if ( pParams->fDrop )
{
@@ -193,7 +202,7 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
Vec_IntFree( vChoices );
Cut_ManPrintStats( p );
ABC_PRT( "TOTAL", clock() - clk );
- printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) );
+// printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) );
//Abc_NtkPrintCuts( p, pNtk, 0 );
// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
@@ -428,7 +437,6 @@ void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
// assert( Abc_NtkIsStrash(pObj->pNtk) );
assert( Abc_ObjFaninNum(pObj) == 2 );
-
// check if the node is a DAG node
fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj));
// increment the counter of DAG nodes
@@ -444,7 +452,6 @@ void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1);
}
-
// changes due to the global/local cut computation
{
Cut_Params_t * pParams = Cut_ManReadParams((Cut_Man_t *)p);
@@ -568,9 +575,6 @@ void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq )
Cut_CutPrintList( pList, fSeq );
}
-
-
-
/**Function*************************************************************
Synopsis [Assigns global attributes randomly.]
diff --git a/src/base/abci/abcNpnSave.c b/src/base/abci/abcNpnSave.c
new file mode 100644
index 00000000..381409de
--- /dev/null
+++ b/src/base/abci/abcNpnSave.c
@@ -0,0 +1,739 @@
+/**CFile****************************************************************
+
+ FileName [abcNpnSave.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface with the FPGA mapping package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 21, 2006.]
+
+ Revision [$Id: abcNpnSave.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Npn_Obj_t_ Npn_Obj_t;
+typedef struct Npn_Man_t_ Npn_Man_t;
+
+struct Npn_Obj_t_
+{
+ word uTruth; // truth table
+ int Count; // occurances
+ int iNext; // next entry
+};
+struct Npn_Man_t_
+{
+ Npn_Obj_t * pBuffer; // all NPN entries
+ int * pBins; // hash table
+ int nBins; // hash table size
+ int nBufferSize; // buffer size
+ int nEntries; // entry count
+};
+
+static inline Npn_Obj_t * Npn_ManObj( Npn_Man_t * p, int i ) { assert( i < p->nBufferSize ); return i ? p->pBuffer + i : NULL; }
+static inline int Npn_ManObjNum( Npn_Man_t * p, Npn_Obj_t * pObj ) { assert( p->pBuffer < pObj ); return pObj - p->pBuffer; }
+
+static word Truth[8] = {
+ 0xAAAAAAAAAAAAAAAA,
+ 0xCCCCCCCCCCCCCCCC,
+ 0xF0F0F0F0F0F0F0F0,
+ 0xFF00FF00FF00FF00,
+ 0xFFFF0000FFFF0000,
+ 0xFFFFFFFF00000000,
+ 0x0000000000000000,
+ 0xFFFFFFFFFFFFFFFF
+};
+
+static Npn_Man_t * pNpnMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_TruthPermute_rec( char * pStr, int mid, int end )
+{
+ static int count = 0;
+ char * pTemp = Aig_UtilStrsav(pStr);
+ char e;
+ int i;
+ if ( mid == end )
+ {
+ printf( "%03d: %s\n", count++, pTemp );
+ return ;
+ }
+ for ( i = mid; i <= end; i++ )
+ {
+ e = pTemp[mid];
+ pTemp[mid] = pTemp[i];
+ pTemp[i] = e;
+
+ Npn_TruthPermute_rec( pTemp, mid + 1, end );
+
+ e = pTemp[mid];
+ pTemp[mid] = pTemp[i];
+ pTemp[i] = e;
+ }
+ ABC_FREE( pTemp );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Npn_TruthHasVar( word t, int v )
+{
+ return ((t & Truth[v]) >> (1<<v)) != (t & ~Truth[v]);
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Npn_TruthSupport( word t )
+{
+ int v, Supp = 0;
+ for ( v = 0; v < 6; v++ )
+ if ( Npn_TruthHasVar( t, v ) )
+ Supp |= (1 << v);
+ return Supp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Npn_TruthSuppSize( word t, int nVars )
+{
+ int v, nSupp = 0;
+ assert( nVars <= 6 );
+ for ( v = 0; v < nVars; v++ )
+ if ( Npn_TruthHasVar( t, v ) )
+ nSupp++;
+ return nSupp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Npn_TruthIsMinBase( word t )
+{
+ int Supp = Npn_TruthSupport(t);
+ return (Supp & (Supp+1)) == 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+word Npn_TruthPadWord( word uTruth, int nVars )
+{
+ if ( nVars == 6 )
+ return uTruth;
+ if ( nVars <= 5 )
+ uTruth = ((uTruth & 0x00000000FFFFFFFF) << 32) | (uTruth & 0x00000000FFFFFFFF);
+ if ( nVars <= 4 )
+ uTruth = ((uTruth & 0x0000FFFF0000FFFF) << 16) | (uTruth & 0x0000FFFF0000FFFF);
+ if ( nVars <= 3 )
+ uTruth = ((uTruth & 0x00FF00FF00FF00FF) << 8) | (uTruth & 0x00FF00FF00FF00FF);
+ if ( nVars <= 2 )
+ uTruth = ((uTruth & 0x0F0F0F0F0F0F0F0F) << 4) | (uTruth & 0x0F0F0F0F0F0F0F0F);
+ if ( nVars <= 1 )
+ uTruth = ((uTruth & 0x3333333333333333) << 2) | (uTruth & 0x3333333333333333);
+ if ( nVars == 0 )
+ uTruth = ((uTruth & 0x5555555555555555) << 1) | (uTruth & 0x5555555555555555);
+ return uTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Npn_TruthCountOnes( word t )
+{
+ t = (t & 0x5555555555555555) + ((t>> 1) & 0x5555555555555555);
+ t = (t & 0x3333333333333333) + ((t>> 2) & 0x3333333333333333);
+ t = (t & 0x0F0F0F0F0F0F0F0F) + ((t>> 4) & 0x0F0F0F0F0F0F0F0F);
+ t = (t & 0x00FF00FF00FF00FF) + ((t>> 8) & 0x00FF00FF00FF00FF);
+ t = (t & 0x0000FFFF0000FFFF) + ((t>>16) & 0x0000FFFF0000FFFF);
+ return (t & 0x00000000FFFFFFFF) + (t>>32);
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline word Npn_TruthChangePhase( word t, int v )
+{
+ return ((t & Truth[v]) >> (1<<v)) | ((t & ~Truth[v]) << (1<<v));
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline word Npn_TruthSwapAdjacentVars( word t, int v )
+{
+ static word PMasks[5][3] = {
+ { 0x9999999999999999, 0x2222222222222222, 0x4444444444444444 },
+ { 0xC3C3C3C3C3C3C3C3, 0x0C0C0C0C0C0C0C0C, 0x3030303030303030 },
+ { 0xF00FF00FF00FF00F, 0x00F000F000F000F0, 0x0F000F000F000F00 },
+ { 0xFF0000FFFF0000FF, 0x0000FF000000FF00, 0x00FF000000FF0000 },
+ { 0xFFFF00000000FFFF, 0x00000000FFFF0000, 0x0000FFFF00000000 }
+ };
+ assert( v < 6 );
+ return (t & PMasks[v][0]) | ((t & PMasks[v][1]) << (1 << v)) | ((t & PMasks[v][2]) >> (1 << v));
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline word Npn_TruthCanon( word t, int nVars, int * pPhase )
+{
+ int fUsePolarity = 0;
+ int fUsePermutation = 0;
+ char Temp, pSigs[13], pCanonPerm[6];
+ int v, fChange, CanonPhase = 0;
+ assert( nVars < 7 );
+ pSigs[12] = Npn_TruthCountOnes( t );
+ if ( pSigs[12] > 32 )
+ {
+ t = ~t;
+ pSigs[12] = 64 - pSigs[12];
+ CanonPhase |= (1 << 6);
+ }
+ if ( fUsePolarity || fUsePermutation )
+ {
+ for ( v = 0; v < nVars; v++ )
+ {
+ pCanonPerm[v] = v;
+ pSigs[2*v+1] = Npn_TruthCountOnes( t & Truth[v] );
+ pSigs[2*v] = pSigs[12] - pSigs[2*v+1];
+ }
+ }
+ if ( fUsePolarity )
+ {
+ for ( v = 0; v < nVars; v++ )
+ {
+ if ( pSigs[2*v] >= pSigs[2*v+1] )
+ continue;
+ CanonPhase |= (1 << v);
+ Temp = pSigs[2*v];
+ pSigs[2*v] = pSigs[2*v+1];
+ pSigs[2*v+1] = Temp;
+ t = Npn_TruthChangePhase( t, v );
+ }
+ }
+ if ( fUsePermutation )
+ {
+ do {
+ fChange = 0;
+ for ( v = 0; v < nVars-1; v++ )
+ {
+ if ( fUsePolarity )
+ {
+ if ( pSigs[2*v] >= pSigs[2*(v+1)] )
+ continue;
+ }
+ else
+ {
+ if ( ABC_MIN(pSigs[2*v],pSigs[2*v+1]) >= ABC_MIN(pSigs[2*(v+1)],pSigs[2*(v+1)+1]) )
+ continue;
+ }
+ fChange = 1;
+
+ Temp = pCanonPerm[v];
+ pCanonPerm[v] = pCanonPerm[v+1];
+ pCanonPerm[v+1] = Temp;
+
+ Temp = pSigs[2*v];
+ pSigs[2*v] = pSigs[2*(v+1)];
+ pSigs[2*(v+1)] = Temp;
+
+ Temp = pSigs[2*v+1];
+ pSigs[2*v+1] = pSigs[2*(v+1)+1];
+ pSigs[2*(v+1)+1] = Temp;
+
+ t = Npn_TruthSwapAdjacentVars( t, v );
+ }
+ } while ( fChange );
+ }
+ if ( pPhase )
+ {
+ *pPhase = 0;
+ for ( v = 0; v < nVars; v++ )
+ *pPhase |= (pCanonPerm[v] << (4 * v));
+ *pPhase |= (CanonPhase << 24);
+ }
+ return t;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the hash key.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Npn_ManHash( Npn_Man_t * p, word uTruth )
+{
+ word Key = (uTruth * (word)101) ^ (uTruth * (word)733) ^ (uTruth * (word)1777);
+ return (int)(Key % (word)p->nBins);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_ManResize( Npn_Man_t * p )
+{
+ Npn_Obj_t * pEntry, * pNext;
+ int * pBinsOld, * ppPlace;
+ int nBinsOld, Counter, i, clk;
+ assert( p->pBins != NULL );
+clk = clock();
+ // save the old Bins
+ pBinsOld = p->pBins;
+ nBinsOld = p->nBins;
+ // get the new Bins
+ p->nBins = Aig_PrimeCudd( 3 * nBinsOld );
+ p->pBins = ABC_CALLOC( int, p->nBins );
+ // rehash the entries from the old table
+ Counter = 1;
+ for ( i = 0; i < nBinsOld; i++ )
+ for ( pEntry = Npn_ManObj(p, pBinsOld[i]),
+ pNext = pEntry ? Npn_ManObj(p, pEntry->iNext) : NULL;
+ pEntry;
+ pEntry = pNext,
+ pNext = pEntry ? Npn_ManObj(p, pEntry->iNext) : NULL )
+ {
+ // get the place where this entry goes
+ ppPlace = p->pBins + Npn_ManHash( p, pEntry->uTruth );
+ // add the entry to the list
+ pEntry->iNext = *ppPlace;
+ *ppPlace = Npn_ManObjNum( p, pEntry );
+ Counter++;
+ }
+ assert( Counter == p->nEntries );
+ ABC_FREE( pBinsOld );
+//ABC_PRT( "Hash table resizing time", clock() - clk );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one entry to the table.]
+
+ Description [Increments ref counter by 1.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Npn_Obj_t * Npn_ManAdd( Npn_Man_t * p, word uTruth )
+{
+ Npn_Obj_t * pEntry;
+ int * pPlace, Key = Npn_ManHash( p, uTruth );
+ // resize the link storage if needed
+ if ( p->nEntries == p->nBufferSize )
+ {
+ p->nBufferSize *= 2;
+ p->pBuffer = ABC_REALLOC( Npn_Obj_t, p->pBuffer, p->nBufferSize );
+ }
+ // find the entry
+ for ( pEntry = Npn_ManObj(p, p->pBins[Key]),
+ pPlace = p->pBins + Key;
+ pEntry;
+ pPlace = &pEntry->iNext,
+ pEntry = Npn_ManObj(p, pEntry->iNext) )
+ if ( pEntry->uTruth == uTruth )
+ {
+ pEntry->Count++;
+ return pEntry;
+ }
+ // create new entry
+ *pPlace = p->nEntries;
+ assert( p->nEntries < p->nBufferSize );
+ pEntry = Npn_ManObj( p, p->nEntries++ );
+ pEntry->uTruth = uTruth;
+ pEntry->Count = 1;
+ pEntry->iNext = 0;
+ // resize the table if needed
+ if ( p->nEntries > 3 * p->nBins )
+ Npn_ManResize( p );
+ return pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fills table from file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_ManRead( Npn_Man_t * p, char * pFileName )
+{
+ char pBuffer[1000];
+ char * pToken;
+ Npn_Obj_t * pEntry;
+ unsigned Truth[2];
+ word uTruth;
+ FILE * pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName );
+ return;
+ }
+ // read lines from the file
+ while ( fgets( pBuffer, 1000, pFile ) != NULL )
+ {
+ pToken = strtok( pBuffer, " \t\n" );
+ if ( pToken == NULL )
+ continue;
+ if ( pToken[0] == '#' )
+ continue;
+ if ( strlen(pToken) != 16 )
+ {
+ Abc_Print( 0, "Skipping token %s that does not look like a 16-digit hex number.\n" );
+ continue;
+ }
+ // extract truth table
+ Extra_ReadHexadecimal( Truth, pToken, 6 );
+ uTruth = (((word)Truth[1]) << 32) | (word)Truth[0];
+ // add truth table
+ pEntry = Npn_ManAdd( p, uTruth );
+ assert( pEntry->Count == 1 );
+ // read area
+ pToken = strtok( NULL, " \t\n" );
+ pEntry->Count = atoi(pToken);
+ }
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two entries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static int Npn_ManCompareEntries( Npn_Obj_t ** pp1, Npn_Obj_t ** pp2 )
+{
+ if ( (*pp1)->Count > (*pp2)->Count )
+ return -1;
+ if ( (*pp1)->Count < (*pp2)->Count )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one entry to the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_ManWrite( Npn_Man_t * p, char * pFileName )
+{
+ Vec_Ptr_t * vEntries;
+ Npn_Obj_t * pEntry;
+ FILE * pFile = fopen( pFileName, "w" );
+ int i;
+ if ( pFile == NULL )
+ {
+ Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName );
+ return;
+ }
+ vEntries = Vec_PtrAlloc( p->nEntries );
+ for ( i = 0; i < p->nBins; i++ )
+ for ( pEntry = Npn_ManObj(p, p->pBins[i]); pEntry; pEntry = Npn_ManObj(p, pEntry->iNext) )
+ Vec_PtrPush( vEntries, pEntry );
+ Vec_PtrSort( vEntries, (int (*)())Npn_ManCompareEntries );
+ Vec_PtrForEachEntry( Npn_Obj_t *, vEntries, pEntry, i )
+ {
+ Extra_PrintHexadecimal( pFile, (unsigned *)&pEntry->uTruth, 6 );
+ fprintf( pFile, " %d %d\n", pEntry->Count, Npn_TruthSuppSize(pEntry->uTruth, 6) );
+ }
+ fclose( pFile );
+ Vec_PtrFree( vEntries );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Npn_Man_t * Npn_ManStart( char * pFileName )
+{
+ Npn_Man_t * p;
+ p = ABC_CALLOC( Npn_Man_t, 1 );
+ if ( pFileName == NULL )
+ {
+ p->nBufferSize = 1000000;
+ p->nBufferSize = 100;
+ p->pBuffer = ABC_ALLOC( Npn_Obj_t, p->nBufferSize );
+ p->nBins = Aig_PrimeCudd( p->nBufferSize / 2 );
+ p->pBins = ABC_CALLOC( int, p->nBins );
+ p->nEntries = 1;
+ }
+ else
+ {
+ FILE * pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName );
+ return NULL;
+ }
+ fclose( pFile );
+ p->nBufferSize = 4 * ( Extra_FileSize(pFileName) / 20 );
+ p->pBuffer = ABC_ALLOC( Npn_Obj_t, p->nBufferSize );
+ p->nBins = Aig_PrimeCudd( p->nBufferSize / 2 );
+ p->pBins = ABC_CALLOC( int, p->nBins );
+ p->nEntries = 1;
+ Npn_ManRead( p, pFileName );
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_ManStop( Npn_Man_t * p )
+{
+ ABC_FREE( p->pBuffer );
+ ABC_FREE( p->pBins );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_ManClean()
+{
+ if ( pNpnMan != NULL )
+ {
+ Npn_ManStop( pNpnMan );
+ pNpnMan = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads functions from a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_ManLoad( char * pFileName )
+{
+// Npn_TruthPermute_rec( "012345", 0, 5 );
+ if ( pNpnMan != NULL )
+ {
+ Abc_Print( 1, "Removing old table with %d entries.\n", pNpnMan->nEntries );
+ Npn_ManStop( pNpnMan );
+ }
+ pNpnMan = Npn_ManStart( pFileName );
+ Abc_Print( 1, "Created new table with %d entries from file \"%s\".\n", pNpnMan->nEntries, pFileName );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves functions into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_ManSave( char * pFileName )
+{
+ if ( pNpnMan == NULL )
+ {
+ Abc_Print( 1, "There is no table with entries.\n" );
+ return;
+ }
+ Npn_ManWrite( pNpnMan, pFileName );
+ Abc_Print( 1, "Dumped table with %d entries from file \"%s\".\n", pNpnMan->nEntries, pFileName );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves one function into storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Npn_ManSaveOne( unsigned * puTruth, int nVars )
+{
+ word uTruth = (((word)puTruth[1]) << 32) | (word)puTruth[0];
+ assert( nVars >= 0 && nVars <= 6 );
+ if ( pNpnMan == NULL )
+ {
+ Abc_Print( 1, "Creating new table with 0 entries.\n" );
+ pNpnMan = Npn_ManStart( NULL );
+ }
+ // skip truth tables that do not depend on some vars
+ if ( !Npn_TruthIsMinBase( uTruth ) )
+ return;
+ // extend truth table to look like 6-input
+ uTruth = Npn_TruthPadWord( uTruth, nVars );
+ // semi(!)-NPN-canonize the truth table
+ uTruth = Npn_TruthCanon( uTruth, 6, NULL );
+ // add to storage
+ Npn_ManAdd( pNpnMan, uTruth );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/base/abci/module.make b/src/base/abci/module.make
index b9342881..b0223330 100644
--- a/src/base/abci/module.make
+++ b/src/base/abci/module.make
@@ -34,6 +34,7 @@ SRC += src/base/abci/abc.c \
src/base/abci/abcMiter.c \
src/base/abci/abcMulti.c \
src/base/abci/abcNtbdd.c \
+ src/base/abci/abcNpnSave.c \
src/base/abci/abcOdc.c \
src/base/abci/abcOrder.c \
src/base/abci/abcPart.c \