Commit 616bb095 by Alan Mishchenko

Version abc60701

parent 38141217
......@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\temp\ivy" /I "src\temp\esop" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\temp\ivy" /I "src\temp\esop" /I "src\temp\rwt" /I "src\temp\deco" /I "src\temp\mem" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
......@@ -50,7 +50,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"_TEST/abc.exe"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386 /out:"_TEST/abc.exe"
!ELSEIF "$(CFG)" == "abc - Win32 Debug"
......@@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\temp\ivy" /I "src\temp\esop" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\aig" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\temp\ivy" /I "src\temp\esop" /I "src\temp\rwt" /I "src\temp\deco" /I "src\temp\mem" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c
# SUBTRACT CPP /X
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
......@@ -2114,6 +2114,10 @@ SOURCE=.\src\temp\ivy\ivyMulti.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\ivy\ivyMulti8.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\ivy\ivyObj.c
# End Source File
# Begin Source File
......@@ -2122,10 +2126,22 @@ SOURCE=.\src\temp\ivy\ivyOper.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\ivy\ivyResyn.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\ivy\ivyRewrite.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\ivy\ivyRwrAlg.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\ivy\ivyRwrPre.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\ivy\ivySeq.c
# End Source File
# Begin Source File
......@@ -2182,10 +2198,6 @@ SOURCE=.\src\temp\esop\esopMan.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\esop\esopMem.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\esop\esopMin.c
# End Source File
# Begin Source File
......@@ -2237,6 +2249,46 @@ SOURCE=.\src\temp\xyz\xyzMinUtil.c
SOURCE=.\src\temp\xyz\xyzTest.c
# End Source File
# End Group
# Begin Group "rwt"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\temp\rwt\rwt.h
# End Source File
# Begin Source File
SOURCE=.\src\temp\rwt\rwtDec.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\rwt\rwtMan.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\rwt\rwtUtil.c
# End Source File
# End Group
# Begin Group "deco"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\temp\deco\deco.h
# End Source File
# End Group
# Begin Group "mem"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\temp\mem\mem.c
# End Source File
# Begin Source File
SOURCE=.\src\temp\mem\mem.h
# End Source File
# End Group
# End Group
# End Group
# Begin Group "Header Files"
......
......@@ -4647,9 +4647,11 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
// Ivy_TruthTest();
pNtkRes = Abc_NtkIvy( pNtk );
Ivy_TruthEstimateNodesTest();
// pNtkRes = Abc_NtkIvy( pNtk );
// pNtkRes = Abc_NtkPlayer( pNtk, nLevels, 0 );
// pNtkRes = NULL;
pNtkRes = NULL;
if ( pNtkRes == NULL )
{
fprintf( pErr, "Command has failed.\n" );
......
......@@ -110,7 +110,7 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
Vec_PtrFree( vNodes );
Vec_IntFree( vChoices );
PRT( "Total", clock() - clk );
//Abc_NtkPrintCuts_( p, pNtk, 0 );
//Abc_NtkPrintCuts( p, pNtk, 0 );
// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
// temporary printout of stats
......
......@@ -53,7 +53,7 @@ extern char * Mio_GateReadSop( void * pGate );
***********************************************************************/
Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk )
{
Ivy_Man_t * pMan;
Ivy_Man_t * pMan, * pTemp = NULL;
Abc_Ntk_t * pNtkAig;
int fCleanup = 1;
int nNodes;
......@@ -74,7 +74,6 @@ Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk )
// convert to the AIG manager
pMan = Abc_NtkToAig( pNtk );
if ( !Ivy_ManCheck( pMan ) )
{
printf( "AIG check has failed.\n" );
......@@ -82,13 +81,29 @@ Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk )
return NULL;
}
// Ivy_MffcTest( pMan );
Ivy_ManPrintStats( pMan );
// Ivy_ManPrintStats( pMan );
// pMan = Ivy_ManBalance( pTemp = pMan, 1 );
// Ivy_ManStop( pTemp );
// Ivy_ManSeqRewrite( pMan, 0, 0 );
// Ivy_ManTestCutsAlg( pMan );
Ivy_ManTestCutsBool( pMan );
Ivy_ManPrintStats( pMan );
// Ivy_ManTestCutsBool( pMan );
// Ivy_ManRewriteAlg( pMan, 1, 1 );
// pMan = Ivy_ManResyn( pTemp = pMan, 1 );
// Ivy_ManStop( pTemp );
// Ivy_ManTestCutsAll( pMan );
// Ivy_ManPrintStats( pMan );
// Ivy_ManPrintStats( pMan );
// Ivy_ManRewritePre( pMan, 1, 0, 0 );
// Ivy_ManPrintStats( pMan );
// Ivy_ManRequiredLevels( pMan );
// convert from the AIG manager
pNtkAig = Abc_NtkFromAig( pNtk, pMan );
......@@ -191,9 +206,9 @@ Ivy_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtkOld )
// create the manager
assert( Abc_NtkHasSop(pNtkOld) || Abc_NtkHasAig(pNtkOld) );
if ( Abc_NtkHasSop(pNtkOld) )
pMan = Ivy_ManStart( Abc_NtkCiNum(pNtkOld), Abc_NtkCoNum(pNtkOld), 3 * Abc_NtkGetLitNum(pNtkOld) + 10 );
pMan = Ivy_ManStart( Abc_NtkCiNum(pNtkOld), Abc_NtkCoNum(pNtkOld), Abc_NtkGetLitNum(pNtkOld) + 1000 );
else
pMan = Ivy_ManStart( Abc_NtkCiNum(pNtkOld), Abc_NtkCoNum(pNtkOld), 3 * Abc_NtkNodeNum(pNtkOld) + 10 );
pMan = Ivy_ManStart( Abc_NtkCiNum(pNtkOld), Abc_NtkCoNum(pNtkOld), Abc_NtkNodeNum(pNtkOld) + 1000 );
// create the PIs
Abc_NtkConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Ivy_ManConst1(pMan);
Abc_NtkForEachCi( pNtkOld, pObj, i )
......
......@@ -135,7 +135,7 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
}
*/
/*
// print the statistic into a file
{
FILE * pTable;
......@@ -146,6 +146,7 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
fprintf( pTable, "\n" );
fclose( pTable );
}
*/
/*
// print the statistic into a file
......
......@@ -18,7 +18,7 @@
***********************************************************************/
#include "stdio.h"
#include <stdio.h>
#include "extra.h"
////////////////////////////////////////////////////////////////////////
......
......@@ -18,7 +18,7 @@
***********************************************************************/
#include "stdio.h"
#include <stdio.h>
#include "extra.h"
#include "vec.h"
......
......@@ -18,7 +18,7 @@
***********************************************************************/
#include "stdio.h"
#include <stdio.h>
#include "extra.h"
////////////////////////////////////////////////////////////////////////
......
......@@ -325,6 +325,7 @@ static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
***********************************************************************/
static inline int Vec_IntEntryLast( Vec_Int_t * p )
{
assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
......
......@@ -312,6 +312,7 @@ static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry )
***********************************************************************/
static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p )
{
assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
......
......@@ -303,6 +303,7 @@ static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry )
***********************************************************************/
static inline char Vec_StrEntryLast( Vec_Str_t * p )
{
assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
......
......@@ -71,6 +71,9 @@ struct Vec_Vec_t_
#define Vec_VecForEachEntryReverse( vGlob, pEntry, i, k ) \
for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
#define Vec_VecForEachEntryReverseReverse( vGlob, pEntry, i, k ) \
for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \
Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
......
......@@ -104,6 +104,36 @@ static inline void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList )
/**Function*************************************************************
Synopsis [Checks equality of one cut.]
Description [Returns 1 if the cut is removed.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Cut_CutFilterOneEqual( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut )
{
Cut_Cut_t * pTemp;
Cut_ListForEachCut( pSuperList->pHead[pCut->nLeaves], pTemp )
{
// skip the non-contained cuts
if ( pCut->uSign != pTemp->uSign )
continue;
// check containment seriously
if ( Cut_CutCheckDominance( pTemp, pCut ) )
{
p->nCutsFilter++;
Cut_CutRecycle( p, pCut );
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Checks containment for one cut.]
Description [Returns 1 if the cut is removed.]
......@@ -266,6 +296,7 @@ static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t
if ( p->pParams->fFilter )
{
if ( Cut_CutFilterOne(p, pSuperList, pCut) )
// if ( Cut_CutFilterOneEqual(p, pSuperList, pCut) )
return 0;
if ( p->pParams->fSeq )
{
......
......@@ -26,6 +26,7 @@
////////////////////////////////////////////////////////////////////////
static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest );
static int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
......@@ -64,6 +65,7 @@ int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int
p->nNodesConsidered++;
// get the required times
Required = fUpdateLevel? Abc_NodeReadRequiredLevel(pNode) : ABC_INFINITY;
// get the node's cuts
clk = clock();
pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 );
......@@ -77,6 +79,9 @@ clk = clock();
// consider only 4-input cuts
if ( pCut->nLeaves < 4 )
continue;
// if ( pNode->Id == 82 )
// Cut_CutPrint( pCut, 0 ), printf( "\n" );
// get the fanin permutation
uTruth = 0xFFFF & *Cut_CutReadTruth(pCut);
pPerm = p->pPerms4[ p->pPerms[uTruth] ];
......@@ -144,6 +149,27 @@ p->timeRes += clock() - clk;
return -1;
// printf( "%d", nNodesSaveCur - GainBest );
/*
if ( GainBest > 0 )
{
if ( Rwr_CutIsBoolean( pNode, p->vFanins ) )
printf( "b" );
else
{
printf( "Node %d : ", pNode->Id );
Vec_PtrForEachEntry( p->vFanins, pFanin, i )
printf( "%d ", Abc_ObjRegular(pFanin)->Id );
printf( "a" );
}
}
*/
/*
if ( GainBest > 0 )
if ( p->fCompl )
printf( "c" );
else
printf( "." );
*/
// copy the leaves
Vec_PtrForEachEntry( p->vFanins, pFanin, i )
......@@ -221,6 +247,65 @@ Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCu
return pGraphBest;
}
/**Function*************************************************************
Synopsis [Checks the type of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_CutIsBoolean_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, int fMarkA )
{
if ( Vec_PtrFind(vLeaves, pObj) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pObj)) >= 0 )
{
if ( fMarkA )
pObj->fMarkA = 1;
else
pObj->fMarkB = 1;
return;
}
assert( !Abc_ObjIsCi(pObj) );
Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, fMarkA );
Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, fMarkA );
}
/**Function*************************************************************
Synopsis [Checks the type of the cut.]
Description [Returns 1(0) if the cut is Boolean (algebraic).]
SideEffects []
SeeAlso []
***********************************************************************/
int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
{
Abc_Obj_t * pTemp;
int i, RetValue;
Vec_PtrForEachEntry( vLeaves, pTemp, i )
{
pTemp = Abc_ObjRegular(pTemp);
assert( !pTemp->fMarkA && !pTemp->fMarkB );
}
Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, 1 );
Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, 0 );
RetValue = 0;
Vec_PtrForEachEntry( vLeaves, pTemp, i )
{
pTemp = Abc_ObjRegular(pTemp);
RetValue |= pTemp->fMarkA && pTemp->fMarkB;
pTemp->fMarkA = pTemp->fMarkB = 0;
}
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
/**CFile****************************************************************
FileName [deco.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [A simple decomposition tree/node data structure and its APIs.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __DEC_H__
#define __DEC_H__
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Dec_Edge_t_ Dec_Edge_t;
struct Dec_Edge_t_
{
unsigned fCompl : 1; // the complemented bit
unsigned Node : 30; // the decomposition node pointed by the edge
};
typedef struct Dec_Node_t_ Dec_Node_t;
struct Dec_Node_t_
{
Dec_Edge_t eEdge0; // the left child of the node
Dec_Edge_t eEdge1; // the right child of the node
// other info
void * pFunc; // the function of the node (BDD or AIG)
unsigned Level : 16; // the level of this node in the global AIG
// printing info
unsigned fNodeOr : 1; // marks the original OR node
unsigned fCompl0 : 1; // marks the original complemented edge
unsigned fCompl1 : 1; // marks the original complemented edge
};
typedef struct Dec_Graph_t_ Dec_Graph_t;
struct Dec_Graph_t_
{
int fConst; // marks the constant 1 graph
int nLeaves; // the number of leaves
int nSize; // the number of nodes (including the leaves)
int nCap; // the number of allocated nodes
Dec_Node_t * pNodes; // the array of leaves and internal nodes
Dec_Edge_t eRoot; // the pointer to the topmost node
};
typedef struct Dec_Man_t_ Dec_Man_t;
struct Dec_Man_t_
{
void * pMvcMem; // memory manager for MVC cover (used for factoring)
Vec_Int_t * vCubes; // storage for cubes
Vec_Int_t * vLits; // storage for literals
// precomputation information about 4-variable functions
unsigned short * puCanons; // canonical forms
char * pPhases; // canonical phases
char * pPerms; // canonical permutations
unsigned char * pMap; // mapping of functions into class numbers
};
////////////////////////////////////////////////////////////////////////
/// ITERATORS ///
////////////////////////////////////////////////////////////////////////
// interator throught the leaves
#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \
for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ )
// interator throught the internal nodes
#define Dec_GraphForEachNode( pGraph, pAnd, i ) \
for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates an edge pointing to the node in the given polarity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl )
{
Dec_Edge_t eEdge = { fCompl, Node };
return eEdge;
}
/**Function*************************************************************
Synopsis [Converts the edge into unsigned integer.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge )
{
return (eEdge.Node << 1) | eEdge.fCompl;
}
/**Function*************************************************************
Synopsis [Converts unsigned integer into the edge.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge )
{
return Dec_EdgeCreate( Edge >> 1, Edge & 1 );
}
/**Function*************************************************************
Synopsis [Converts the edge into unsigned integer.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge )
{
return *(unsigned *)&eEdge;
}
/**Function*************************************************************
Synopsis [Converts unsigned integer into the edge.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge )
{
return *(Dec_Edge_t *)&Edge;
}
/**Function*************************************************************
Synopsis [Creates a graph with the given number of leaves.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves )
{
Dec_Graph_t * pGraph;
pGraph = ALLOC( Dec_Graph_t, 1 );
memset( pGraph, 0, sizeof(Dec_Graph_t) );
pGraph->nLeaves = nLeaves;
pGraph->nSize = nLeaves;
pGraph->nCap = 2 * nLeaves + 50;
pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap );
memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize );
return pGraph;
}
/**Function*************************************************************
Synopsis [Creates constant 0 graph.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Graph_t * Dec_GraphCreateConst0()
{
Dec_Graph_t * pGraph;
pGraph = ALLOC( Dec_Graph_t, 1 );
memset( pGraph, 0, sizeof(Dec_Graph_t) );
pGraph->fConst = 1;
pGraph->eRoot.fCompl = 1;
return pGraph;
}
/**Function*************************************************************
Synopsis [Creates constant 1 graph.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Graph_t * Dec_GraphCreateConst1()
{
Dec_Graph_t * pGraph;
pGraph = ALLOC( Dec_Graph_t, 1 );
memset( pGraph, 0, sizeof(Dec_Graph_t) );
pGraph->fConst = 1;
return pGraph;
}
/**Function*************************************************************
Synopsis [Creates the literal graph.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl )
{
Dec_Graph_t * pGraph;
assert( 0 <= iLeaf && iLeaf < nLeaves );
pGraph = Dec_GraphCreate( nLeaves );
pGraph->eRoot.Node = iLeaf;
pGraph->eRoot.fCompl = fCompl;
return pGraph;
}
/**Function*************************************************************
Synopsis [Creates a graph with the given number of leaves.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Dec_GraphFree( Dec_Graph_t * pGraph )
{
FREE( pGraph->pNodes );
free( pGraph );
}
/**Function*************************************************************
Synopsis [Returns 1 if the graph is a constant.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph )
{
return pGraph->fConst;
}
/**Function*************************************************************
Synopsis [Returns 1 if the graph is constant 0.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph )
{
return pGraph->fConst && pGraph->eRoot.fCompl;
}
/**Function*************************************************************
Synopsis [Returns 1 if the graph is constant 1.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph )
{
return pGraph->fConst && !pGraph->eRoot.fCompl;
}
/**Function*************************************************************
Synopsis [Returns 1 if the graph is complemented.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph )
{
return pGraph->eRoot.fCompl;
}
/**Function*************************************************************
Synopsis [Checks if the graph is complemented.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Dec_GraphComplement( Dec_Graph_t * pGraph )
{
pGraph->eRoot.fCompl ^= 1;
}
/**Function*************************************************************
Synopsis [Returns the number of leaves.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph )
{
return pGraph->nLeaves;
}
/**Function*************************************************************
Synopsis [Returns the number of internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph )
{
return pGraph->nSize - pGraph->nLeaves;
}
/**Function*************************************************************
Synopsis [Returns the pointer to the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i )
{
return pGraph->pNodes + i;
}
/**Function*************************************************************
Synopsis [Returns the pointer to the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph )
{
return pGraph->pNodes + pGraph->nSize - 1;
}
/**Function*************************************************************
Synopsis [Returns the number of the given node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
{
return pNode - pGraph->pNodes;
}
/**Function*************************************************************
Synopsis [Check if the graph represents elementary variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph )
{
return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves;
}
/**Function*************************************************************
Synopsis [Check if the graph represents elementary variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
{
return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves;
}
/**Function*************************************************************
Synopsis [Returns the elementary variable elementary variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph )
{
assert( Dec_GraphIsVar( pGraph ) );
return Dec_GraphNode( pGraph, pGraph->eRoot.Node );
}
/**Function*************************************************************
Synopsis [Returns the number of the elementary variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph )
{
assert( Dec_GraphIsVar( pGraph ) );
return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) );
}
/**Function*************************************************************
Synopsis [Sets the root of the graph.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot )
{
pGraph->eRoot = eRoot;
}
/**Function*************************************************************
Synopsis [Appends a new node to the graph.]
Description [This procedure is meant for internal use.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph )
{
Dec_Node_t * pNode;
if ( pGraph->nSize == pGraph->nCap )
{
pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap );
pGraph->nCap = 2 * pGraph->nCap;
}
pNode = pGraph->pNodes + pGraph->nSize++;
memset( pNode, 0, sizeof(Dec_Node_t) );
return pNode;
}
/**Function*************************************************************
Synopsis [Creates an AND node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
{
Dec_Node_t * pNode;
// get the new node
pNode = Dec_GraphAppendNode( pGraph );
// set the inputs and other info
pNode->eEdge0 = eEdge0;
pNode->eEdge1 = eEdge1;
pNode->fCompl0 = eEdge0.fCompl;
pNode->fCompl1 = eEdge1.fCompl;
return Dec_EdgeCreate( pGraph->nSize - 1, 0 );
}
/**Function*************************************************************
Synopsis [Creates an OR node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
{
Dec_Node_t * pNode;
// get the new node
pNode = Dec_GraphAppendNode( pGraph );
// set the inputs and other info
pNode->eEdge0 = eEdge0;
pNode->eEdge1 = eEdge1;
pNode->fCompl0 = eEdge0.fCompl;
pNode->fCompl1 = eEdge1.fCompl;
// make adjustments for the OR gate
pNode->fNodeOr = 1;
pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl;
pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl;
return Dec_EdgeCreate( pGraph->nSize - 1, 1 );
}
/**Function*************************************************************
Synopsis [Creates an XOR node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type )
{
Dec_Edge_t eNode0, eNode1, eNode;
if ( Type == 0 )
{
// derive the first AND
eEdge0.fCompl ^= 1;
eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
eEdge0.fCompl ^= 1;
// derive the second AND
eEdge1.fCompl ^= 1;
eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
// derive the final OR
eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
}
else
{
// derive the first AND
eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
// derive the second AND
eEdge0.fCompl ^= 1;
eEdge1.fCompl ^= 1;
eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
// derive the final OR
eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
eNode.fCompl ^= 1;
}
return eNode;
}
/**Function*************************************************************
Synopsis [Creates an XOR node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type )
{
Dec_Edge_t eNode0, eNode1, eNode;
if ( Type == 0 )
{
// derive the first AND
eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
// derive the second AND
eEdgeC.fCompl ^= 1;
eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
// derive the final OR
eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
}
else
{
// complement the arguments
eEdgeT.fCompl ^= 1;
eEdgeE.fCompl ^= 1;
// derive the first AND
eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
// derive the second AND
eEdgeC.fCompl ^= 1;
eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
// derive the final OR
eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
eNode.fCompl ^= 1;
}
return eNode;
}
#ifdef __cplusplus
}
#endif
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -25,8 +25,9 @@
extern "C" {
#endif
#include "stdio.h"
#include <stdio.h>
#include "vec.h"
#include "mem.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
......@@ -34,16 +35,16 @@ extern "C" {
typedef struct Esop_Man_t_ Esop_Man_t;
typedef struct Esop_Cube_t_ Esop_Cube_t;
typedef struct Esop_MmFixed_t_ Esop_MmFixed_t;
typedef struct Mem_Fixed_t_ Mem_Fixed_t;
struct Esop_Man_t_
{
int nVars; // the number of vars
int nWords; // the number of words
Esop_MmFixed_t * pMemMan1; // memory manager for cubes
Esop_MmFixed_t * pMemMan2; // memory manager for cubes
Esop_MmFixed_t * pMemMan4; // memory manager for cubes
Esop_MmFixed_t * pMemMan8; // memory manager for cubes
Mem_Fixed_t * pMemMan1; // memory manager for cubes
Mem_Fixed_t * pMemMan2; // memory manager for cubes
Mem_Fixed_t * pMemMan4; // memory manager for cubes
Mem_Fixed_t * pMemMan8; // memory manager for cubes
// temporary cubes
Esop_Cube_t * pOne0; // tautology cube
Esop_Cube_t * pOne1; // tautology cube
......@@ -99,12 +100,12 @@ static inline void Esop_CubeXorVar( Esop_Cube_t * p, int Var, int Value ) { p-
static inline int Esop_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); }
/*=== esopMem.c ===========================================================*/
extern Esop_MmFixed_t * Esop_MmFixedStart( int nEntrySize );
extern void Esop_MmFixedStop( Esop_MmFixed_t * p, int fVerbose );
extern char * Esop_MmFixedEntryFetch( Esop_MmFixed_t * p );
extern void Esop_MmFixedEntryRecycle( Esop_MmFixed_t * p, char * pEntry );
extern void Esop_MmFixedRestart( Esop_MmFixed_t * p );
extern int Esop_MmFixedReadMemUsage( Esop_MmFixed_t * p );
extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize );
extern void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose );
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 );
/*=== esopMin.c ===========================================================*/
extern void Esop_EsopMinimize( Esop_Man_t * p );
extern void Esop_EsopAddCube( Esop_Man_t * p, Esop_Cube_t * pCube );
......@@ -142,13 +143,13 @@ static inline Esop_Cube_t * Esop_CubeAlloc( Esop_Man_t * p )
{
Esop_Cube_t * pCube;
if ( p->nWords <= 1 )
pCube = (Esop_Cube_t *)Esop_MmFixedEntryFetch( p->pMemMan1 );
pCube = (Esop_Cube_t *)Mem_FixedEntryFetch( p->pMemMan1 );
else if ( p->nWords <= 2 )
pCube = (Esop_Cube_t *)Esop_MmFixedEntryFetch( p->pMemMan2 );
pCube = (Esop_Cube_t *)Mem_FixedEntryFetch( p->pMemMan2 );
else if ( p->nWords <= 4 )
pCube = (Esop_Cube_t *)Esop_MmFixedEntryFetch( p->pMemMan4 );
pCube = (Esop_Cube_t *)Mem_FixedEntryFetch( p->pMemMan4 );
else if ( p->nWords <= 8 )
pCube = (Esop_Cube_t *)Esop_MmFixedEntryFetch( p->pMemMan8 );
pCube = (Esop_Cube_t *)Mem_FixedEntryFetch( p->pMemMan8 );
pCube->pNext = NULL;
pCube->nVars = p->nVars;
pCube->nWords = p->nWords;
......@@ -211,13 +212,13 @@ static inline Esop_Cube_t * Esop_CubeDup( Esop_Man_t * p, Esop_Cube_t * pCopy )
static inline void Esop_CubeRecycle( Esop_Man_t * p, Esop_Cube_t * pCube )
{
if ( pCube->nWords <= 1 )
Esop_MmFixedEntryRecycle( p->pMemMan1, (char *)pCube );
Mem_FixedEntryRecycle( p->pMemMan1, (char *)pCube );
else if ( pCube->nWords <= 2 )
Esop_MmFixedEntryRecycle( p->pMemMan2, (char *)pCube );
Mem_FixedEntryRecycle( p->pMemMan2, (char *)pCube );
else if ( pCube->nWords <= 4 )
Esop_MmFixedEntryRecycle( p->pMemMan4, (char *)pCube );
Mem_FixedEntryRecycle( p->pMemMan4, (char *)pCube );
else if ( pCube->nWords <= 8 )
Esop_MmFixedEntryRecycle( p->pMemMan8, (char *)pCube );
Mem_FixedEntryRecycle( p->pMemMan8, (char *)pCube );
}
/**Function*************************************************************
......@@ -238,16 +239,16 @@ static inline void Esop_CoverRecycle( Esop_Man_t * p, Esop_Cube_t * pCover )
return;
if ( pCover->nWords <= 1 )
Esop_CoverForEachCubeSafe( pCover, pCube, pCube2 )
Esop_MmFixedEntryRecycle( p->pMemMan1, (char *)pCube );
Mem_FixedEntryRecycle( p->pMemMan1, (char *)pCube );
else if ( pCover->nWords <= 2 )
Esop_CoverForEachCubeSafe( pCover, pCube, pCube2 )
Esop_MmFixedEntryRecycle( p->pMemMan2, (char *)pCube );
Mem_FixedEntryRecycle( p->pMemMan2, (char *)pCube );
else if ( pCover->nWords <= 4 )
Esop_CoverForEachCubeSafe( pCover, pCube, pCube2 )
Esop_MmFixedEntryRecycle( p->pMemMan4, (char *)pCube );
Mem_FixedEntryRecycle( p->pMemMan4, (char *)pCube );
else if ( pCover->nWords <= 8 )
Esop_CoverForEachCubeSafe( pCover, pCube, pCube2 )
Esop_MmFixedEntryRecycle( p->pMemMan8, (char *)pCube );
Mem_FixedEntryRecycle( p->pMemMan8, (char *)pCube );
}
/**Function*************************************************************
......
......@@ -47,10 +47,10 @@ Esop_Man_t * Esop_ManAlloc( int nVars )
memset( pMan, 0, sizeof(Esop_Man_t) );
pMan->nVars = nVars;
pMan->nWords = Esop_BitWordNum( nVars * 2 );
pMan->pMemMan1 = Esop_MmFixedStart( sizeof(Esop_Cube_t) + sizeof(unsigned) * (1 - 1) );
pMan->pMemMan2 = Esop_MmFixedStart( sizeof(Esop_Cube_t) + sizeof(unsigned) * (2 - 1) );
pMan->pMemMan4 = Esop_MmFixedStart( sizeof(Esop_Cube_t) + sizeof(unsigned) * (4 - 1) );
pMan->pMemMan8 = Esop_MmFixedStart( sizeof(Esop_Cube_t) + sizeof(unsigned) * (8 - 1) );
pMan->pMemMan1 = Mem_FixedStart( sizeof(Esop_Cube_t) + sizeof(unsigned) * (1 - 1) );
pMan->pMemMan2 = Mem_FixedStart( sizeof(Esop_Cube_t) + sizeof(unsigned) * (2 - 1) );
pMan->pMemMan4 = Mem_FixedStart( sizeof(Esop_Cube_t) + sizeof(unsigned) * (4 - 1) );
pMan->pMemMan8 = Mem_FixedStart( sizeof(Esop_Cube_t) + sizeof(unsigned) * (8 - 1) );
// allocate storage for the temporary cover
pMan->ppStore = ALLOC( Esop_Cube_t *, pMan->nVars + 1 );
// create tautology cubes
......@@ -101,10 +101,10 @@ void Esop_ManClean( Esop_Man_t * p, int nSupp )
***********************************************************************/
void Esop_ManFree( Esop_Man_t * p )
{
Esop_MmFixedStop ( p->pMemMan1, 0 );
Esop_MmFixedStop ( p->pMemMan2, 0 );
Esop_MmFixedStop ( p->pMemMan4, 0 );
Esop_MmFixedStop ( p->pMemMan8, 0 );
Mem_FixedStop ( p->pMemMan1, 0 );
Mem_FixedStop ( p->pMemMan2, 0 );
Mem_FixedStop ( p->pMemMan4, 0 );
Mem_FixedStop ( p->pMemMan8, 0 );
free( p->ppStore );
free( p );
}
......
SRC += src/temp/esop/esopMan.c \
src/temp/esop/esopMem.c \
src/temp/esop/esopMin.c \
src/temp/esop/esopUtil.c
......@@ -42,6 +42,11 @@ extern "C" {
typedef struct Ivy_Man_t_ Ivy_Man_t;
typedef struct Ivy_Obj_t_ Ivy_Obj_t;
typedef int Ivy_Edge_t;
// constant edges
#define IVY_CONST0 1
#define IVY_CONST1 0
// object types
typedef enum {
......@@ -102,10 +107,12 @@ struct Ivy_Man_t_
int * pTable; // structural hash table
int nTableSize; // structural hash table size
// various data members
int fCatchExor; // set to 1 to detect EXORs
int fExtended; // set to 1 in extended mode
int nTravIds; // the traversal ID
int nLevelMax; // the maximum level
void * pData; // the temporary data
Vec_Int_t * vRequired; // required times
// truth table of the 8-LUTs
unsigned * pMemory; // memory for truth tables
Vec_Int_t * vTruths; // offset for truth table of each node
......@@ -118,6 +125,26 @@ struct Ivy_Man_t_
};
#define IVY_CUT_LIMIT 256
#define IVY_CUT_INPUT 6
typedef struct Ivy_Cut_t_ Ivy_Cut_t;
struct Ivy_Cut_t_
{
short nSize;
short nSizeMax;
int pArray[IVY_CUT_INPUT];
unsigned uHash;
};
typedef struct Ivy_Store_t_ Ivy_Store_t;
struct Ivy_Store_t_
{
int nCuts;
int nCutsMax;
Ivy_Cut_t pCuts[IVY_CUT_LIMIT]; // storage for cuts
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -133,14 +160,6 @@ static inline int Ivy_InfoHasBit( unsigned * p, int i ) { return (p[(i
static inline void Ivy_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); }
static inline void Ivy_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); }
static inline int Ivy_FanCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; }
static inline int Ivy_FanId( int Fan ) { return Fan >> 1; }
static inline int Ivy_FanCompl( int Fan ) { return Fan & 1; }
static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << 4) | Lat; }
static inline int Ivy_LeafId( int Leaf ) { return Leaf >> 4; }
static inline int Ivy_LeafLat( int Leaf ) { return Leaf & 15; }
static inline Ivy_Obj_t * Ivy_Regular( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned)(p) & ~01); }
static inline Ivy_Obj_t * Ivy_Not( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned)(p) ^ 01); }
static inline Ivy_Obj_t * Ivy_NotCond( Ivy_Obj_t * p, int c ) { return (Ivy_Obj_t *)((unsigned)(p) ^ (c)); }
......@@ -153,6 +172,19 @@ static inline Ivy_Obj_t * Ivy_ManPi( Ivy_Man_t * p, int i ) { return p->pO
static inline Ivy_Obj_t * Ivy_ManPo( Ivy_Man_t * p, int i ) { return p->pObjs + Vec_IntEntry(p->vPos,i); }
static inline Ivy_Obj_t * Ivy_ManObj( Ivy_Man_t * p, int i ) { return p->pObjs + i; }
static inline Ivy_Edge_t Ivy_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; }
static inline int Ivy_EdgeId( Ivy_Edge_t Edge ) { return Edge >> 1; }
static inline int Ivy_EdgeIsComplement( Ivy_Edge_t Edge ) { return Edge & 1; }
static inline Ivy_Edge_t Ivy_EdgeRegular( Ivy_Edge_t Edge ) { return (Edge >> 1) << 1; }
static inline Ivy_Edge_t Ivy_EdgeNot( Ivy_Edge_t Edge ) { return Edge ^ 1; }
static inline Ivy_Edge_t Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond ) { return Edge ^ fCond; }
static inline Ivy_Edge_t Ivy_EdgeFromNode( Ivy_Obj_t * pNode ) { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) ); }
static inline Ivy_Obj_t * Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); }
static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << 4) | Lat; }
static inline int Ivy_LeafId( int Leaf ) { return Leaf >> 4; }
static inline int Ivy_LeafLat( int Leaf ) { return Leaf & 15; }
static inline int Ivy_ManPiNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PI]; }
static inline int Ivy_ManPoNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PO]; }
static inline int Ivy_ManAssertNum( Ivy_Man_t * p ) { return p->nObjs[IVY_ASSERT]; }
......@@ -185,9 +217,9 @@ static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { assert( !Ivy
static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_EXOR; }
static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_BUF; }
static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; }
static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; }
static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; }
static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; }
static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; }
static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; }
static inline int Ivy_ObjIsAndMulti( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_ANDM; }
static inline int Ivy_ObjIsExorMulti( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_EXORM; }
......@@ -227,13 +259,9 @@ static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { assert( !Ivy
static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_NotCond( Ivy_ObjFanin1(pObj), Ivy_ObjFaninC1(pObj) ); }
static inline int Ivy_ObjLevelR( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->LevelR; }
static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Level; }
static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return 1 + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); }
static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); }
static inline void Ivy_ObjClean( Ivy_Obj_t * pObj ) {
int IdSaved = pObj->Id;
if ( IdSaved == 54 )
{
int x = 0;
}
memset( pObj, 0, sizeof(Ivy_Obj_t) );
pObj->Id = IdSaved;
}
......@@ -339,6 +367,8 @@ static inline int Ivy_ObjFaninNum( Ivy_Obj_t * pObj )
// iterator over all objects, including those currently not used
#define Ivy_ManForEachObj( p, pObj, i ) \
for ( i = 0, pObj = p->pObjs; i < p->ObjIdNext; i++, pObj++ )
#define Ivy_ManForEachObjReverse( p, pObj, i ) \
for ( i = p->ObjIdNext - 1, pObj = p->pObjs + i; i >= 0; i--, pObj-- )
// iterator over the primary inputs
#define Ivy_ManForEachPi( p, pObj, i ) \
for ( i = 0; i < Vec_IntSize(p->vPis) && ((pObj) = Ivy_ManPi(p, i)); i++ )
......@@ -369,6 +399,9 @@ static inline int Ivy_ObjFaninNum( Ivy_Obj_t * pObj )
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== ivyBalance.c ========================================================*/
extern Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel );
extern Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel );
/*=== ivyCanon.c ========================================================*/
extern Ivy_Obj_t * Ivy_CanonAnd( Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
extern Ivy_Obj_t * Ivy_CanonExor( Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
......@@ -377,11 +410,13 @@ extern Ivy_Obj_t * Ivy_CanonLatch( Ivy_Obj_t * pObj, Ivy_Init_t Init );
extern int Ivy_ManCheck( Ivy_Man_t * p );
/*=== ivyCut.c ==========================================================*/
extern void Ivy_ManSeqFindCut( Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize );
/*=== ivyBalance.c ======================================================*/
extern int Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel );
extern Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Obj_t * pObj, int nLeaves );
/*=== ivyDfs.c ==========================================================*/
extern Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p );
extern Vec_Int_t * Ivy_ManDfsExt( Ivy_Man_t * p );
extern void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone );
extern Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p );
extern Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p );
/*=== ivyDsd.c ==========================================================*/
extern int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree );
extern void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree );
......@@ -399,6 +434,7 @@ extern Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type
extern Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
extern Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type );
extern Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
extern int Ivy_MultiPlus( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol );
/*=== ivyObj.c ==========================================================*/
extern Ivy_Obj_t * Ivy_ObjCreate( Ivy_Obj_t * pGhost );
extern Ivy_Obj_t * Ivy_ObjCreateExt( Ivy_Man_t * p, Ivy_Type_t Type );
......@@ -415,8 +451,12 @@ extern Ivy_Obj_t * Ivy_Exor( Ivy_Obj_t * p0, Ivy_Obj_t * p1 );
extern Ivy_Obj_t * Ivy_Mux( Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 );
extern Ivy_Obj_t * Ivy_Maj( Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC );
extern Ivy_Obj_t * Ivy_Miter( Vec_Ptr_t * vPairs );
/*=== ivyResyn.c =========================================================*/
extern Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel );
/*=== ivyRewrite.c =========================================================*/
extern int Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost );
extern int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost );
extern int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose );
/*=== ivyTable.c ========================================================*/
extern Ivy_Obj_t * Ivy_TableLookup( Ivy_Obj_t * pObj );
extern void Ivy_TableInsert( Ivy_Obj_t * pObj );
......@@ -437,6 +477,8 @@ extern Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObj
extern unsigned * Ivy_ManCutTruth( Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth );
extern Ivy_Obj_t * Ivy_NodeRealFanin_rec( Ivy_Obj_t * pNode, int iFanin );
extern Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p );
extern int Ivy_ManReadLevels( Ivy_Man_t * p );
extern Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj );
#ifdef __cplusplus
}
......
......@@ -17,32 +17,18 @@
Revision [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ivy.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void Ivy_NodeBalance( Ivy_Obj_t * pNode, int fUpdateLevel, Vec_Ptr_t * vFront, Vec_Ptr_t * vSpots );
// this procedure returns 1 if the node cannot be expanded
static inline int Ivy_NodeStopFanin( Ivy_Obj_t * pNode, int iFanin )
{
if ( iFanin == 0 )
return Ivy_ObjFanin0(pNode)->Type != pNode->Type || Ivy_ObjRefs(Ivy_ObjFanin0(pNode)) > 1 || Ivy_ObjFaninC0(pNode);
else
return Ivy_ObjFanin1(pNode)->Type != pNode->Type || Ivy_ObjRefs(Ivy_ObjFanin1(pNode)) > 1 || Ivy_ObjFaninC1(pNode);
}
// this procedure returns 1 if the node cannot be recursively dereferenced
static inline int Ivy_NodeBalanceDerefFanin( Ivy_Obj_t * pNode, int iFanin )
{
if ( iFanin == 0 )
return Ivy_ObjFanin0(pNode)->Type == pNode->Type && Ivy_ObjRefs(Ivy_ObjFanin0(pNode)) == 0 && !Ivy_ObjFaninC0(pNode);
else
return Ivy_ObjFanin1(pNode)->Type == pNode->Type && Ivy_ObjRefs(Ivy_ObjFanin1(pNode)) == 0 && !Ivy_ObjFaninC1(pNode);
}
static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
static void Ivy_NodeBalancePermute( Vec_Ptr_t * vSuper, int LeftBound, int fExor );
static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
......@@ -59,44 +45,41 @@ static inline int Ivy_NodeBalanceDerefFanin( Ivy_Obj_t * pNode, int iFanin )
SeeAlso []
***********************************************************************/
int Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel )
Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel )
{
Vec_Int_t * vNodes;
Vec_Ptr_t * vFront, * vSpots;
Ivy_Obj_t * pNode;
int i;
vSpots = Vec_PtrAlloc( 50 );
vFront = Vec_PtrAlloc( 50 );
vNodes = Ivy_ManDfs( p );
Ivy_ManForEachNodeVec( p, vNodes, pNode, i )
Ivy_Man_t * pNew;
Ivy_Obj_t * pObj, * pDriver;
Vec_Vec_t * vStore;
int i, NewNodeId;
// clean the old manager
Ivy_ManCleanTravId( p );
// create the new manager
pNew = Ivy_ManStart( Ivy_ManPiNum(p), Ivy_ManPoNum(p), Ivy_ManNodeNum(p) + 20000 );
// map the nodes
Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) );
Ivy_ManForEachPi( p, pObj, i )
pObj->TravId = Ivy_EdgeFromNode( Ivy_ManPi(pNew, i) );
// balance the AIG
vStore = Vec_VecAlloc( 50 );
Ivy_ManForEachPo( p, pObj, i )
{
if ( Ivy_ObjIsBuf(pNode) )
continue;
// fix the fanin buffer problem
Ivy_NodeFixBufferFanins( pNode );
// skip node if it became a buffer
if ( Ivy_ObjIsBuf(pNode) )
continue;
// skip nodes with one fanout if type of the node is the same as type of the fanout
// such nodes will be processed when the fanouts are processed
if ( Ivy_ObjRefs(pNode) == 1 && Ivy_ObjIsExor(pNode) == Ivy_ObjExorFanout(pNode) )
continue;
assert( Ivy_ObjRefs(pNode) > 0 );
// do not balance the node if both if its fanins have more than one fanout
if ( Ivy_NodeStopFanin(pNode, 0) && Ivy_NodeStopFanin(pNode, 1) )
continue;
// try balancing this node
Ivy_NodeBalance( pNode, fUpdateLevel, vFront, vSpots );
pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) );
NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel );
NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) );
Ivy_ObjConnect( Ivy_ManPo(pNew, i), Ivy_EdgeToNode(pNew, NewNodeId) );
}
Vec_IntFree( vNodes );
Vec_PtrFree( vSpots );
Vec_PtrFree( vFront );
return 1;
Vec_VecFree( vStore );
if ( i = Ivy_ManCleanup( pNew ) )
printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
// check the resulting AIG
if ( !Ivy_ManCheck(pNew) )
printf( "Ivy_ManBalance(): The check has failed.\n" );
return pNew;
}
/**Function*************************************************************
Synopsis [Dereferences MFFC of the node.]
Synopsis [Procedure used for sorting the nodes in decreasing order of levels.]
Description []
......@@ -105,24 +88,19 @@ int Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel )
SeeAlso []
***********************************************************************/
void Ivy_NodeBalanceDeref_rec( Ivy_Obj_t * pNode )
int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
{
Ivy_Obj_t * pFan;
// deref the first fanin
pFan = Ivy_ObjFanin0(pNode);
Ivy_ObjRefsDec( pFan );
if ( Ivy_NodeBalanceDerefFanin(pNode, 0) )
Ivy_NodeBalanceDeref_rec( pFan );
// deref the second fanin
pFan = Ivy_ObjFanin1(pNode);
Ivy_ObjRefsDec( pFan );
if ( Ivy_NodeBalanceDerefFanin(pNode, 1) )
Ivy_NodeBalanceDeref_rec( pFan );
int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level;
if ( Diff > 0 )
return -1;
if ( Diff < 0 )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Removes nodes inside supergate and determines frontier.]
Synopsis [Returns the ID of new node constructed.]
Description []
......@@ -131,35 +109,47 @@ void Ivy_NodeBalanceDeref_rec( Ivy_Obj_t * pNode )
SeeAlso []
***********************************************************************/
void Ivy_NodeBalanceCollect_rec( Ivy_Obj_t * pNode, Vec_Ptr_t * vSpots, Vec_Ptr_t * vFront )
int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
{
Ivy_Obj_t * pFanin;
// skip visited nodes
if ( Vec_PtrFind(vSpots, pNode) >= 0 )
return;
// collect node
Vec_PtrPush( vSpots, pNode );
// first fanin
pFanin = Ivy_ObjFanin0(pNode);
if ( Ivy_ObjRefs(pFanin) == 0 )
Ivy_NodeBalanceCollect_rec( pFanin, vSpots, vFront );
else if ( Ivy_ObjIsExor(pNode) && Vec_PtrFind(vFront, Ivy_ObjChild0(pNode)) >= 0 )
Vec_PtrRemove( vFront, Ivy_ObjChild0(pNode) );
else
Vec_PtrPushUnique( vFront, Ivy_ObjChild0(pNode) );
// second fanin
pFanin = Ivy_ObjFanin1(pNode);
if ( Ivy_ObjRefs(pFanin) == 0 )
Ivy_NodeBalanceCollect_rec( pFanin, vSpots, vFront );
else if ( Ivy_ObjIsExor(pNode) && Vec_PtrFind(vFront, Ivy_ObjChild1(pNode)) >= 0 )
Vec_PtrRemove( vFront, Ivy_ObjChild1(pNode) );
else
Vec_PtrPushUnique( vFront, Ivy_ObjChild1(pNode) );
Ivy_Obj_t * pObjNew;
Vec_Ptr_t * vSuper;
int i, NewNodeId;
assert( !Ivy_IsComplement(pObjOld) );
assert( !Ivy_ObjIsBuf(pObjOld) );
// return if the result is known
if ( Ivy_ObjIsConst1(pObjOld) )
return pObjOld->TravId;
if ( pObjOld->TravId )
return pObjOld->TravId;
assert( Ivy_ObjIsNode(pObjOld) );
// get the implication supergate
vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level );
if ( vSuper->nSize == 0 )
{ // it means that the supergate contains two nodes in the opposite polarity
pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) );
return pObjOld->TravId;
}
if ( vSuper->nSize < 2 )
printf( "BUG!\n" );
// for each old node, derive the new well-balanced node
for ( i = 0; i < vSuper->nSize; i++ )
{
NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(vSuper->pArray[i]) );
vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId );
}
// build the supergate
pObjNew = Ivy_NodeBalanceBuildSuper( vSuper, Ivy_ObjType(pObjOld), fUpdateLevel );
vSuper->nSize = 0;
// make sure the balanced node is not assigned
assert( pObjOld->TravId == 0 );
pObjOld->TravId = Ivy_EdgeFromNode( pObjNew );
return pObjOld->TravId;
}
/**Function*************************************************************
Synopsis [Comparison procedure for two nodes by level.]
Synopsis [Builds implication supergate.]
Description []
......@@ -168,89 +158,107 @@ void Ivy_NodeBalanceCollect_rec( Ivy_Obj_t * pNode, Vec_Ptr_t * vSpots, Vec_Ptr_
SeeAlso []
***********************************************************************/
int Ivy_BalanceCompareByLevel( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel )
{
int Level1 = Ivy_ObjLevel( *pp1 );
int Level2 = Ivy_ObjLevel( *pp2 );
if ( Level1 > Level2 )
return -1;
if ( Level1 < Level2 )
return 1;
return 0;
Ivy_Obj_t * pObj1, * pObj2;
int LeftBound;
assert( vSuper->nSize > 1 );
// sort the new nodes by level in the decreasing order
Vec_PtrSort( vSuper, Ivy_NodeCompareLevelsDecrease );
// balance the nodes
while ( vSuper->nSize > 1 )
{
// find the left bound on the node to be paired
LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper );
// find the node that can be shared (if no such node, randomize choice)
Ivy_NodeBalancePermute( vSuper, LeftBound, Type == IVY_EXOR );
// pull out the last two nodes
pObj1 = Vec_PtrPop(vSuper);
pObj2 = Vec_PtrPop(vSuper);
Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(pObj1, pObj2, Type) );
}
return Vec_PtrEntry(vSuper, 0);
}
/**Function*************************************************************
Synopsis [Removes nodes inside supergate and determines frontier.]
Synopsis [Collects the nodes of the supergate.]
Description [Return 1 if the output needs to be complemented.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_NodeBalancePrepare( Ivy_Obj_t * pNode, Vec_Ptr_t * vFront, Vec_Ptr_t * vSpots )
int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper )
{
Ivy_Man_t * pMan = Ivy_ObjMan( pNode );
Ivy_Obj_t * pObj, * pNext;
int i, k, Counter = 0;
// dereference the cone
Ivy_NodeBalanceDeref_rec( pNode );
// collect the frontier and the internal nodes
Vec_PtrClear( vFront );
Vec_PtrClear( vSpots );
Ivy_NodeBalanceCollect_rec( pNode, vSpots, vFront );
// remove all the nodes
Vec_PtrForEachEntry( vSpots, pObj, i )
{
// skip the first entry (the node itself)
if ( i == 0 ) continue;
// collect the free entries
Vec_IntPush( pMan->vFree, pObj->Id );
Ivy_ObjDelete( pObj, 1 );
}
// sort nodes by level in decreasing order
qsort( (void *)Vec_PtrArray(vFront), Vec_PtrSize(vFront), sizeof(Ivy_Obj_t *),
(int (*)(const void *, const void *))Ivy_BalanceCompareByLevel );
// check if there are nodes and their complements
Counter = 0;
Vec_PtrForEachEntry( vFront, pObj, i )
int RetValue1, RetValue2, i;
// check if the node is visited
if ( Ivy_Regular(pObj)->fMarkB )
{
if ( i == Vec_PtrSize(vFront) - 1 )
break;
pNext = Vec_PtrEntry( vFront, i+1 );
if ( Ivy_Regular(pObj) == Ivy_Regular(pNext) )
{
assert( pObj == Ivy_Not(pNext) );
Vec_PtrWriteEntry( vFront, i, NULL );
Vec_PtrWriteEntry( vFront, i+1, NULL );
i++;
Counter++;
}
}
// if there are no complemented pairs, go ahead and balance
if ( Counter == 0 )
// check if the node occurs in the same polarity
for ( i = 0; i < vSuper->nSize; i++ )
if ( vSuper->pArray[i] == pObj )
return 1;
// check if the node is present in the opposite polarity
for ( i = 0; i < vSuper->nSize; i++ )
if ( vSuper->pArray[i] == Ivy_Not(pObj) )
return -1;
assert( 0 );
return 0;
// if there are complemented pairs and this is AND, create const 0
if ( Counter > 0 && Ivy_ObjIsAnd(pNode) )
}
// if the new node is complemented or a PI, another gate begins
if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1) )
{
Vec_PtrClear( vFront );
Vec_PtrPush( vFront, Ivy_ManConst0(pMan) );
Vec_PtrPush( vSuper, pObj );
Ivy_Regular(pObj)->fMarkB = 1;
return 0;
}
assert( Counter > 0 && Ivy_ObjIsExor(pNode) );
// remove the pairs
k = 0;
Vec_PtrForEachEntry( vFront, pObj, i )
if ( pObj )
Vec_PtrWriteEntry( vFront, k++, pObj );
Vec_PtrShrink( vFront, k );
// add constant zero node if nothing is left
if ( Vec_PtrSize(vFront) == 0 )
Vec_PtrPush( vFront, Ivy_ManConst0(pMan) );
// return 1 if the number of pairs is odd (need to complement the output)
return Counter & 1;
assert( !Ivy_IsComplement(pObj) );
assert( Ivy_ObjIsNode(pObj) );
// go through the branches
RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper );
RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper );
if ( RetValue1 == -1 || RetValue2 == -1 )
return -1;
// return 1 if at least one branch has a duplicate
return RetValue1 || RetValue2;
}
/**Function*************************************************************
Synopsis [Collects the nodes of the supergate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
{
Vec_Ptr_t * vNodes;
int RetValue, i;
assert( !Ivy_IsComplement(pObj) );
// extend the storage
if ( Vec_VecSize( vStore ) <= Level )
Vec_VecPush( vStore, Level, 0 );
// get the temporary array of nodes
vNodes = Vec_VecEntry( vStore, Level );
Vec_PtrClear( vNodes );
// collect the nodes in the implication supergate
RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes );
assert( vNodes->nSize > 1 );
// unmark the visited nodes
Vec_PtrForEachEntry( vNodes, pObj, i )
Ivy_Regular(pObj)->fMarkB = 0;
// if we found the node and its complement in the same implication supergate,
// return empty set of nodes (meaning that we should use constant-0 node)
if ( RetValue == -1 )
vNodes->nSize = 0;
return vNodes;
}
/**Function*************************************************************
......@@ -270,27 +278,27 @@ int Ivy_NodeBalancePrepare( Ivy_Obj_t * pNode, Vec_Ptr_t * vFront, Vec_Ptr_t * v
***********************************************************************/
int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
{
Ivy_Obj_t * pNodeRight, * pNodeLeft;
Ivy_Obj_t * pObjRight, * pObjLeft;
int Current;
// if two or less nodes, pair with the first
if ( Vec_PtrSize(vSuper) < 3 )
return 0;
// set the pointer to the one before the last
Current = Vec_PtrSize(vSuper) - 2;
pNodeRight = Vec_PtrEntry( vSuper, Current );
pObjRight = Vec_PtrEntry( vSuper, Current );
// go through the nodes to the left of this one
for ( Current--; Current >= 0; Current-- )
{
// get the next node on the left
pNodeLeft = Vec_PtrEntry( vSuper, Current );
pObjLeft = Vec_PtrEntry( vSuper, Current );
// if the level of this node is different, quit the loop
if ( Ivy_Regular(pNodeLeft)->Level != Ivy_Regular(pNodeRight)->Level )
if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level )
break;
}
Current++;
// get the node, for which the equality holds
pNodeLeft = Vec_PtrEntry( vSuper, Current );
assert( Ivy_Regular(pNodeLeft)->Level == Ivy_Regular(pNodeRight)->Level );
pObjLeft = Vec_PtrEntry( vSuper, Current );
assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level );
return Current;
}
......@@ -306,9 +314,9 @@ int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
SeeAlso []
***********************************************************************/
void Ivy_NodeBalancePermute( Ivy_Man_t * pMan, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
void Ivy_NodeBalancePermute( Vec_Ptr_t * vSuper, int LeftBound, int fExor )
{
Ivy_Obj_t * pNode1, * pNode2, * pNode3, * pGhost;
Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
int RightBound, i;
// get the right bound
RightBound = Vec_PtrSize(vSuper) - 2;
......@@ -316,19 +324,19 @@ void Ivy_NodeBalancePermute( Ivy_Man_t * pMan, Vec_Ptr_t * vSuper, int LeftBound
if ( LeftBound == RightBound )
return;
// get the two last nodes
pNode1 = Vec_PtrEntry( vSuper, RightBound + 1 );
pNode2 = Vec_PtrEntry( vSuper, RightBound );
pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 );
pObj2 = Vec_PtrEntry( vSuper, RightBound );
// find the first node that can be shared
for ( i = RightBound; i >= LeftBound; i-- )
{
pNode3 = Vec_PtrEntry( vSuper, i );
pGhost = Ivy_ObjCreateGhost( pNode1, pNode3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE );
pObj3 = Vec_PtrEntry( vSuper, i );
pGhost = Ivy_ObjCreateGhost( pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE );
if ( Ivy_TableLookup( pGhost ) )
{
if ( pNode3 == pNode2 )
if ( pObj3 == pObj2 )
return;
Vec_PtrWriteEntry( vSuper, i, pNode2 );
Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
Vec_PtrWriteEntry( vSuper, i, pObj2 );
Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
return;
}
}
......@@ -336,11 +344,11 @@ void Ivy_NodeBalancePermute( Ivy_Man_t * pMan, Vec_Ptr_t * vSuper, int LeftBound
// we did not find the node to share, randomize choice
{
int Choice = rand() % (RightBound - LeftBound + 1);
pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
if ( pNode3 == pNode2 )
pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
if ( pObj3 == pObj2 )
return;
Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 );
Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
}
*/
}
......@@ -356,61 +364,22 @@ void Ivy_NodeBalancePermute( Ivy_Man_t * pMan, Vec_Ptr_t * vSuper, int LeftBound
SeeAlso []
***********************************************************************/
void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vFront, Ivy_Obj_t * pNode )
void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj )
{
Ivy_Obj_t * pNode1, * pNode2;
Ivy_Obj_t * pObj1, * pObj2;
int i;
if ( Vec_PtrPushUnique(vFront, pNode) )
if ( Vec_PtrPushUnique(vStore, pObj) )
return;
// find the p of the node
for ( i = vFront->nSize-1; i > 0; i-- )
for ( i = vStore->nSize-1; i > 0; i-- )
{
pNode1 = vFront->pArray[i ];
pNode2 = vFront->pArray[i-1];
if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level )
pObj1 = vStore->pArray[i ];
pObj2 = vStore->pArray[i-1];
if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level )
break;
vFront->pArray[i ] = pNode2;
vFront->pArray[i-1] = pNode1;
}
}
/**Function*************************************************************
Synopsis [Balances one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_NodeBalance( Ivy_Obj_t * pNode, int fUpdateLevel, Vec_Ptr_t * vFront, Vec_Ptr_t * vSpots )
{
Ivy_Man_t * pMan = Ivy_ObjMan( pNode );
Ivy_Obj_t * pFan0, * pFan1, * pNodeNew;
int fCompl, LeftBound;
// remove internal nodes and derive the frontier
fCompl = Ivy_NodeBalancePrepare( pNode, vFront, vSpots );
assert( Vec_PtrSize(vFront) > 0 );
// balance the nodes
while ( Vec_PtrSize(vFront) > 1 )
{
// find the left bound on the node to be paired
LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vFront );
// find the node that can be shared (if no such node, randomize choice)
Ivy_NodeBalancePermute( pMan, vFront, LeftBound, Ivy_ObjIsExor(pNode) );
// pull out the last two nodes
pFan0 = Vec_PtrPop(vFront); assert( !Ivy_ObjIsConst1(Ivy_Regular(pFan0)) );
pFan1 = Vec_PtrPop(vFront); assert( !Ivy_ObjIsConst1(Ivy_Regular(pFan1)) );
// create the new node
pNodeNew = Ivy_ObjCreate( Ivy_ObjCreateGhost(pFan0, pFan1, Ivy_ObjType(pNode), IVY_INIT_NONE) );
// add the new node to the frontier
Ivy_NodeBalancePushUniqueOrderByLevel( vFront, pNodeNew );
vStore->pArray[i ] = pObj2;
vStore->pArray[i-1] = pObj1;
}
assert( Vec_PtrSize(vFront) == 1 );
// perform the replacement
Ivy_ObjReplace( pNode, Ivy_NotCond(Vec_PtrPop(vFront), fCompl), 1, 1 );
}
......
......@@ -200,180 +200,6 @@ void Ivy_ManSeqFindCut( Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInsi
/**Function*************************************************************
Synopsis [Comparison for node pointers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
{
if ( *pp1 < *pp2 )
return -1;
if ( *pp1 > *pp2 )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Computing one algebraic cut.]
Description [Returns 1 if the tree-leaves of this node where traversed
and found to have no external references (and have not been collected).
Returns 0 if the tree-leaves have external references and are collected.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pRoot, Ivy_Type_t Type, Vec_Ptr_t * vFront )
{
int RetValue0, RetValue1;
Ivy_Obj_t * pRootR = Ivy_Regular(pRoot);
assert( Type != IVY_EXOR || !Ivy_IsComplement(pRoot) );
// if the node is a buffer skip through it
if ( Ivy_ObjIsBuf(pRootR) )
return Ivy_ManFindAlgCut_rec( Ivy_NotCond(Ivy_ObjChild0(pRootR), Ivy_IsComplement(pRoot)), Type, vFront );
// if the node is the end of the tree, return
if ( Ivy_IsComplement(pRoot) || Ivy_ObjIsCi(pRoot) || Ivy_ObjType(pRoot) != Type )
{
if ( Ivy_ObjRefs(pRootR) == 1 )
return 1;
assert( Ivy_ObjRefs(pRootR) > 1 );
Vec_PtrPush( vFront, pRoot );
return 0;
}
// branch on the node
assert( Ivy_ObjIsNode(pRoot) );
RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjChild0(pRoot), Type, vFront );
RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjChild1(pRoot), Type, vFront );
// the case when both have no external referenced
if ( RetValue0 && RetValue1 )
{
if ( Ivy_ObjRefs(pRoot) == 1 )
return 1;
assert( Ivy_ObjRefs(pRoot) > 1 );
Vec_PtrPush( vFront, pRoot );
return 0;
}
// the case when one of them has external references
if ( RetValue0 )
Vec_PtrPush( vFront, Ivy_ObjChild0(pRoot) );
if ( RetValue1 )
Vec_PtrPush( vFront, Ivy_ObjChild1(pRoot) );
return 0;
}
/**Function*************************************************************
Synopsis [Computing one algebraic cut.]
Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge,
(c) boundary of different gates. Returns 1 if this is a pure tree.
Returns -1 if the contant 0 is detected. Return 0 if the array can be used.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront )
{
Ivy_Obj_t * pObj, * pPrev;
int RetValue, i, k;
assert( !Ivy_IsComplement(pRoot) );
// clear the frontier and collect the nodes
Vec_PtrClear( vFront );
RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront );
// return if the node is the root of a tree
if ( RetValue == 1 )
return 1;
// sort the entries to in increasing order
Vec_PtrSort( vFront, Ivy_ManFindAlgCutCompare );
// remove duplicated
k = 1;
Vec_PtrForEachEntryStart( vFront, pObj, i, 1 )
{
pPrev = (k == 0 ? NULL : Vec_PtrEntry(vFront, k-1));
if ( pObj == pPrev )
{
if ( Ivy_ObjIsExor(pRoot) )
k--;
continue;
}
if ( pObj == Ivy_Not(pPrev) )
return -1;
Vec_PtrWriteEntry( vFront, k++, pObj );
}
if ( k == 0 )
return -1;
Vec_PtrShrink( vFront, k );
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManTestCutsAlg( Ivy_Man_t * p )
{
Vec_Ptr_t * vFront;
Ivy_Obj_t * pObj, * pTemp;
int i, k, RetValue;
vFront = Vec_PtrAlloc( 100 );
Ivy_ManForEachObj( p, pObj, i )
{
if ( !Ivy_ObjIsNode(pObj) )
continue;
if ( Ivy_ObjIsMuxType(pObj) )
{
printf( "m " );
continue;
}
if ( pObj->Id == 509 )
{
int y = 0;
}
RetValue = Ivy_ManFindAlgCut( pObj, vFront );
if ( Ivy_ObjIsExor(pObj) )
printf( "x" );
if ( RetValue == -1 )
printf( "Const0 " );
else if ( RetValue == 1 || Vec_PtrSize(vFront) <= 2 )
printf( ". " );
else
printf( "%d ", Vec_PtrSize(vFront) );
printf( "( " );
Vec_PtrForEachEntry( vFront, pTemp, k )
printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) );
printf( ")\n" );
if ( Vec_PtrSize(vFront) == 5 )
{
int x = 0;
}
}
printf( "\n" );
Vec_PtrFree( vFront );
}
/**Function*************************************************************
......@@ -639,8 +465,8 @@ int Ivy_ManFindBoolCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolu
void Ivy_ManTestCutsBool( Ivy_Man_t * p )
{
Vec_Ptr_t * vFront, * vVolume, * vLeaves;
Ivy_Obj_t * pObj, * pTemp;
int i, k, RetValue;
Ivy_Obj_t * pObj;//, * pTemp;
int i, RetValue;//, k;
vFront = Vec_PtrAlloc( 100 );
vVolume = Vec_PtrAlloc( 100 );
vLeaves = Vec_PtrAlloc( 100 );
......@@ -673,6 +499,376 @@ void Ivy_ManTestCutsBool( Ivy_Man_t * p )
Vec_PtrFree( vLeaves );
}
/**Function*************************************************************
Synopsis [Find the hash value of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut )
{
int i;
// for ( i = 1; i < pCut->nSize; i++ )
// assert( pCut->pArray[i-1] < pCut->pArray[i] );
pCut->uHash = 0;
for ( i = 0; i < pCut->nSize; i++ )
pCut->uHash |= (1 << (pCut->pArray[i] % 31));
return pCut->uHash;
}
/**Function*************************************************************
Synopsis [Removes one node to the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld )
{
int i, k;
for ( i = k = 0; i < pCut->nSize; i++ )
if ( pCut->pArray[i] != iOld )
pCut->pArray[k++] = pCut->pArray[i];
assert( k == pCut->nSize - 1 );
pCut->nSize--;
}
/**Function*************************************************************
Synopsis [Adds one node to the cut.]
Description [Returns 1 if the cuts is still okay.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew )
{
int i;
for ( i = 0; i < pCut->nSize; i++ )
if ( pCut->pArray[i] == iNew )
return 1;
// check if there is room
if ( pCut->nSize == pCut->nSizeMax )
return 0;
// add the new one
for ( i = pCut->nSize - 1; i >= 0; i-- )
if ( pCut->pArray[i] > iNew )
pCut->pArray[i+1] = pCut->pArray[i];
else
{
assert( pCut->pArray[i] < iNew );
break;
}
pCut->pArray[i+1] = iNew;
pCut->nSize++;
return 1;
}
/**Function*************************************************************
Synopsis [Check if the cut exists.]
Description [Returns 1 if the cut exists.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
{
Ivy_Cut_t * pCut;
int i, k;
assert( pCutNew->uHash );
// try to find the cut
for ( i = 0; i < pCutStore->nCuts; i++ )
{
pCut = pCutStore->pCuts + i;
if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize )
{
for ( k = 0; k < pCutNew->nSize; k++ )
if ( pCut->pArray[k] != pCutNew->pArray[k] )
break;
if ( k == pCutNew->nSize )
return 1;
}
}
assert( pCutStore->nCuts < pCutStore->nCutsMax );
// add the cut
pCut = pCutStore->pCuts + pCutStore->nCuts++;
*pCut = *pCutNew;
return 0;
}
/**Function*************************************************************
Synopsis [Returns 1 if pDom is contained in pCut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut )
{
int i, k;
for ( i = 0; i < pDom->nSize; i++ )
{
for ( k = 0; k < pCut->nSize; k++ )
if ( pDom->pArray[i] == pCut->pArray[k] )
break;
if ( k == pCut->nSize ) // node i in pDom is not contained in pCut
return 0;
}
// every node in pDom is contained in pCut
return 1;
}
/**Function*************************************************************
Synopsis [Check if the cut exists.]
Description [Returns 1 if the cut exists.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew )
{
Ivy_Cut_t * pCut;
int i, k;
assert( pCutNew->uHash );
// try to find the cut
for ( i = 0; i < pCutStore->nCuts; i++ )
{
pCut = pCutStore->pCuts + i;
if ( pCut->nSize == 0 )
continue;
if ( pCut->nSize == pCutNew->nSize )
{
if ( pCut->uHash == pCutNew->uHash )
{
for ( k = 0; k < pCutNew->nSize; k++ )
if ( pCut->pArray[k] != pCutNew->pArray[k] )
break;
if ( k == pCutNew->nSize )
return 1;
}
continue;
}
if ( pCut->nSize < pCutNew->nSize )
{
// skip the non-contained cuts
if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash )
continue;
// check containment seriously
if ( Ivy_CutCheckDominance( pCut, pCutNew ) )
return 1;
continue;
}
// check potential containment of other cut
// skip the non-contained cuts
if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash )
continue;
// check containment seriously
if ( Ivy_CutCheckDominance( pCutNew, pCut ) )
{
// remove the current cut
// --pCutStore->nCuts;
// for ( k = i; k < pCutStore->nCuts; k++ )
// pCutStore->pCuts[k] = pCutStore->pCuts[k+1];
// i--;
pCut->nSize = 0;
}
}
assert( pCutStore->nCuts < pCutStore->nCutsMax );
// add the cut
pCut = pCutStore->pCuts + pCutStore->nCuts++;
*pCut = *pCutNew;
return 0;
}
/**Function*************************************************************
Synopsis [Print the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore )
{
Ivy_Cut_t * pCut;
int i, k;
for ( i = k = 0; i < pCutStore->nCuts; i++ )
{
pCut = pCutStore->pCuts + i;
if ( pCut->nSize == 0 )
continue;
pCutStore->pCuts[k++] = *pCut;
}
pCutStore->nCuts = k;
}
/**Function*************************************************************
Synopsis [Print the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_NodePrintCut( Ivy_Cut_t * pCut )
{
int i;
assert( pCut->nSize > 0 );
printf( "%d : {", pCut->nSize );
for ( i = 0; i < pCut->nSize; i++ )
printf( " %d", pCut->pArray[i] );
printf( " }\n" );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore )
{
int i;
printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] );
for ( i = 0; i < pCutStore->nCuts; i++ )
Ivy_NodePrintCut( pCutStore->pCuts + i );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Obj_t * pObj, int nLeaves )
{
static Ivy_Store_t CutStore, * pCutStore = &CutStore;
Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut;
Ivy_Man_t * pMan = Ivy_ObjMan(pObj);
Ivy_Obj_t * pLeaf;
int i, k;
assert( nLeaves <= IVY_CUT_INPUT );
// start the structure
pCutStore->nCuts = 0;
pCutStore->nCutsMax = IVY_CUT_LIMIT;
// start the trivial cut
pCutNew->uHash = 0;
pCutNew->nSize = 1;
pCutNew->nSizeMax = nLeaves;
pCutNew->pArray[0] = pObj->Id;
Ivy_NodeCutHash( pCutNew );
// add the trivial cut
Ivy_NodeCutFindOrAdd( pCutStore, pCutNew );
assert( pCutStore->nCuts == 1 );
// explore the cuts
for ( i = 0; i < pCutStore->nCuts; i++ )
{
// expand this cut
pCut = pCutStore->pCuts + i;
if ( pCut->nSize == 0 )
continue;
for ( k = 0; k < pCut->nSize; k++ )
{
pLeaf = Ivy_ObjObj( pObj, pCut->pArray[k] );
if ( Ivy_ObjIsCi(pLeaf) )
continue;
*pCutNew = *pCut;
Ivy_NodeCutShrink( pCutNew, pLeaf->Id );
if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) )
continue;
if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) )
continue;
Ivy_NodeCutHash( pCutNew );
Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew );
if ( pCutStore->nCuts == IVY_CUT_LIMIT )
break;
}
if ( pCutStore->nCuts == IVY_CUT_LIMIT )
break;
}
Ivy_NodeCompactCuts( pCutStore );
// Ivy_NodePrintCuts( pCutStore );
return pCutStore;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManTestCutsAll( Ivy_Man_t * p )
{
Ivy_Obj_t * pObj;
int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver;
int clk = clock();
nNodeTotal = nNodeOver = 0;
nCutsTotal = -Ivy_ManNodeNum(p);
Ivy_ManForEachObj( p, pObj, i )
{
if ( !Ivy_ObjIsNode(pObj) )
continue;
nCutsCut = Ivy_NodeFindCutsAll( pObj, 4 )->nCuts;
nCutsTotal += nCutsCut;
nNodeOver += (nCutsCut == IVY_CUT_LIMIT);
nNodeTotal++;
}
printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ",
nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver );
PRT( "Time", clock() - clk );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -69,6 +69,9 @@ Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p )
Vec_Int_t * vNodes;
Ivy_Obj_t * pObj;
int i;
// make sure the nodes are not marked
Ivy_ManForEachObj( p, pObj, i )
assert( !pObj->fMarkA && !pObj->fMarkB );
// collect the nodes
vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) );
if ( Ivy_ManLatchNum(p) > 0 )
......@@ -107,7 +110,7 @@ void Ivy_ManDfsExt_rec( Ivy_Obj_t * pObj, Vec_Int_t * vNodes )
// traverse the fanins
vFanins = Ivy_ObjGetFanins( pObj );
Vec_IntForEachEntry( vFanins, Fanin, i )
Ivy_ManDfsExt_rec( Ivy_ObjObj(pObj, Ivy_FanId(Fanin)), vNodes );
Ivy_ManDfsExt_rec( Ivy_ObjObj(pObj, Ivy_EdgeId(Fanin)), vNodes );
// add the node
Vec_IntPush( vNodes, pObj->Id );
}
......@@ -134,7 +137,7 @@ Vec_Int_t * Ivy_ManDfsExt( Ivy_Man_t * p )
vNodes = Vec_IntAlloc( 10 );
Ivy_ManForEachPo( p, pObj, i )
{
pFanin = Ivy_ManObj( p, Ivy_FanId( Ivy_ObjReadFanin(pObj,0) ) );
pFanin = Ivy_ManObj( p, Ivy_EdgeId( Ivy_ObjReadFanin(pObj,0) ) );
Ivy_ManDfsExt_rec( pFanin, vNodes );
}
Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
......@@ -145,6 +148,132 @@ Vec_Int_t * Ivy_ManDfsExt( Ivy_Man_t * p )
return vNodes;
}
/**Function*************************************************************
Synopsis [Collects nodes in the cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone )
{
if ( pObj->fMarkA )
return;
if ( Ivy_ObjIsBuf(pObj) )
{
Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone );
Vec_PtrPush( vCone, pObj );
return;
}
assert( Ivy_ObjIsNode(pObj) );
Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone );
Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone );
Vec_PtrPushUnique( vCone, pObj );
}
/**Function*************************************************************
Synopsis [Collects nodes in the cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone )
{
Ivy_Obj_t * pTemp;
int i;
assert( !Ivy_IsComplement(pObj) );
assert( Ivy_ObjIsNode(pObj) );
// mark the nodes
Vec_PtrForEachEntry( vFront, pTemp, i )
Ivy_Regular(pTemp)->fMarkA = 1;
assert( pObj->fMarkA == 0 );
// collect the cone
Vec_PtrClear( vCone );
Ivy_ManCollectCone_rec( pObj, vCone );
// unmark the nodes
Vec_PtrForEachEntry( vFront, pTemp, i )
Ivy_Regular(pTemp)->fMarkA = 0;
}
/**Function*************************************************************
Synopsis [Returns the nodes by level.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p )
{
Vec_Vec_t * vNodes;
Ivy_Obj_t * pObj;
int i;
vNodes = Vec_VecAlloc( 100 );
Ivy_ManForEachObj( p, pObj, i )
{
assert( !Ivy_ObjIsBuf(pObj) );
if ( Ivy_ObjIsNode(pObj) )
Vec_VecPush( vNodes, pObj->Level, pObj );
}
return vNodes;
}
/**Function*************************************************************
Synopsis [Computes required levels for each node.]
Description [Assumes topological ordering of the nodes.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p )
{
Ivy_Obj_t * pObj;
Vec_Int_t * vLevelsR;
Vec_Vec_t * vNodes;
int i, k, Level, LevelMax;
assert( p->vRequired == NULL );
// start the required times
vLevelsR = Vec_IntStart( Ivy_ManObjIdNext(p) );
// iterate through the nodes in the reverse order
vNodes = Ivy_ManLevelize( p );
Vec_VecForEachEntryReverseReverse( vNodes, pObj, i, k )
{
Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj);
if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level )
Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level );
if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level )
Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level );
}
Vec_VecFree( vNodes );
// convert it into the required times
LevelMax = Ivy_ManReadLevels( p );
//printf( "max %5d\n",LevelMax );
Ivy_ManForEachObj( p, pObj, i )
{
Level = Vec_IntEntry( vLevelsR, pObj->Id );
Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level );
//printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level );
}
p->vRequired = vLevelsR;
return vLevelsR;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -48,6 +48,7 @@ Ivy_Man_t * Ivy_ManStart( int nPis, int nPos, int nNodesMax )
p = ALLOC( Ivy_Man_t, 1 );
memset( p, 0, sizeof(Ivy_Man_t) );
p->nTravIds = 1;
p->fCatchExor = 1;
// AIG nodes
p->nObjsAlloc = 1 + nPis + nPos + nNodesMax;
// p->nObjsAlloc += (p->nObjsAlloc & 1); // make it even
......@@ -191,12 +192,13 @@ void Ivy_ManPrintStats( Ivy_Man_t * p )
{
printf( "A = %d. ", Ivy_ManAndNum(p) );
printf( "X = %d. ", Ivy_ManExorNum(p) );
printf( "B = %d. ", Ivy_ManBufNum(p) );
printf( "B = %4d. ", Ivy_ManBufNum(p) );
}
printf( "MaxID = %d. ", p->ObjIdNext-1 );
printf( "All = %d. ", p->nObjsAlloc );
// printf( "MaxID = %d. ", p->ObjIdNext-1 );
// printf( "All = %d. ", p->nObjsAlloc );
printf( "Cre = %d. ", p->nCreated );
printf( "Del = %d. ", p->nDeleted );
printf( "Lev = %d. ", Ivy_ManReadLevels(p) );
printf( "\n" );
}
......
......@@ -24,22 +24,18 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Ivy_Eval_t_ Ivy_Eval_t;
struct Ivy_Eval_t_
#define IVY_EVAL_LIMIT 128
typedef struct Ivy_Eva_t_ Ivy_Eva_t;
struct Ivy_Eva_t_
{
unsigned Mask : 5; // the mask of covered nodes
unsigned Weight : 3; // the number of covered nodes
unsigned Cost : 4; // the number of overlapping nodes
unsigned Level : 12; // the level of this node
unsigned Fan0 : 4; // the first fanin
unsigned Fan1 : 4; // the second fanin
Ivy_Obj_t * pArg; // the argument node
unsigned Mask; // the mask of covered nodes
int Weight; // the number of covered nodes
};
static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs );
static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode );
static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
static void Ivy_MultiPrint( Ivy_Eva_t * pEvals, int nLeaves, int nEvals );
static int Ivy_MultiCover( Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
......@@ -47,212 +43,121 @@ static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type
/**Function*************************************************************
Synopsis [Constructs the well-balanced tree of gates.]
Description [Disregards levels and possible logic sharing.]
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type )
{
Ivy_Obj_t * pObj1, * pObj2;
if ( nObjs == 1 )
return ppObjs[0];
pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type );
pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type );
return Ivy_Oper( pObj1, pObj2, Type );
}
/**Function*************************************************************
Synopsis [Constructs a balanced tree while taking sharing into account.]
Description []
Description [Returns 1 if the implementation exists.]
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type )
int Ivy_MultiPlus( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols )
{
static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5};
static Ivy_Eval_t pEvals[15+15*14/2];
static Ivy_Obj_t * pArgs[16];
Ivy_Eval_t * pEva, * pEvaBest;
int nArgsNew, nEvals, i, k;
Ivy_Obj_t * pTemp;
// consider the case of one argument
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgsInit[0];
// consider the case of two arguments
if ( nArgs == 2 )
return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type );
//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" );
// set the initial ones
for ( i = 0; i < nArgs; i++ )
static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT];
Ivy_Eva_t * pEval, * pFan0, * pFan1;
Ivy_Obj_t * pObj, * pTemp;
int nEvals, nEvalsOld, i, k, x, nLeaves;
unsigned uMaskAll;
// consider special cases
nLeaves = Vec_PtrSize(vLeaves);
assert( nLeaves > 2 );
if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT )
return 0;
// if ( nLeaves == 1 )
// return Vec_PtrEntry( vLeaves, 0 );
// if ( nLeaves == 2 )
// return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type );
// set the leaf entries
uMaskAll = ((1 << nLeaves) - 1);
nEvals = 0;
Vec_PtrForEachEntry( vLeaves, pObj, i )
{
pArgs[i] = pArgsInit[i];
pEva = pEvals + i;
pEva->Mask = (1 << i);
pEva->Weight = 1;
pEva->Cost = 0;
pEva->Level = Ivy_Regular(pArgs[i])->Level;
pEva->Fan0 = 0;
pEva->Fan1 = 0;
pEval = pEvals + nEvals;
pEval->pArg = pObj;
pEval->Mask = (1 << nEvals);
pEval->Weight = 1;
// mark the leaf
Ivy_Regular(pObj)->TravId = nEvals;
nEvals++;
}
// find the available nodes
pEvaBest = pEvals;
nArgsNew = nArgs;
for ( i = 1; i < nArgsNew; i++ )
for ( k = 0; k < i; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) )
{
pEva = pEvals + nArgsNew;
pEva->Mask = pEvals[k].Mask | pEvals[i].Mask;
pEva->Weight = NumBits[pEva->Mask];
pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask];
pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level);
pEva->Fan0 = k;
pEva->Fan1 = i;
// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) );
// compare
if ( pEvaBest->Weight < pEva->Weight ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
pEvaBest = pEva;
// save the argument
pArgs[nArgsNew++] = pTemp;
if ( nArgsNew == 15 )
goto Outside;
}
Outside:
// printf( "Best = %d.\n", pEvaBest - pEvals );
// the case of no common nodes
if ( nArgsNew == nArgs )
// propagate masks through the cone
Vec_PtrForEachEntry( vCone, pObj, i )
{
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
pObj->TravId = nEvals + i;
if ( Ivy_ObjIsBuf(pObj) )
pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask;
else
pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask;
}
// the case of one common node
if ( nArgsNew == nArgs + 1 )
// set the internal entries
Vec_PtrForEachEntry( vCone, pObj, i )
{
assert( pEvaBest - pEvals == nArgs );
k = 0;
for ( i = 0; i < nArgs; i++ )
if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 )
pArgs[k++] = pArgs[i];
pArgs[k++] = pArgs[nArgs];
assert( k == nArgs - 1 );
nArgs = k;
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
if ( i == Vec_PtrSize(vCone) - 1 )
break;
// skip buffers
if ( Ivy_ObjIsBuf(pObj) )
continue;
// skip nodes without external fanout
if ( Ivy_ObjRefs(pObj) == 0 )
continue;
assert( !Ivy_IsComplement(pObj) );
pEval = pEvals + nEvals;
pEval->pArg = pObj;
pEval->Mask = pEvals[pObj->TravId].Mask;
pEval->Weight = Extra_WordCountOnes(pEval->Mask);
// mark the node
pObj->TravId = nEvals;
nEvals++;
}
// the case when there is a node that covers everything
if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) )
return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
// evaluate node pairs
nEvals = nArgsNew;
for ( i = 1; i < nArgsNew; i++ )
// find the available nodes
nEvalsOld = nEvals;
for ( i = 1; i < nEvals; i++ )
for ( k = 0; k < i; k++ )
{
pEva = pEvals + nEvals;
pEva->Mask = pEvals[k].Mask | pEvals[i].Mask;
pEva->Weight = NumBits[pEva->Mask];
pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask];
pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level);
pEva->Fan0 = k;
pEva->Fan1 = i;
// compare
if ( pEvaBest->Weight < pEva->Weight ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
pEvaBest = pEva;
pFan0 = pEvals + i;
pFan1 = pEvals + k;
pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE));
// skip nodes in the cone
if ( pTemp == NULL || pTemp->fMarkB )
continue;
// skip the leaves
for ( x = 0; x < nLeaves; x++ )
if ( pTemp == Ivy_Regular(vLeaves->pArray[x]) )
break;
if ( x < nLeaves )
continue;
pEval = pEvals + nEvals;
pEval->pArg = pTemp;
pEval->Mask = pFan0->Mask | pFan1->Mask;
pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight;
// save the argument
pObj->TravId = nEvals;
nEvals++;
// quit if the number of entries exceeded the limit
if ( nEvals == IVY_EVAL_LIMIT )
goto Outside;
// quit if we found an acceptable implementation
if ( pEval->Mask == uMaskAll )
goto Outside;
}
assert( pEvaBest - pEvals >= nArgsNew );
// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 );
// get the best implementation
pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
// collect those not covered by EvaBest
k = 0;
for ( i = 0; i < nArgs; i++ )
if ( (pEvaBest->Mask & (1 << i)) == 0 )
pArgs[k++] = pArgs[i];
pArgs[k++] = pTemp;
assert( k == nArgs - (int)pEvaBest->Weight + 1 );
nArgs = k;
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
/**Function*************************************************************
Synopsis [Implements multi-input AND/EXOR operation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pNode0, * pNode1;
if ( iNum < nArgs )
return pArgs[iNum];
pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type );
pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type );
return Ivy_Oper( pNode0, pNode1, Type );
}
/**Function*************************************************************
Synopsis [Selection-sorts the nodes in the decreasing over of level.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs )
{
Ivy_Obj_t * pTemp;
int i, j, iBest;
Outside:
for ( i = 0; i < nArgs-1; i++ )
{
iBest = i;
for ( j = i+1; j < nArgs; j++ )
if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level )
iBest = j;
pTemp = pArgs[i];
pArgs[i] = pArgs[iBest];
pArgs[iBest] = pTemp;
}
// Ivy_MultiPrint( pEvals, nLeaves, nEvals );
if ( !Ivy_MultiCover( pEvals, nLeaves, nEvals, nLimit, vSols ) )
return 0;
assert( Vec_PtrSize( vSols ) > 0 );
return 1;
}
/**Function*************************************************************
Synopsis [Inserts a new node in the order by levels.]
Synopsis [Computes how many uncovered ones this one covers.]
Description []
......@@ -261,32 +166,28 @@ void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs )
SeeAlso []
***********************************************************************/
int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode )
void Ivy_MultiPrint( Ivy_Eva_t * pEvals, int nLeaves, int nEvals )
{
Ivy_Obj_t * pNode1, * pNode2;
int i;
// try to find the node in the array
for ( i = 0; i < nArgs; i++ )
if ( pArray[i] == pNode )
return nArgs;
// put the node last
pArray[nArgs++] = pNode;
// find the place to put the new node
for ( i = nArgs-1; i > 0; i-- )
Ivy_Eva_t * pEval;
int i, k;
for ( i = nLeaves; i < nEvals; i++ )
{
pNode1 = pArray[i ];
pNode2 = pArray[i-1];
if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level )
break;
pArray[i ] = pNode2;
pArray[i-1] = pNode1;
pEval = pEvals + i;
printf( "%2d (id = %5d) : |", i-nLeaves, Ivy_ObjId(pEval->pArg) );
for ( k = 0; k < nLeaves; k++ )
{
if ( pEval->Mask & (1 << k) )
printf( "+" );
else
printf( " " );
}
printf( "| Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) );
}
return nArgs;
}
/**Function*************************************************************
Synopsis [Balances the array recursively.]
Synopsis [Computes how many uncovered ones this one covers.]
Description []
......@@ -295,129 +196,102 @@ int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t *
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound )
{
Ivy_Obj_t * pNodeNew;
// consider the case of one argument
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgs[0];
// consider the case of two arguments
if ( nArgs == 2 )
return Ivy_Oper( pArgs[0], pArgs[1], Type );
// get the last two nodes
pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type );
// add the new node
nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
assert( uMask & ~uFound );
if ( (uMask & uFound) == 0 )
return nMaskOnes;
return Extra_WordCountOnes( uMask & ~uFound );
}
/**Function*************************************************************
Synopsis [Implements multi-input AND/EXOR operation.]
Synopsis [Finds the cover.]
Description []
Description [Returns 1 if the cover is found.]
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
int Ivy_MultiCover( Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols )
{
Ivy_Obj_t * pTemp;
int i, k;
int nArgsOld = nArgs;
for ( i = 0; i < nArgs; i++ )
printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level );
for ( i = 1; i < nArgs; i++ )
for ( k = 0; k < i; k++ )
int fVerbose = 0;
Ivy_Eva_t * pEval, * pEvalBest;
unsigned uMaskAll, uFound, uTemp;
int i, k, BestK, WeightBest, WeightCur, LevelBest, LevelCur;
uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1);
uFound = 0;
// solve the covering problem
if ( fVerbose )
printf( "Solution: " );
Vec_PtrClear( vSols );
for ( i = 0; i < nLimit; i++ )
{
BestK = -1;
for ( k = nEvals - 1; k >= 0; k-- )
{
pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE));
if ( pTemp != NULL )
pEval = pEvals + k;
if ( (pEval->Mask & ~uFound) == 0 )
continue;
if ( BestK == -1 )
{
printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i );
pArgs[nArgs++] = pTemp;
BestK = k;
pEvalBest = pEval;
WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound );
LevelBest = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) );
continue;
}
// compare BestK and the new one (k)
WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound );
LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) );
if ( WeightBest < WeightCur ||
(WeightBest == WeightCur && LevelBest > LevelCur) )
{
BestK = k;
pEvalBest = pEval;
WeightBest = WeightCur;
LevelBest = LevelCur;
}
}
printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld );
return NULL;
}
/**Function*************************************************************
Synopsis [Old code.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pArgsRef[5], * pTemp;
int i, k, m, nArgsNew, Counter = 0;
//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" );
assert( Type == IVY_AND || Type == IVY_EXOR );
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgs[0];
// find the nodes with more than one fanout
nArgsNew = 0;
for ( i = 0; i < nArgs; i++ )
if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 )
pArgsRef[nArgsNew++] = pArgs[i];
// go through pairs
if ( nArgsNew >= 2 )
for ( i = 0; i < nArgsNew; i++ )
for ( k = i + 1; k < nArgsNew; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
Counter++;
// printf( "%d", Counter );
// go through pairs
if ( nArgsNew >= 2 )
for ( i = 0; i < nArgsNew; i++ )
for ( k = i + 1; k < nArgsNew; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
assert( BestK != -1 );
// if the cost is only 1, take the leaf
if ( WeightBest == 1 && BestK >= nLeaves )
{
nArgsNew = 0;
for ( m = 0; m < nArgs; m++ )
if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] )
pArgs[nArgsNew++] = pArgs[m];
pArgs[nArgsNew++] = pTemp;
assert( nArgsNew == nArgs - 1 );
return Ivy_Multi1( pArgs, nArgsNew, Type );
uTemp = (pEvalBest->Mask & ~uFound);
for ( k = 0; k < nLeaves; k++ )
if ( uTemp & (1 << k) )
break;
assert( k < nLeaves );
BestK = k;
pEvalBest = pEvals + BestK;
}
return Ivy_Multi_rec( pArgs, nArgs, Type );
}
/**Function*************************************************************
Synopsis [Old code.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
assert( Type == IVY_AND || Type == IVY_EXOR );
assert( nArgs > 0 );
return Ivy_Multi_rec( pArgs, nArgs, Type );
if ( fVerbose )
{
if ( BestK < nLeaves )
printf( "L(%d) ", BestK );
else
printf( "%d ", BestK - nLeaves );
}
// update the found set
Vec_PtrPush( vSols, pEvalBest->pArg );
uFound |= pEvalBest->Mask;
if ( uFound == uMaskAll )
break;
}
if ( uFound == uMaskAll )
{
if ( fVerbose )
printf( " Found \n\n" );
return 1;
}
else
{
if ( fVerbose )
printf( " Not found \n\n" );
return 0;
}
}
////////////////////////////////////////////////////////////////////////
......
/**CFile****************************************************************
FileName [ivyMulti.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [And-Inverter Graph package.]
Synopsis [Constructing multi-input AND/EXOR gates.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - May 11, 2006.]
Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ivy.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Ivy_Eval_t_ Ivy_Eval_t;
struct Ivy_Eval_t_
{
unsigned Mask : 5; // the mask of covered nodes
unsigned Weight : 3; // the number of covered nodes
unsigned Cost : 4; // the number of overlapping nodes
unsigned Level : 12; // the level of this node
unsigned Fan0 : 4; // the first fanin
unsigned Fan1 : 4; // the second fanin
};
static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs );
static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode );
static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Constructs the well-balanced tree of gates.]
Description [Disregards levels and possible logic sharing.]
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type )
{
Ivy_Obj_t * pObj1, * pObj2;
if ( nObjs == 1 )
return ppObjs[0];
pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type );
pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type );
return Ivy_Oper( pObj1, pObj2, Type );
}
/**Function*************************************************************
Synopsis [Constructs a balanced tree while taking sharing into account.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type )
{
static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5};
static Ivy_Eval_t pEvals[15+15*14/2];
static Ivy_Obj_t * pArgs[16];
Ivy_Eval_t * pEva, * pEvaBest;
int nArgsNew, nEvals, i, k;
Ivy_Obj_t * pTemp;
// consider the case of one argument
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgsInit[0];
// consider the case of two arguments
if ( nArgs == 2 )
return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type );
//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" );
// set the initial ones
for ( i = 0; i < nArgs; i++ )
{
pArgs[i] = pArgsInit[i];
pEva = pEvals + i;
pEva->Mask = (1 << i);
pEva->Weight = 1;
pEva->Cost = 0;
pEva->Level = Ivy_Regular(pArgs[i])->Level;
pEva->Fan0 = 0;
pEva->Fan1 = 0;
}
// find the available nodes
pEvaBest = pEvals;
nArgsNew = nArgs;
for ( i = 1; i < nArgsNew; i++ )
for ( k = 0; k < i; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) )
{
pEva = pEvals + nArgsNew;
pEva->Mask = pEvals[k].Mask | pEvals[i].Mask;
pEva->Weight = NumBits[pEva->Mask];
pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask];
pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level);
pEva->Fan0 = k;
pEva->Fan1 = i;
// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) );
// compare
if ( pEvaBest->Weight < pEva->Weight ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
pEvaBest = pEva;
// save the argument
pArgs[nArgsNew++] = pTemp;
if ( nArgsNew == 15 )
goto Outside;
}
Outside:
// printf( "Best = %d.\n", pEvaBest - pEvals );
// the case of no common nodes
if ( nArgsNew == nArgs )
{
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
// the case of one common node
if ( nArgsNew == nArgs + 1 )
{
assert( pEvaBest - pEvals == nArgs );
k = 0;
for ( i = 0; i < nArgs; i++ )
if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 )
pArgs[k++] = pArgs[i];
pArgs[k++] = pArgs[nArgs];
assert( k == nArgs - 1 );
nArgs = k;
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
// the case when there is a node that covers everything
if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) )
return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
// evaluate node pairs
nEvals = nArgsNew;
for ( i = 1; i < nArgsNew; i++ )
for ( k = 0; k < i; k++ )
{
pEva = pEvals + nEvals;
pEva->Mask = pEvals[k].Mask | pEvals[i].Mask;
pEva->Weight = NumBits[pEva->Mask];
pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask];
pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level);
pEva->Fan0 = k;
pEva->Fan1 = i;
// compare
if ( pEvaBest->Weight < pEva->Weight ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
pEvaBest = pEva;
// save the argument
nEvals++;
}
assert( pEvaBest - pEvals >= nArgsNew );
// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 );
// get the best implementation
pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
// collect those not covered by EvaBest
k = 0;
for ( i = 0; i < nArgs; i++ )
if ( (pEvaBest->Mask & (1 << i)) == 0 )
pArgs[k++] = pArgs[i];
pArgs[k++] = pTemp;
assert( k == nArgs - (int)pEvaBest->Weight + 1 );
nArgs = k;
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
/**Function*************************************************************
Synopsis [Implements multi-input AND/EXOR operation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pNode0, * pNode1;
if ( iNum < nArgs )
return pArgs[iNum];
pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type );
pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type );
return Ivy_Oper( pNode0, pNode1, Type );
}
/**Function*************************************************************
Synopsis [Selection-sorts the nodes in the decreasing over of level.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs )
{
Ivy_Obj_t * pTemp;
int i, j, iBest;
for ( i = 0; i < nArgs-1; i++ )
{
iBest = i;
for ( j = i+1; j < nArgs; j++ )
if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level )
iBest = j;
pTemp = pArgs[i];
pArgs[i] = pArgs[iBest];
pArgs[iBest] = pTemp;
}
}
/**Function*************************************************************
Synopsis [Inserts a new node in the order by levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode )
{
Ivy_Obj_t * pNode1, * pNode2;
int i;
// try to find the node in the array
for ( i = 0; i < nArgs; i++ )
if ( pArray[i] == pNode )
return nArgs;
// put the node last
pArray[nArgs++] = pNode;
// find the place to put the new node
for ( i = nArgs-1; i > 0; i-- )
{
pNode1 = pArray[i ];
pNode2 = pArray[i-1];
if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level )
break;
pArray[i ] = pNode2;
pArray[i-1] = pNode1;
}
return nArgs;
}
/**Function*************************************************************
Synopsis [Balances the array recursively.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pNodeNew;
// consider the case of one argument
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgs[0];
// consider the case of two arguments
if ( nArgs == 2 )
return Ivy_Oper( pArgs[0], pArgs[1], Type );
// get the last two nodes
pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type );
// add the new node
nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
/**Function*************************************************************
Synopsis [Implements multi-input AND/EXOR operation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pTemp;
int i, k;
int nArgsOld = nArgs;
for ( i = 0; i < nArgs; i++ )
printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level );
for ( i = 1; i < nArgs; i++ )
for ( k = 0; k < i; k++ )
{
pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE));
if ( pTemp != NULL )
{
printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i );
pArgs[nArgs++] = pTemp;
}
}
printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld );
return NULL;
}
/**Function*************************************************************
Synopsis [Old code.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pArgsRef[5], * pTemp;
int i, k, m, nArgsNew, Counter = 0;
//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" );
assert( Type == IVY_AND || Type == IVY_EXOR );
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgs[0];
// find the nodes with more than one fanout
nArgsNew = 0;
for ( i = 0; i < nArgs; i++ )
if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 )
pArgsRef[nArgsNew++] = pArgs[i];
// go through pairs
if ( nArgsNew >= 2 )
for ( i = 0; i < nArgsNew; i++ )
for ( k = i + 1; k < nArgsNew; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
Counter++;
// printf( "%d", Counter );
// go through pairs
if ( nArgsNew >= 2 )
for ( i = 0; i < nArgsNew; i++ )
for ( k = i + 1; k < nArgsNew; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
{
nArgsNew = 0;
for ( m = 0; m < nArgs; m++ )
if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] )
pArgs[nArgsNew++] = pArgs[m];
pArgs[nArgsNew++] = pTemp;
assert( nArgsNew == nArgs - 1 );
return Ivy_Multi1( pArgs, nArgsNew, Type );
}
return Ivy_Multi_rec( pArgs, nArgs, Type );
}
/**Function*************************************************************
Synopsis [Old code.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
assert( Type == IVY_AND || Type == IVY_EXOR );
assert( nArgs > 0 );
return Ivy_Multi_rec( pArgs, nArgs, Type );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -51,6 +51,7 @@ Ivy_Obj_t * Ivy_ObjCreate( Ivy_Obj_t * pGhost )
// realloc the node array
if ( p->ObjIdNext == p->nObjsAlloc )
{
printf( "AIG manager is being resized. In the current release, it is not allowed!\n" );
Ivy_ManGrow( p );
pGhost = Ivy_ManGhost( p );
}
......
......@@ -81,7 +81,7 @@ Ivy_Obj_t * Ivy_Oper( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type )
Ivy_Obj_t * Ivy_And( Ivy_Obj_t * p0, Ivy_Obj_t * p1 )
{
Ivy_Obj_t * pConst1 = Ivy_ObjConst1(Ivy_Regular(p0));
Ivy_Obj_t * pFan0, * pFan1;
// Ivy_Obj_t * pFan0, * pFan1;
// check trivial cases
if ( p0 == p1 )
return p0;
......@@ -92,8 +92,8 @@ Ivy_Obj_t * Ivy_And( Ivy_Obj_t * p0, Ivy_Obj_t * p1 )
if ( Ivy_Regular(p1) == pConst1 )
return p1 == pConst1 ? p0 : Ivy_Not(pConst1);
// check if it can be an EXOR gate
if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) )
return Ivy_CanonExor( pFan0, pFan1 );
// if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) )
// return Ivy_CanonExor( pFan0, pFan1 );
return Ivy_CanonAnd( p0, p1 );
}
......
/**CFile****************************************************************
FileName [ivyResyn.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [And-Inverter Graph package.]
Synopsis [AIG rewriting script.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - May 11, 2006.]
Revision [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ivy.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs several passes of rewriting on the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel )
{
int clk, fVerbose = 0;
Ivy_Man_t * pTemp;
if ( fVerbose ) Ivy_ManPrintStats( pMan );
clk = clock();
pMan = Ivy_ManBalance( pMan, fUpdateLevel );
if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
if ( fVerbose ) Ivy_ManPrintStats( pMan );
// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 );
clk = clock();
Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 );
if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
if ( fVerbose ) Ivy_ManPrintStats( pMan );
clk = clock();
pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
Ivy_ManStop( pTemp );
if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
if ( fVerbose ) Ivy_ManPrintStats( pMan );
// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 );
clk = clock();
if ( fVerbose ) Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 );
if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
if ( fVerbose ) Ivy_ManPrintStats( pMan );
clk = clock();
pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
Ivy_ManStop( pTemp );
if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
if ( fVerbose ) Ivy_ManPrintStats( pMan );
// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 );
clk = clock();
Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 );
if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); }
if ( fVerbose ) Ivy_ManPrintStats( pMan );
clk = clock();
pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel );
Ivy_ManStop( pTemp );
if ( fVerbose ) { PRT( "Balance", clock() - clk ); }
if ( fVerbose ) Ivy_ManPrintStats( pMan );
return pMan;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [ivyRwrAlg.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [And-Inverter Graph package.]
Synopsis [Algebraic AIG rewriting.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - May 11, 2006.]
Revision [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ivy.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone );
static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost );
static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Algebraic AIG rewriting.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost )
{
Vec_Int_t * vRequired;
Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol;
Ivy_Obj_t * pObj, * pResult;
int i, RetValue, LevelR, nNodesOld;
int CountUsed, CountUndo;
vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL;
vFront = Vec_PtrAlloc( 100 );
vLeaves = Vec_PtrAlloc( 100 );
vCone = Vec_PtrAlloc( 100 );
vSol = Vec_PtrAlloc( 100 );
// go through the nodes in the topological order
CountUsed = CountUndo = 0;
nNodesOld = Ivy_ManObjIdNext(p);
Ivy_ManForEachObj( p, pObj, i )
{
assert( !Ivy_ObjIsBuf(pObj) );
if ( i >= nNodesOld )
break;
// skip no-nodes and MUX roots
if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) )
continue;
// if ( pObj->Id > 297 ) // 296 --- 297
// break;
if ( pObj->Id == 297 )
{
int x = 0;
}
// get the largest algebraic cut
RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone );
// the case of a trivial tree cut
if ( RetValue == 1 )
continue;
// the case of constant 0 cone
if ( RetValue == -1 )
{
Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0 );
continue;
}
assert( Vec_PtrSize(vLeaves) > 2 );
// get the required level for this node
LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000;
// create a new cone
pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost );
if ( pResult == NULL || pResult == pObj )
continue;
assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) );
if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 )
Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++;
else
Ivy_ObjReplace( pObj, pResult, 1, 0 ), CountUsed++;
}
printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo );
Vec_PtrFree( vFront );
Vec_PtrFree( vCone );
Vec_PtrFree( vSol );
if ( vRequired ) Vec_IntFree( vRequired );
if ( i = Ivy_ManCleanup(p) )
printf( "Cleanup after rewriting removed %d dangling nodes.\n", i );
if ( !Ivy_ManCheck(p) )
printf( "Ivy_ManRewriteAlg(): The check has failed.\n" );
return 1;
}
/**Function*************************************************************
Synopsis [Analizes one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost )
{
int fVerbose = 0;
Ivy_Obj_t * pTemp;
int k, Counter, nMffc, RetValue;
if ( fVerbose )
{
if ( Ivy_ObjIsExor(pObj) )
printf( "x " );
else
printf( " " );
}
/*
printf( "%d ", Vec_PtrSize(vFront) );
printf( "( " );
Vec_PtrForEachEntry( vFront, pTemp, k )
printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) );
printf( ")\n" );
*/
// collect nodes in the cone
if ( Ivy_ObjIsExor(pObj) )
Ivy_ManCollectCone( pObj, vFront, vCone );
else
Ivy_ManCollectCone( pObj, vLeaves, vCone );
// deref nodes in the cone
Vec_PtrForEachEntry( vCone, pTemp, k )
{
Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) );
Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) );
pTemp->fMarkB = 1;
}
// count the MFFC size
Vec_PtrForEachEntry( vFront, pTemp, k )
Ivy_Regular(pTemp)->fMarkA = 1;
nMffc = Ivy_NodeCountMffc( pObj );
Vec_PtrForEachEntry( vFront, pTemp, k )
Ivy_Regular(pTemp)->fMarkA = 0;
if ( fVerbose )
{
Counter = 0;
Vec_PtrForEachEntry( vCone, pTemp, k )
Counter += (Ivy_ObjRefs(pTemp) > 0);
printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d. Mffc = %d. Lev = %d. LevR = %d.\n",
pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR );
}
/*
printf( "Leaves:" );
Vec_PtrForEachEntry( vLeaves, pTemp, k )
printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" );
printf( "\n" );
printf( "Cone:\n" );
Vec_PtrForEachEntry( vCone, pTemp, k )
printf( " %5d = %d%s %d%s\n", pTemp->Id,
Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "",
Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" );
*/
RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols );
// ref nodes in the cone
Vec_PtrForEachEntry( vCone, pTemp, k )
{
Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) );
Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) );
pTemp->fMarkA = 0;
pTemp->fMarkB = 0;
}
if ( !RetValue )
return NULL;
if ( Vec_PtrSize( vSols ) == 1 )
return Vec_PtrEntry( vSols, 0 );
return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 );
}
/**Function*************************************************************
Synopsis [Comparison for node pointers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode )
{
if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA )
return 0;
assert( pNode->fMarkB );
pNode->fMarkA = 1;
// printf( "%d ", pNode->Id );
if ( Ivy_ObjIsBuf(pNode) )
return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) );
return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) );
}
/**Function*************************************************************
Synopsis [Comparison for node pointers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_NodeCountMffc( Ivy_Obj_t * pNode )
{
assert( pNode->fMarkB );
return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) );
}
/**Function*************************************************************
Synopsis [Comparison for node pointers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 )
{
if ( *pp1 < *pp2 )
return -1;
if ( *pp1 > *pp2 )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Computing one algebraic cut.]
Description [Returns 1 if the tree-leaves of this node where traversed
and found to have no external references (and have not been collected).
Returns 0 if the tree-leaves have external references and are collected.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone )
{
int RetValue0, RetValue1;
Ivy_Obj_t * pObjR = Ivy_Regular(pObj);
assert( !Ivy_ObjIsBuf(pObjR) );
assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) );
// make sure the node is not visited twice in different polarities
if ( Ivy_IsComplement(pObj) )
{ // if complemented, mark B
if ( pObjR->fMarkA )
return -1;
pObjR->fMarkB = 1;
}
else
{ // if non-complicated, mark A
if ( pObjR->fMarkB )
return -1;
pObjR->fMarkA = 1;
}
Vec_PtrPush( vCone, pObjR );
// if the node is the end of the tree, return
if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type )
{
if ( Ivy_ObjRefs(pObjR) == 1 )
return 1;
assert( Ivy_ObjRefs(pObjR) > 1 );
Vec_PtrPush( vFront, pObj );
return 0;
}
// branch on the node
assert( !Ivy_IsComplement(pObj) );
assert( Ivy_ObjIsNode(pObj) );
// what if buffer has more than one fanout???
RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone );
RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone );
if ( RetValue0 == -1 || RetValue1 == -1 )
return -1;
// the case when both have no external references
if ( RetValue0 && RetValue1 )
{
if ( Ivy_ObjRefs(pObj) == 1 )
return 1;
assert( Ivy_ObjRefs(pObj) > 1 );
Vec_PtrPush( vFront, pObj );
return 0;
}
// the case when one of them has external references
if ( RetValue0 )
Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) );
if ( RetValue1 )
Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) );
return 0;
}
/**Function*************************************************************
Synopsis [Computing one algebraic cut.]
Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge,
(c) boundary of different gates. Returns 1 if this is a pure tree.
Returns -1 if the contant 0 is detected. Return 0 if the array can be used.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone )
{
Ivy_Obj_t * pObj, * pPrev;
int RetValue, i;
assert( !Ivy_IsComplement(pRoot) );
assert( Ivy_ObjIsNode(pRoot) );
// clear the frontier and collect the nodes
Vec_PtrClear( vCone );
Vec_PtrClear( vFront );
Vec_PtrClear( vLeaves );
RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone );
// clean the marks
Vec_PtrForEachEntry( vCone, pObj, i )
pObj->fMarkA = pObj->fMarkB = 0;
// quit if the same node is found in both polarities
if ( RetValue == -1 )
return -1;
// return if the node is the root of a tree
if ( RetValue == 1 )
return 1;
// return if the cut is composed of two nodes
if ( Vec_PtrSize(vFront) <= 2 )
return 1;
// sort the entries in increasing order
Vec_PtrSort( vFront, Ivy_ManFindAlgCutCompare );
// remove duplicates from vFront and save the nodes in vLeaves
pPrev = Vec_PtrEntry(vFront, 0);
Vec_PtrPush( vLeaves, pPrev );
Vec_PtrForEachEntryStart( vFront, pObj, i, 1 )
{
// compare current entry and the previous entry
if ( pObj == pPrev )
{
if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0
{
// vLeaves are no longer structural support of pRoot!!!
Vec_PtrPop(vLeaves);
pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves);
}
continue;
}
if ( pObj == Ivy_Not(pPrev) )
{
assert( Ivy_ObjIsAnd(pRoot) );
return -1;
}
pPrev = pObj;
Vec_PtrPush( vLeaves, pObj );
}
if ( Vec_PtrSize(vLeaves) == 0 )
return -1;
if ( Vec_PtrSize(vLeaves) <= 2 )
return 1;
return 0;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [ivyRwtPre.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [And-Inverter Graph package.]
Synopsis [Rewriting based on precomputation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - May 11, 2006.]
Revision [$Id: ivyRwtPre.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ivy.h"
#include "deco.h"
#include "rwt.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums );
static int Ivy_NodeMffcLabel( Ivy_Obj_t * pObj );
static int Rwt_NodeRewrite( Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost );
static Dec_Graph_t * Rwt_CutEvaluate( Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut,
Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth );
static int Ivy_GraphToNetworkCount( Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
static void Ivy_GraphUpdateNetwork( Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs incremental rewriting of the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose )
{
Rwt_Man_t * pManRwt;
Ivy_Obj_t * pNode;
int i, nNodes, nGain;
int clk, clkStart = clock();
// start the rewriting manager
pManRwt = Rwt_ManStart( 0 );
if ( pManRwt == NULL )
return 0;
// compute the reverse levels if level update is requested
if ( fUpdateLevel )
Ivy_ManRequiredLevels( p );
// resynthesize each node once
nNodes = Ivy_ManObjIdNext( p );
Ivy_ManForEachObj( p, pNode, i )
{
if ( !Ivy_ObjIsNode(pNode) )
continue;
// fix the fanin buffer problem
Ivy_NodeFixBufferFanins( pNode );
if ( Ivy_ObjIsBuf(pNode) )
continue;
// stop if all nodes have been tried once
if ( i >= nNodes )
break;
// skip the nodes with many fanouts
// if ( Ivy_ObjRefs(pNode) > 1000 )
// continue;
// for each cut, try to resynthesize it
nGain = Rwt_NodeRewrite( pManRwt, pNode, fUpdateLevel, fUseZeroCost );
if ( nGain > 0 || nGain == 0 && fUseZeroCost )
{
Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt);
int fCompl = Rwt_ManReadCompl(pManRwt);
/*
{
Ivy_Obj_t * pObj;
int i;
printf( "USING: (" );
Vec_PtrForEachEntry( Rwt_ManReadLeaves(pManRwt), pObj, i )
printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) );
printf( ") Gain = %d.\n", nGain );
}
if ( nGain > 0 )
{ // print stats on the MFFC
extern void Ivy_NodeMffsConeSuppPrint( Ivy_Obj_t * pNode );
printf( "Node %6d : Gain = %4d ", pNode->Id, nGain );
Ivy_NodeMffsConeSuppPrint( pNode );
}
*/
// complement the FF if needed
clk = clock();
if ( fCompl ) Dec_GraphComplement( pGraph );
Ivy_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain );
if ( fCompl ) Dec_GraphComplement( pGraph );
Rwt_ManAddTimeUpdate( pManRwt, clock() - clk );
}
}
Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart );
// print stats
if ( fVerbose )
Rwt_ManPrintStats( pManRwt );
// delete the managers
Rwt_ManStop( pManRwt );
// fix the levels
if ( fUpdateLevel )
Vec_IntFree( p->vRequired ), p->vRequired = NULL;
// check
if ( i = Ivy_ManCleanup(p) )
printf( "Cleanup after rewriting removed %d dangling nodes.\n", i );
if ( !Ivy_ManCheck(p) )
printf( "Ivy_ManRewritePre(): The check has failed.\n" );
return 1;
}
/**Function*************************************************************
Synopsis [Performs rewriting for one node.]
Description [This procedure considers all the cuts computed for the node
and tries to rewrite each of them using the "forest" of different AIG
structures precomputed and stored in the RWR manager.
Determines the best rewriting and computes the gain in the number of AIG
nodes in the final network. In the end, p->vFanins contains information
about the best cut that can be used for rewriting, while p->pGraph gives
the decomposition dag (represented using decomposition graph data structure).
Returns gain in the number of nodes or -1 if node cannot be rewritten.]
SideEffects []
SeeAlso []
***********************************************************************/
int Rwt_NodeRewrite( Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost )
{
int fVeryVerbose = 0;
Dec_Graph_t * pGraph;
Ivy_Store_t * pStore;
Ivy_Cut_t * pCut;
Ivy_Obj_t * pFanin;
unsigned uPhase, uTruthBest, uTruth;
char * pPerm;
int Required, nNodesSaved, nNodesSaveCur;
int i, c, GainCur, GainBest = -1;
int clk, clk2;
p->nNodesConsidered++;
// get the required times
Required = fUpdateLevel? Vec_IntEntry( Ivy_ObjMan(pNode)->vRequired, pNode->Id ) : 1000000;
// get the node's cuts
clk = clock();
pStore = Ivy_NodeFindCutsAll( pNode, 5 );
p->timeCut += clock() - clk;
// go through the cuts
clk = clock();
for ( c = 1; c < pStore->nCuts; c++ )
{
pCut = pStore->pCuts + c;
// consider only 4-input cuts
if ( pCut->nSize != 4 )
continue;
// skip the cuts with buffers
for ( i = 0; i < (int)pCut->nSize; i++ )
if ( Ivy_ObjIsBuf( Ivy_ObjObj(pNode, pCut->pArray[i]) ) )
break;
if ( i != pCut->nSize )
continue;
// if ( pNode->Id == 82 )
// Ivy_NodePrintCut( pCut );
// get the fanin permutation
clk2 = clock();
uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize ); // truth table
p->timeTruth += clock() - clk2;
pPerm = p->pPerms4[ p->pPerms[uTruth] ];
uPhase = p->pPhases[uTruth];
// collect fanins with the corresponding permutation/phase
Vec_PtrClear( p->vFaninsCur );
Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 );
for ( i = 0; i < (int)pCut->nSize; i++ )
{
pFanin = Ivy_ObjObj( pNode, pCut->pArray[pPerm[i]] );
assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) );
pFanin = Ivy_NotCond(pFanin, ((uPhase & (1<<i)) > 0) );
Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin );
}
clk2 = clock();
/*
printf( "Considering: (" );
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) );
printf( ")\n" );
*/
// mark the fanin boundary
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
Ivy_ObjRefsInc( Ivy_Regular(pFanin) );
// label MFFC with current ID
Ivy_ManIncrementTravId( Ivy_ObjMan(pNode) );
nNodesSaved = Ivy_NodeMffcLabel( pNode );
// unmark the fanin boundary
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
Ivy_ObjRefsDec( Ivy_Regular(pFanin) );
p->timeMffc += clock() - clk2;
// evaluate the cut
clk2 = clock();
pGraph = Rwt_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth );
p->timeEval += clock() - clk2;
// check if the cut is better than the current best one
if ( pGraph != NULL && GainBest < GainCur )
{
// save this form
nNodesSaveCur = nNodesSaved;
GainBest = GainCur;
p->pGraph = pGraph;
p->fCompl = ((uPhase & (1<<4)) > 0);
uTruthBest = uTruth;
// collect fanins in the
Vec_PtrClear( p->vFanins );
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
Vec_PtrPush( p->vFanins, pFanin );
}
}
p->timeRes += clock() - clk;
if ( GainBest == -1 )
return -1;
// printf( "%d", nNodesSaveCur - GainBest );
/*
if ( GainBest > 0 )
{
if ( Rwt_CutIsintean( pNode, p->vFanins ) )
printf( "b" );
else
{
printf( "Node %d : ", pNode->Id );
Vec_PtrForEachEntry( p->vFanins, pFanin, i )
printf( "%d ", Ivy_Regular(pFanin)->Id );
printf( "a" );
}
}
*/
/*
if ( GainBest > 0 )
if ( p->fCompl )
printf( "c" );
else
printf( "." );
*/
// copy the leaves
Vec_PtrForEachEntry( p->vFanins, pFanin, i )
Dec_GraphNode(p->pGraph, i)->pFunc = pFanin;
p->nScores[p->pMap[uTruthBest]]++;
p->nNodesGained += GainBest;
if ( fUseZeroCost || GainBest > 0 )
p->nNodesRewritten++;
// report the progress
if ( fVeryVerbose && GainBest > 0 )
{
printf( "Node %6d : ", Ivy_ObjId(pNode) );
printf( "Fanins = %d. ", p->vFanins->nSize );
printf( "Save = %d. ", nNodesSaveCur );
printf( "Add = %d. ", nNodesSaveCur-GainBest );
printf( "GAIN = %d. ", GainBest );
printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 );
printf( "Class = %d. ", p->pMap[uTruthBest] );
printf( "\n" );
}
return GainBest;
}
/**Function*************************************************************
Synopsis [References/references the node and returns MFFC size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_NodeRefDeref( Ivy_Obj_t * pNode, int fReference, int fLabel )
{
Ivy_Obj_t * pNode0, * pNode1;
int Counter;
// label visited nodes
if ( fLabel )
Ivy_ObjSetTravIdCurrent( pNode );
// skip the CI
if ( Ivy_ObjIsCi(pNode) )
return 0;
assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) );
// process the internal node
pNode0 = Ivy_ObjFanin0(pNode);
pNode1 = Ivy_ObjFanin1(pNode);
Counter = Ivy_ObjIsNode(pNode);
if ( fReference )
{
if ( pNode0->nRefs++ == 0 )
Counter += Ivy_NodeRefDeref( pNode0, fReference, fLabel );
if ( Ivy_ObjIsNode(pNode) && pNode1->nRefs++ == 0 )
Counter += Ivy_NodeRefDeref( pNode1, fReference, fLabel );
}
else
{
assert( pNode0->nRefs > 0 );
assert( pNode1->nRefs > 0 );
if ( --pNode0->nRefs == 0 )
Counter += Ivy_NodeRefDeref( pNode0, fReference, fLabel );
if ( Ivy_ObjIsNode(pNode) && --pNode1->nRefs == 0 )
Counter += Ivy_NodeRefDeref( pNode1, fReference, fLabel );
}
return Counter;
}
/**Function*************************************************************
Synopsis [Computes the size of MFFC and labels nodes with the current TravId.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_NodeMffcLabel( Ivy_Obj_t * pNode )
{
int nConeSize1, nConeSize2;
assert( !Ivy_IsComplement( pNode ) );
assert( Ivy_ObjIsNode( pNode ) );
nConeSize1 = Ivy_NodeRefDeref( pNode, 0, 1 ); // dereference
nConeSize2 = Ivy_NodeRefDeref( pNode, 1, 0 ); // reference
assert( nConeSize1 == nConeSize2 );
assert( nConeSize1 > 0 );
return nConeSize1;
}
/**Function*************************************************************
Synopsis [Computes the truth table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums )
{
static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
unsigned uTruth0, uTruth1;
int i;
for ( i = 0; i < nNums; i++ )
if ( pObj->Id == pNums[i] )
return uMasks[i];
assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) );
uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums );
if ( Ivy_ObjFaninC0(pObj) )
uTruth0 = ~uTruth0;
if ( Ivy_ObjIsBuf(pObj) )
return uTruth0;
uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums );
if ( Ivy_ObjFaninC1(pObj) )
uTruth1 = ~uTruth1;
return uTruth0 & uTruth1;
}
/**Function*************************************************************
Synopsis [Computes the truth table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums )
{
assert( nNums < 6 );
return Ivy_NodeGetTruth_rec( pObj, pNums, nNums );
}
/**Function*************************************************************
Synopsis [Evaluates the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Graph_t * Rwt_CutEvaluate( Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth )
{
Vec_Ptr_t * vSubgraphs;
Dec_Graph_t * pGraphBest, * pGraphCur;
Rwt_Node_t * pNode, * pFanin;
int nNodesAdded, GainBest, i, k;
// find the matching class of subgraphs
vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
p->nSubgraphs += vSubgraphs->nSize;
// determine the best subgraph
GainBest = -1;
Vec_PtrForEachEntry( vSubgraphs, pNode, i )
{
// get the current graph
pGraphCur = (Dec_Graph_t *)pNode->pNext;
// copy the leaves
Vec_PtrForEachEntry( vFaninsCur, pFanin, k )
Dec_GraphNode(pGraphCur, k)->pFunc = pFanin;
// detect how many unlabeled nodes will be reused
nNodesAdded = Ivy_GraphToNetworkCount( pRoot, pGraphCur, nNodesSaved, LevelMax );
if ( nNodesAdded == -1 )
continue;
assert( nNodesSaved >= nNodesAdded );
// count the gain at this node
if ( GainBest < nNodesSaved - nNodesAdded )
{
GainBest = nNodesSaved - nNodesAdded;
pGraphBest = pGraphCur;
}
}
if ( GainBest == -1 )
return NULL;
*pGainBest = GainBest;
return pGraphBest;
}
/**Function*************************************************************
Synopsis [Counts the number of new nodes added when using this graph.]
Description [AIG nodes for the fanins should be assigned to pNode->pFunc
of the leaves of the graph before calling this procedure.
Returns -1 if the number of nodes and levels exceeded the given limit or
the number of levels exceeded the maximum allowed level.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_GraphToNetworkCount( Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax )
{
Dec_Node_t * pNode, * pNode0, * pNode1;
Ivy_Obj_t * pAnd, * pAnd0, * pAnd1;
int i, Counter, LevelNew, LevelOld;
// check for constant function or a literal
if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) )
return 0;
// set the levels of the leaves
Dec_GraphForEachLeaf( pGraph, pNode, i )
pNode->Level = Ivy_Regular(pNode->pFunc)->Level;
// compute the AIG size after adding the internal nodes
Counter = 0;
Dec_GraphForEachNode( pGraph, pNode, i )
{
// get the children of this node
pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node );
pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node );
// get the AIG nodes corresponding to the children
pAnd0 = pNode0->pFunc;
pAnd1 = pNode1->pFunc;
if ( pAnd0 && pAnd1 )
{
// if they are both present, find the resulting node
pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl );
pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl );
pAnd = Ivy_TableLookup( Ivy_ObjCreateGhost(pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) );
// return -1 if the node is the same as the original root
if ( Ivy_Regular(pAnd) == pRoot )
return -1;
}
else
pAnd = NULL;
// count the number of added nodes
if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(Ivy_Regular(pAnd)) )
{
if ( ++Counter > NodeMax )
return -1;
}
// count the number of new levels
LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level );
if ( pAnd )
{
if ( Ivy_Regular(pAnd) == Ivy_ObjConst1(pRoot) )
LevelNew = 0;
else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) )
LevelNew = (int)Ivy_Regular(pAnd0)->Level;
else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) )
LevelNew = (int)Ivy_Regular(pAnd1)->Level;
LevelOld = (int)Ivy_Regular(pAnd)->Level;
// assert( LevelNew == LevelOld );
}
if ( LevelNew > LevelMax )
return -1;
pNode->pFunc = pAnd;
pNode->Level = LevelNew;
}
return Counter;
}
/**Function*************************************************************
Synopsis [Transforms the decomposition graph into the AIG.]
Description [AIG nodes for the fanins should be assigned to pNode->pFunc
of the leaves of the graph before calling this procedure.]
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * pMan, Dec_Graph_t * pGraph )
{
Ivy_Obj_t * pAnd0, * pAnd1;
Dec_Node_t * pNode;
int i;
// check for constant function
if ( Dec_GraphIsConst(pGraph) )
return Ivy_NotCond( Ivy_ManConst1(pMan), Dec_GraphIsComplement(pGraph) );
// check for a literal
if ( Dec_GraphIsVar(pGraph) )
return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
// build the AIG nodes corresponding to the AND gates of the graph
Dec_GraphForEachNode( pGraph, pNode, i )
{
pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
pNode->pFunc = Ivy_And( pAnd0, pAnd1 );
}
// complement the result if necessary
return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
}
/**Function*************************************************************
Synopsis [Replaces MFFC of the node by the new factored form.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_GraphUpdateNetwork( Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain )
{
Ivy_Obj_t * pRootNew;
int nNodesNew, nNodesOld;
nNodesOld = Ivy_ManNodeNum(Ivy_ObjMan(pRoot));
// create the new structure of nodes
pRootNew = Ivy_GraphToNetwork( Ivy_ObjMan(pRoot), pGraph );
// remove the old nodes
// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel );
Ivy_ObjReplace( pRoot, pRootNew, 1, 0 );
// compare the gains
nNodesNew = Ivy_ManNodeNum(Ivy_ObjMan(pRoot));
assert( nGain <= nNodesOld - nNodesNew );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -362,6 +362,222 @@ Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p )
return vLatches;
}
/**Function*************************************************************
Synopsis [Collect the latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_ManReadLevels( Ivy_Man_t * p )
{
Ivy_Obj_t * pObj;
int i, LevelMax = 0;
Ivy_ManForEachPo( p, pObj, i )
{
pObj = Ivy_ObjFanin0(pObj);
LevelMax = IVY_MAX( LevelMax, (int)pObj->Level );
}
return LevelMax;
}
/**Function*************************************************************
Synopsis [Returns the real fanin.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj )
{
Ivy_Obj_t * pFanin;
if ( !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) )
return pObj;
pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) );
return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) );
}
/**Function*************************************************************
Synopsis [Checks if the cube has exactly one 1.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Ivy_TruthHasOneOne( unsigned uCube )
{
return (uCube & (uCube - 1)) == 0;
}
/**Function*************************************************************
Synopsis [Checks if two cubes are distance-1.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Ivy_TruthCubesDist1( unsigned uCube1, unsigned uCube2 )
{
unsigned uTemp = uCube1 | uCube2;
return Ivy_TruthHasOneOne( (uTemp >> 1) & uTemp & 0x55555555 );
}
/**Function*************************************************************
Synopsis [Checks if two cubes differ in only one literal.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Ivy_TruthCubesDiff1( unsigned uCube1, unsigned uCube2 )
{
unsigned uTemp = uCube1 ^ uCube2;
return Ivy_TruthHasOneOne( ((uTemp >> 1) | uTemp) & 0x55555555 );
}
/**Function*************************************************************
Synopsis [Combines two distance 1 cubes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline unsigned Ivy_TruthCubesMerge( unsigned uCube1, unsigned uCube2 )
{
unsigned uTemp;
uTemp = uCube1 | uCube2;
uTemp &= (uTemp >> 1) & 0x55555555;
assert( Ivy_TruthHasOneOne(uTemp) );
uTemp |= (uTemp << 1);
return (uCube1 | uCube2) ^ uTemp;
}
/**Function*************************************************************
Synopsis [Estimates the number of AIG nodes in the truth table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_TruthEstimateNodes( unsigned * pTruth, int nVars )
{
static unsigned short uResult[256];
static unsigned short uCover[81*81];
static char pVarCount[81*81];
int nMints, uCube, uCubeNew, i, k, c, nCubes, nRes, Counter;
assert( nVars <= 8 );
// create the cover
nCubes = 0;
nMints = (1 << nVars);
for ( i = 0; i < nMints; i++ )
if ( pTruth[i/32] & (1 << (i & 31)) )
{
uCube = 0;
for ( k = 0; k < nVars; k++ )
if ( i & (1 << k) )
uCube |= (1 << ((k<<1)+1));
else
uCube |= (1 << ((k<<1)+0));
uCover[nCubes] = uCube;
pVarCount[nCubes] = nVars;
nCubes++;
// Extra_PrintBinary( stdout, &uCube, 8 ); printf( "\n" );
}
assert( nCubes <= 256 );
// reduce the cover by building larger cubes
for ( i = 1; i < nCubes; i++ )
for ( k = 0; k < i; k++ )
if ( pVarCount[i] && pVarCount[i] == pVarCount[k] && Ivy_TruthCubesDist1(uCover[i], uCover[k]) )
{
uCubeNew = Ivy_TruthCubesMerge(uCover[i], uCover[k]);
for ( c = i; c < nCubes; c++ )
if ( uCubeNew == uCover[c] )
break;
if ( c != nCubes )
continue;
uCover[nCubes] = uCubeNew;
pVarCount[nCubes] = pVarCount[i] - 1;
nCubes++;
assert( nCubes < 81*81 );
// Extra_PrintBinary( stdout, &uCubeNew, 8 ); printf( "\n" );
// c = c;
}
// compact the cover
nRes = 0;
for ( i = nCubes -1; i >= 0; i-- )
{
for ( k = 0; k < nRes; k++ )
if ( (uCover[i] & uResult[k]) == uResult[k] )
break;
if ( k != nRes )
continue;
uResult[nRes++] = uCover[i];
}
// count the number of literals
Counter = 0;
for ( i = 0; i < nRes; i++ )
{
for ( k = 0; k < nVars; k++ )
if ( uResult[i] & (3 << (k<<1)) )
Counter++;
}
return Counter;
}
/**Function*************************************************************
Synopsis [Tests the cover procedure.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_TruthEstimateNodesTest()
{
unsigned uTruth[8];
int i;
for ( i = 0; i < 8; i++ )
uTruth[i] = ~(unsigned)0;
uTruth[3] ^= (1 << 13);
// uTruth[4] = 0xFFFFF;
// uTruth[0] = 0xFF;
// uTruth[0] ^= (1 << 3);
printf( "Number = %d.\n", Ivy_TruthEstimateNodes(uTruth, 8) );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -8,7 +8,8 @@ SRC += src/temp/ivy/ivyBalance.c \
src/temp/ivy/ivyMulti.c \
src/temp/ivy/ivyObj.c \
src/temp/ivy/ivyOper.c \
src/temp/ivy/ivyRewrite.c \
src/temp/ivy/ivyResyn.c \
src/temp/ivy/ivyRwrPre.c \
src/temp/ivy/ivySeq.c \
src/temp/ivy/ivyTable.c \
src/temp/ivy/ivyUndo.c \
......
......@@ -18,13 +18,17 @@
***********************************************************************/
#include "esop.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "mem.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
struct Esop_MmFixed_t_
struct Mem_Fixed_t_
{
// information about individual entries
int nEntrySize; // the size of one entry
......@@ -44,7 +48,7 @@ struct Esop_MmFixed_t_
int nMemoryAlloc; // memory allocated
};
struct Esop_MmFlex_t_
struct Mem_Flex_t_
{
// information about individual entries
int nEntriesUsed; // the number of entries allocated
......@@ -62,14 +66,20 @@ struct Esop_MmFlex_t_
int nMemoryAlloc; // memory allocated
};
struct Esop_MmStep_t_
struct Mem_Step_t_
{
int nMems; // the number of fixed memory managers employed
Esop_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc
int nMapSize; // the size of the memory array
Esop_MmFixed_t ** pMap; // maps the number of bytes into its memory manager
int nMems; // the number of fixed memory managers employed
Mem_Fixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc
int nMapSize; // the size of the memory array
Mem_Fixed_t ** pMap; // maps the number of bytes into its memory manager
};
#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
#define REALLOC(type, obj, num) \
((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
((type *) malloc(sizeof(type) * (num))))
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -86,12 +96,12 @@ struct Esop_MmStep_t_
SeeAlso []
***********************************************************************/
Esop_MmFixed_t * Esop_MmFixedStart( int nEntrySize )
Mem_Fixed_t * Mem_FixedStart( int nEntrySize )
{
Esop_MmFixed_t * p;
Mem_Fixed_t * p;
p = ALLOC( Esop_MmFixed_t, 1 );
memset( p, 0, sizeof(Esop_MmFixed_t) );
p = ALLOC( Mem_Fixed_t, 1 );
memset( p, 0, sizeof(Mem_Fixed_t) );
p->nEntrySize = nEntrySize;
p->nEntriesAlloc = 0;
......@@ -125,7 +135,7 @@ Esop_MmFixed_t * Esop_MmFixedStart( int nEntrySize )
SeeAlso []
***********************************************************************/
void Esop_MmFixedStop( Esop_MmFixed_t * p, int fVerbose )
void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose )
{
int i;
if ( p == NULL )
......@@ -154,7 +164,7 @@ void Esop_MmFixedStop( Esop_MmFixed_t * p, int fVerbose )
SeeAlso []
***********************************************************************/
char * Esop_MmFixedEntryFetch( Esop_MmFixed_t * p )
char * Mem_FixedEntryFetch( Mem_Fixed_t * p )
{
char * pTemp;
int i;
......@@ -205,7 +215,7 @@ char * Esop_MmFixedEntryFetch( Esop_MmFixed_t * p )
SeeAlso []
***********************************************************************/
void Esop_MmFixedEntryRecycle( Esop_MmFixed_t * p, char * pEntry )
void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry )
{
// decrement the counter of used entries
p->nEntriesUsed--;
......@@ -225,7 +235,7 @@ void Esop_MmFixedEntryRecycle( Esop_MmFixed_t * p, char * pEntry )
SeeAlso []
***********************************************************************/
void Esop_MmFixedRestart( Esop_MmFixed_t * p )
void Mem_FixedRestart( Mem_Fixed_t * p )
{
int i;
char * pTemp;
......@@ -263,12 +273,288 @@ void Esop_MmFixedRestart( Esop_MmFixed_t * p )
SeeAlso []
***********************************************************************/
int Esop_MmFixedReadMemUsage( Esop_MmFixed_t * p )
int Mem_FixedReadMemUsage( Mem_Fixed_t * p )
{
return p->nMemoryAlloc;
}
/**Function*************************************************************
Synopsis [Allocates entries of flexible size.]
Description [Can only work with entry size at least 4 byte long.]
SideEffects []
SeeAlso []
***********************************************************************/
Mem_Flex_t * Mem_FlexStart()
{
Mem_Flex_t * p;
p = ALLOC( Mem_Flex_t, 1 );
memset( p, 0, sizeof(Mem_Flex_t) );
p->nEntriesUsed = 0;
p->pCurrent = NULL;
p->pEnd = NULL;
p->nChunkSize = (1 << 12);
p->nChunksAlloc = 64;
p->nChunks = 0;
p->pChunks = ALLOC( char *, p->nChunksAlloc );
p->nMemoryUsed = 0;
p->nMemoryAlloc = 0;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Mem_FlexStop( Mem_Flex_t * p, int fVerbose )
{
int i;
if ( p == NULL )
return;
if ( fVerbose )
{
printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
p->nChunkSize, p->nChunks );
printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
}
for ( i = 0; i < p->nChunks; i++ )
free( p->pChunks[i] );
free( p->pChunks );
free( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes )
{
char * pTemp;
// check if there are still free entries
if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
{ // need to allocate more entries
if ( p->nChunks == p->nChunksAlloc )
{
p->nChunksAlloc *= 2;
p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
}
if ( nBytes > p->nChunkSize )
{
// resize the chunk size if more memory is requested than it can give
// (ideally, this should never happen)
p->nChunkSize = 2 * nBytes;
}
p->pCurrent = ALLOC( char, p->nChunkSize );
p->pEnd = p->pCurrent + p->nChunkSize;
p->nMemoryAlloc += p->nChunkSize;
// add the chunk to the chunk storage
p->pChunks[ p->nChunks++ ] = p->pCurrent;
}
assert( p->pCurrent + nBytes <= p->pEnd );
// increment the counter of used entries
p->nEntriesUsed++;
// keep track of the memory used
p->nMemoryUsed += nBytes;
// return the next entry
pTemp = p->pCurrent;
p->pCurrent += nBytes;
return pTemp;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Mem_FlexReadMemUsage( Mem_Flex_t * p )
{
return p->nMemoryAlloc;
}
/**Function*************************************************************
Synopsis [Starts the hierarchical memory manager.]
Description [This manager can allocate entries of any size.
Iternally they are mapped into the entries with the number of bytes
equal to the power of 2. The smallest entry size is 8 bytes. The
next one is 16 bytes etc. So, if the user requests 6 bytes, he gets
8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
The input parameters "nSteps" says how many fixed memory managers
are employed internally. Calling this procedure with nSteps equal
to 10 results in 10 hierarchically arranged internal memory managers,
which can allocate up to 4096 (1Kb) entries. Requests for larger
entries are handed over to malloc() and then free()ed.]
SideEffects []
SeeAlso []
***********************************************************************/
Mem_Step_t * Mem_StepStart( int nSteps )
{
Mem_Step_t * p;
int i, k;
p = ALLOC( Mem_Step_t, 1 );
memset( p, 0, sizeof(Mem_Step_t) );
p->nMems = nSteps;
// start the fixed memory managers
p->pMems = ALLOC( Mem_Fixed_t *, p->nMems );
for ( i = 0; i < p->nMems; i++ )
p->pMems[i] = Mem_FixedStart( (8<<i) );
// set up the mapping of the required memory size into the corresponding manager
p->nMapSize = (4<<p->nMems);
p->pMap = ALLOC( Mem_Fixed_t *, p->nMapSize+1 );
p->pMap[0] = NULL;
for ( k = 1; k <= 4; k++ )
p->pMap[k] = p->pMems[0];
for ( i = 0; i < p->nMems; i++ )
for ( k = (4<<i)+1; k <= (8<<i); k++ )
p->pMap[k] = p->pMems[i];
//for ( i = 1; i < 100; i ++ )
//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
return p;
}
/**Function*************************************************************
Synopsis [Stops the memory manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Mem_StepStop( Mem_Step_t * p, int fVerbose )
{
int i;
for ( i = 0; i < p->nMems; i++ )
Mem_FixedStop( p->pMems[i], fVerbose );
// if ( p->pLargeChunks )
// {
// for ( i = 0; i < p->nLargeChunks; i++ )
// free( p->pLargeChunks[i] );
// free( p->pLargeChunks );
// }
free( p->pMems );
free( p->pMap );
free( p );
}
/**Function*************************************************************
Synopsis [Creates the entry.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes )
{
if ( nBytes == 0 )
return NULL;
if ( nBytes > p->nMapSize )
{
// printf( "Allocating %d bytes.\n", nBytes );
/*
if ( p->nLargeChunks == p->nLargeChunksAlloc )
{
if ( p->nLargeChunksAlloc == 0 )
p->nLargeChunksAlloc = 5;
p->nLargeChunksAlloc *= 2;
p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc );
}
p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes );
return p->pLargeChunks[ p->nLargeChunks - 1 ];
*/
return ALLOC( char, nBytes );
}
return Mem_FixedEntryFetch( p->pMap[nBytes] );
}
/**Function*************************************************************
Synopsis [Recycles the entry.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes )
{
if ( nBytes == 0 )
return;
if ( nBytes > p->nMapSize )
{
free( pEntry );
return;
}
Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Mem_StepReadMemUsage( Mem_Step_t * p )
{
int i, nMemTotal = 0;
for ( i = 0; i < p->nMems; i++ )
nMemTotal += p->pMems[i]->nMemoryAlloc;
return nMemTotal;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [mem.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Memory management.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: mem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __MEM_H__
#define __MEM_H__
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Mem_Fixed_t_ Mem_Fixed_t;
typedef struct Mem_Flex_t_ Mem_Flex_t;
typedef struct Mem_Step_t_ Mem_Step_t;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*=== mem.c ===========================================================*/
// fixed-size-block memory manager
extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize );
extern void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose );
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 );
// flexible-size-block memory manager
extern Mem_Flex_t * Mem_FlexStart();
extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose );
extern char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes );
extern int Mem_FlexReadMemUsage( Mem_Flex_t * p );
// hierarchical memory manager
extern Mem_Step_t * Mem_StepStart( int nSteps );
extern void Mem_StepStop( Mem_Step_t * p, int fVerbose );
extern char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes );
extern void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes );
extern int Mem_StepReadMemUsage( Mem_Step_t * p );
#ifdef __cplusplus
}
#endif
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
SRC += src/temp/mem/mem.c
......@@ -40,8 +40,8 @@ typedef struct Pla_Obj_t_ Pla_Obj_t;
struct Pla_Obj_t_
{
unsigned fFixed : 1; // fixed node
unsigned Depth : 7; // the depth in terms of LUTs/PLAs
unsigned nRefs : 24; // the number of references
unsigned Depth : 31; // the depth in terms of LUTs/PLAs
int nRefs; // the number of references
Vec_Int_t vSupp[2]; // supports in two frames
Esop_Cube_t * pCover[2]; // esops in two frames
};
......
......@@ -45,8 +45,10 @@ static Abc_Ntk_t * Ivy_ManToAbc( Abc_Ntk_t * pNtkOld, Ivy_Man_t * p );
***********************************************************************/
void * Abc_NtkPlayer( void * pNtk, int nLutMax, int nPlaMax, int fVerbose )
{
int fUseRewriting = 1;
Ivy_Man_t * pMan, * pManExt;
Abc_Ntk_t * pNtkAig;
if ( !Abc_NtkIsStrash(pNtk) )
return NULL;
// convert to the new AIG manager
......@@ -60,6 +62,14 @@ void * Abc_NtkPlayer( void * pNtk, int nLutMax, int nPlaMax, int fVerbose )
}
if ( fVerbose )
Ivy_ManPrintStats( pMan );
if ( fUseRewriting )
{
// simplify
pMan = Ivy_ManResyn( pManExt = pMan, 1 );
Ivy_ManStop( pManExt );
if ( fVerbose )
Ivy_ManPrintStats( pMan );
}
// perform decomposition/mapping into PLAs/LUTs
pManExt = Pla_ManDecompose( pMan, nLutMax, nPlaMax, fVerbose );
Ivy_ManStop( pMan );
......@@ -150,10 +160,10 @@ Abc_Ntk_t * Ivy_ManToAbc( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan )
pObjNew = Abc_NtkCreateNode( pNtkNew );
Vec_IntForEachEntry( vIvyFanins, Fanin, k )
{
pIvyFanin = Ivy_ObjObj( pIvyNode, Ivy_FanId(Fanin) );
pIvyFanin = Ivy_ObjObj( pIvyNode, Ivy_EdgeId(Fanin) );
pFaninNew = Abc_NtkObj( pNtkNew, pIvyFanin->TravId );
Abc_ObjAddFanin( pObjNew, pFaninNew );
pCompls[k] = Ivy_FanCompl(Fanin);
pCompls[k] = Ivy_EdgeIsComplement(Fanin);
assert( Ivy_ObjIsAndMulti(pIvyNode) || nFanins == 1 || pCompls[k] == 0 ); // EXOR/LUT cannot have complemented fanins
}
assert( k <= PLAYER_FANIN_LIMIT );
......@@ -176,10 +186,10 @@ Abc_Ntk_t * Ivy_ManToAbc( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan )
// get the old fanin of the PO node
vIvyFanins = Ivy_ObjGetFanins( Ivy_ManPo(pMan, i) );
Fanin = Vec_IntEntry( vIvyFanins, 0 );
pIvyFanin = Ivy_ManObj( pMan, Ivy_FanId(Fanin) );
pIvyFanin = Ivy_ManObj( pMan, Ivy_EdgeId(Fanin) );
// get the new ABC node corresponding to the old fanin
pFaninNew = Abc_NtkObj( pNtkNew, pIvyFanin->TravId );
if ( Ivy_FanCompl(Fanin) ) // complement
if ( Ivy_EdgeIsComplement(Fanin) ) // complement
{
// pFaninNew = Abc_NodeCreateInv(pNtkNew, pFaninNew);
if ( Abc_ObjIsCi(pFaninNew) )
......
......@@ -62,7 +62,7 @@ Ivy_Man_t * Pla_ManToAig( Ivy_Man_t * pOld )
{
pObjNew = Pla_ManToAig_rec( pNew, Ivy_ObjFanin0(pObjOld) );
Ivy_ObjStartFanins( Ivy_ManPo(pNew, i), 1 );
Ivy_ObjAddFanin( Ivy_ManPo(pNew, i), Ivy_FanCreate(pObjNew->Id, Ivy_ObjFaninC0(pObjOld)) );
Ivy_ObjAddFanin( Ivy_ManPo(pNew, i), Ivy_EdgeCreate(pObjNew->Id, Ivy_ObjFaninC0(pObjOld)) );
}
// compute the LUT functions
Pla_ManToAigLutFuncs( pNew, pOld );
......@@ -118,7 +118,7 @@ Ivy_Obj_t * Pla_ManToAig_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld )
Vec_IntForEachEntry( vSupp, Entry, i )
{
pFaninOld = Ivy_ObjObj( pObjOld, Entry );
Ivy_ObjAddFanin( Ivy_ManObj(pNew, ObjNewId), Ivy_FanCreate(pFaninOld->TravId, 0) );
Ivy_ObjAddFanin( Ivy_ManObj(pNew, ObjNewId), Ivy_EdgeCreate(pFaninOld->TravId, 0) );
}
// get the new object
pObjNew = Ivy_ManObj(pNew, ObjNewId);
......@@ -140,7 +140,7 @@ Ivy_Obj_t * Pla_ManToAig_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld )
Esop_CoverForEachCube( pCover, pCube )
{
pFaninNew = Ivy_ManToAigCube( pNew, pObjOld, pCube, vSupp );
Ivy_ObjAddFanin( Ivy_ManObj(pNew, ObjNewId), Ivy_FanCreate(pFaninNew->Id, 0) );
Ivy_ObjAddFanin( Ivy_ManObj(pNew, ObjNewId), Ivy_EdgeCreate(pFaninNew->Id, 0) );
}
// get the new object
pObjNew = Ivy_ManObj(pNew, ObjNewId);
......@@ -168,7 +168,7 @@ Ivy_Obj_t * Ivy_ManToAigConst( Ivy_Man_t * pNew, int fConst1 )
Ivy_Obj_t * pObjNew;
pObjNew = Ivy_ObjCreateExt( pNew, IVY_ANDM );
Ivy_ObjStartFanins( pObjNew, 1 );
Ivy_ObjAddFanin( pObjNew, Ivy_FanCreate(0, !fConst1) );
Ivy_ObjAddFanin( pObjNew, Ivy_EdgeCreate(0, !fConst1) );
return pObjNew;
}
......@@ -201,7 +201,7 @@ Ivy_Obj_t * Ivy_ManToAigCube( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Esop_Cube_t
if ( Value == 3 )
continue;
pFaninOld = Ivy_ObjObj( pObjOld, Vec_IntEntry(vSupp, i) );
Ivy_ObjAddFanin( pObjNew, Ivy_FanCreate( pFaninOld->TravId, Value==1 ) );
Ivy_ObjAddFanin( pObjNew, Ivy_EdgeCreate( pFaninOld->TravId, Value==1 ) );
}
assert( Ivy_ObjFaninNum(pObjNew) == (int)pCube->nLits );
return pObjNew;
......@@ -262,7 +262,7 @@ int Pla_ManToAigLutFuncs( Ivy_Man_t * pNew, Ivy_Man_t * pOld )
// point it to the constant 1 node
vFanins = Ivy_ObjGetFanins( pObjNew );
Vec_IntClear( vFanins );
Vec_IntPush( vFanins, Ivy_FanCreate(0, 1) );
Vec_IntPush( vFanins, Ivy_EdgeCreate(0, 1) );
}
memcpy( pTruth, pComputed, sizeof(unsigned) * 8 );
// Extra_PrintBinary( stdout, pTruth, 16 ); printf( "\n" );
......
......@@ -221,6 +221,7 @@ int Pla_ManDecomposeNode( Pla_Man_t * p, Ivy_Obj_t * pObj )
if ( pStr1->fFixed == 0 ) Pla_ManCountDecNodes( p, pStr1 );
pStr1->fFixed = 1;
}
assert( pStr->Depth );
// free some of the covers to save memory
assert( pStr0->nRefs > 0 );
......
......@@ -309,7 +309,7 @@ void Pla_ManComputeStats( Ivy_Man_t * p, Vec_Int_t * vNodes )
vFanins = Ivy_ObjGetFanins( pObj );
Vec_IntForEachEntry( vFanins, Fanin, k )
{
pFanin = Ivy_ManObj(p, Ivy_FanId(Fanin));
pFanin = Ivy_ManObj(p, Ivy_EdgeId(Fanin));
pObj->Level = IVY_MAX( pObj->Level, pFanin->Level );
}
pObj->Level += 1;
......@@ -335,7 +335,7 @@ void Pla_ManComputeStats( Ivy_Man_t * p, Vec_Int_t * vNodes )
Ivy_ManForEachPo( p, pObj, i )
{
Fanin = Ivy_ObjReadFanin(pObj, 0);
pFanin = Ivy_ManObj( p, Ivy_FanId(Fanin) );
pFanin = Ivy_ManObj( p, Ivy_EdgeId(Fanin) );
pObj->Level = pFanin->Level;
Delay = IVY_MAX( Delay, (int)pObj->Level );
}
......
SRC += src/temp/rwt/rwtDec.c \
src/temp/rwt/rwtMan.c \
src/temp/rwt/rwtUtil.c
/**CFile****************************************************************
FileName [rwt.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __RWT_H__
#define __RWT_H__
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include "mem.h"
#include "vec.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
#define RWT_LIMIT 1048576/4 // ((1 << 20)
#define RWT_MIN(a,b) (((a) < (b))? (a) : (b))
#define RWT_MAX(a,b) (((a) > (b))? (a) : (b))
typedef struct Rwt_Man_t_ Rwt_Man_t;
typedef struct Rwt_Node_t_ Rwt_Node_t;
struct Rwt_Man_t_
{
// internal lookups
int nFuncs; // number of four var functions
unsigned short * puCanons; // canonical forms
char * pPhases; // canonical phases
char * pPerms; // canonical permutations
unsigned char * pMap; // mapping of functions into class numbers
unsigned short * pMapInv; // mapping of classes into functions
char * pPractical; // practical NPN classes
char ** pPerms4; // four-var permutations
// node space
Vec_Ptr_t * vForest; // all the nodes
Rwt_Node_t ** pTable; // the hash table of nodes by their canonical form
Vec_Vec_t * vClasses; // the nodes of the equivalence classes
Mem_Fixed_t * pMmNode; // memory for nodes and cuts
// statistical variables
int nTravIds; // the counter of traversal IDs
int nConsidered; // the number of nodes considered
int nAdded; // the number of nodes added to lists
int nClasses; // the number of NN classes
// the result of resynthesis
int fCompl; // indicates if the output of FF should be complemented
void * pGraph; // the decomposition tree (temporary)
Vec_Ptr_t * vFanins; // the fanins array (temporary)
Vec_Ptr_t * vFaninsCur; // the fanins array (temporary)
Vec_Int_t * vLevNums; // the array of levels (temporary)
Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary)
// node statistics
int nNodesConsidered;
int nNodesRewritten;
int nNodesGained;
int nScores[222];
int nCutsGood;
int nCutsBad;
int nSubgraphs;
// runtime statistics
int timeStart;
int timeTruth;
int timeCut;
int timeRes;
int timeEval;
int timeMffc;
int timeUpdate;
int timeTotal;
};
struct Rwt_Node_t_ // 24 bytes
{
int Id; // ID
int TravId; // traversal ID
unsigned uTruth : 16; // truth table
unsigned Volume : 8; // volume
unsigned Level : 6; // level
unsigned fUsed : 1; // mark
unsigned fExor : 1; // mark
Rwt_Node_t * p0; // first child
Rwt_Node_t * p1; // second child
Rwt_Node_t * pNext; // next in the table
};
// manipulation of complemented attributes
static inline int Rwt_IsComplement( Rwt_Node_t * p ) { return (int)(((unsigned)p) & 01); }
static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned)(p) & ~01); }
static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned)(p) ^ 01); }
static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((unsigned)(p) ^ (c)); }
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== rwrDec.c ========================================================*/
extern void Rwt_ManPreprocess( Rwt_Man_t * p );
/*=== rwrMan.c ========================================================*/
extern Rwt_Man_t * Rwt_ManStart( int fPrecompute );
extern void Rwt_ManStop( Rwt_Man_t * p );
extern void Rwt_ManPrintStats( Rwt_Man_t * p );
extern void Rwt_ManPrintStatsFile( Rwt_Man_t * p );
extern void * Rwt_ManReadDecs( Rwt_Man_t * p );
extern Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p );
extern int Rwt_ManReadCompl( Rwt_Man_t * p );
extern void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time );
extern void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time );
extern void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time );
/*=== rwrUtil.c ========================================================*/
extern void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose );
extern char * Rwt_ManGetPractical( Rwt_Man_t * p );
extern Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute );
extern void Rwt_ManIncTravId( Rwt_Man_t * p );
#ifdef __cplusplus
}
#endif
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [rwtDec.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [Evaluation and decomposition procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwtDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwt.h"
#include "deco.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode );
static Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Preprocesses computed library of subgraphs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManPreprocess( Rwt_Man_t * p )
{
Dec_Graph_t * pGraph;
Rwt_Node_t * pNode;
int i, k;
// put the nodes into the structure
p->pMapInv = ALLOC( unsigned short, 222 );
memset( p->pMapInv, 0, sizeof(unsigned short) * 222 );
p->vClasses = Vec_VecStart( 222 );
for ( i = 0; i < p->nFuncs; i++ )
{
if ( p->pTable[i] == NULL )
continue;
// consider all implementations of this function
for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
{
assert( pNode->uTruth == p->pTable[i]->uTruth );
assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 );
Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode );
p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth];
}
}
// compute decomposition forms for each node and verify them
Vec_VecForEachEntry( p->vClasses, pNode, i, k )
{
pGraph = Rwt_NodePreprocess( p, pNode );
pNode->pNext = (Rwt_Node_t *)pGraph;
// assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) );
}
}
/**Function*************************************************************
Synopsis [Preprocesses subgraphs rooted at this node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode )
{
Dec_Graph_t * pGraph;
Dec_Edge_t eRoot;
assert( !Rwt_IsComplement(pNode) );
// consider constant
if ( pNode->uTruth == 0 )
return Dec_GraphCreateConst0();
// consider the case of elementary var
if ( pNode->uTruth == 0x00FF )
return Dec_GraphCreateLeaf( 3, 4, 1 );
// start the subgraphs
pGraph = Dec_GraphCreate( 4 );
// collect the nodes
Rwt_ManIncTravId( p );
eRoot = Rwt_TravCollect_rec( p, pNode, pGraph );
Dec_GraphSetRoot( pGraph, eRoot );
return pGraph;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph )
{
Dec_Edge_t eNode0, eNode1, eNode;
// elementary variable
if ( pNode->fUsed )
return Dec_EdgeCreate( pNode->Id - 1, 0 );
// previously visited node
if ( pNode->TravId == p->nTravIds )
return Dec_IntToEdge( pNode->Volume );
pNode->TravId = p->nTravIds;
// solve for children
eNode0 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p0), pGraph );
if ( Rwt_IsComplement(pNode->p0) )
eNode0.fCompl = !eNode0.fCompl;
eNode1 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p1), pGraph );
if ( Rwt_IsComplement(pNode->p1) )
eNode1.fCompl = !eNode1.fCompl;
// create the decomposition node(s)
if ( pNode->fExor )
eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 );
else
eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
// save the result
pNode->Volume = Dec_EdgeToInt( eNode );
return eNode;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [rwtMan.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [Rewriting manager.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwt.h"
#include "deco.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static unsigned short * s_puCanons = NULL;
static char * s_pPhases = NULL;
static char * s_pPerms = NULL;
static unsigned char * s_pMap = NULL;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Starts residual rewriting manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManGlobalStart()
{
if ( s_puCanons == NULL )
Extra_Truth4VarNPN( &s_puCanons, &s_pPhases, &s_pPerms, &s_pMap );
}
/**Function*************************************************************
Synopsis [Starts residual rewriting manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManGlobalStop()
{
if ( s_puCanons == NULL ) free( s_puCanons );
if ( s_pPhases == NULL ) free( s_pPhases );
if ( s_pPerms == NULL ) free( s_pPerms );
if ( s_pMap == NULL ) free( s_pMap );
}
/**Function*************************************************************
Synopsis [Starts rewriting manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwt_Man_t * Rwt_ManStart( int fPrecompute )
{
Rwt_Man_t * p;
int clk = clock();
clk = clock();
p = ALLOC( Rwt_Man_t, 1 );
memset( p, 0, sizeof(Rwt_Man_t) );
p->nFuncs = (1<<16);
// copy the global tables
Rwt_ManGlobalStart();
p->puCanons = s_puCanons;
p->pPhases = s_pPhases;
p->pPerms = s_pPerms;
p->pMap = s_pMap;
// initialize practical NPN classes
p->pPractical = Rwt_ManGetPractical( p );
// create the table
p->pTable = ALLOC( Rwt_Node_t *, p->nFuncs );
memset( p->pTable, 0, sizeof(Rwt_Node_t *) * p->nFuncs );
// create the elementary nodes
p->pMmNode = Mem_FixedStart( sizeof(Rwt_Node_t) );
p->vForest = Vec_PtrAlloc( 100 );
Rwt_ManAddVar( p, 0x0000, fPrecompute ); // constant 0
Rwt_ManAddVar( p, 0xAAAA, fPrecompute ); // var A
Rwt_ManAddVar( p, 0xCCCC, fPrecompute ); // var B
Rwt_ManAddVar( p, 0xF0F0, fPrecompute ); // var C
Rwt_ManAddVar( p, 0xFF00, fPrecompute ); // var D
p->nClasses = 5;
// other stuff
p->nTravIds = 1;
p->pPerms4 = Extra_Permutations( 4 );
p->vLevNums = Vec_IntAlloc( 50 );
p->vFanins = Vec_PtrAlloc( 50 );
p->vFaninsCur = Vec_PtrAlloc( 50 );
p->vNodesTemp = Vec_PtrAlloc( 50 );
if ( fPrecompute )
{ // precompute subgraphs
// Rwt_ManPrecompute( p );
// Rwt_ManPrint( p );
// Rwt_ManWriteToArray( p );
}
else
{ // load saved subgraphs
Rwt_ManLoadFromArray( p, 0 );
// Rwt_ManPrint( p );
Rwt_ManPreprocess( p );
}
p->timeStart = clock() - clk;
return p;
}
/**Function*************************************************************
Synopsis [Stops rewriting manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManStop( Rwt_Man_t * p )
{
if ( p->vClasses )
{
Rwt_Node_t * pNode;
int i, k;
Vec_VecForEachEntry( p->vClasses, pNode, i, k )
Dec_GraphFree( (Dec_Graph_t *)pNode->pNext );
}
if ( p->vClasses ) Vec_VecFree( p->vClasses );
Vec_PtrFree( p->vNodesTemp );
Vec_PtrFree( p->vForest );
Vec_IntFree( p->vLevNums );
Vec_PtrFree( p->vFanins );
Vec_PtrFree( p->vFaninsCur );
Mem_FixedStop( p->pMmNode, 0 );
FREE( p->pMapInv );
free( p->pTable );
free( p->pPractical );
free( p->pPerms4 );
free( p );
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManPrintStats( Rwt_Man_t * p )
{
int i, Counter = 0;
for ( i = 0; i < 222; i++ )
Counter += (p->nScores[i] > 0);
printf( "Rewriting statistics:\n" );
printf( "Total cuts tries = %8d.\n", p->nCutsGood );
printf( "Bad cuts found = %8d.\n", p->nCutsBad );
printf( "Total subgraphs = %8d.\n", p->nSubgraphs );
printf( "Used NPN classes = %8d.\n", Counter );
printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten );
printf( "Calculated gain = %8d.\n", p->nNodesGained );
PRT( "Start ", p->timeStart );
PRT( "Cuts ", p->timeCut );
PRT( "Truth ", p->timeTruth );
PRT( "Resynthesis ", p->timeRes );
PRT( " Mffc ", p->timeMffc );
PRT( " Eval ", p->timeEval );
PRT( "Update ", p->timeUpdate );
PRT( "TOTAL ", p->timeTotal );
printf( "The scores are:\n" );
for ( i = 0; i < 222; i++ )
if ( p->nScores[i] > 0 )
{
extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] );
Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) );
}
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManPrintStatsFile( Rwt_Man_t * p )
{
FILE * pTable;
pTable = fopen( "stats.txt", "a+" );
fprintf( pTable, "%d ", p->nCutsGood );
fprintf( pTable, "%d ", p->nSubgraphs );
fprintf( pTable, "%d ", p->nNodesRewritten );
fprintf( pTable, "%d", p->nNodesGained );
fprintf( pTable, "\n" );
fclose( pTable );
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void * Rwt_ManReadDecs( Rwt_Man_t * p )
{
return p->pGraph;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p )
{
return p->vFanins;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Rwt_ManReadCompl( Rwt_Man_t * p )
{
return p->fCompl;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time )
{
p->timeCut += Time;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time )
{
p->timeUpdate += Time;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time )
{
p->timeTotal += Time;
}
/**Function*************************************************************
Synopsis [Precomputes AIG subgraphs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_Precompute()
{
Rwt_Man_t * p;
p = Rwt_ManStart( 1 );
Rwt_ManStop( p );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [rwtUtil.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [Various utilities.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwtUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwt.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// precomputed data
#ifdef _WIN32
unsigned short s_RwtPracticalClasses[];
unsigned short s_RwtAigSubgraphs[];
#else
static unsigned short s_RwtPracticalClasses[];
static unsigned short s_RwtAigSubgraphs[];
#endif
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Adds the node to the end of the list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ListAddToTail( Rwt_Node_t ** ppList, Rwt_Node_t * pNode )
{
Rwt_Node_t * pTemp;
// find the last one
for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext )
ppList = &pTemp->pNext;
// attach at the end
*ppList = pNode;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute )
{
Rwt_Node_t * pNew;
pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode );
pNew->Id = p->vForest->nSize;
pNew->TravId = 0;
pNew->uTruth = uTruth;
pNew->Level = 0;
pNew->Volume = 0;
pNew->fUsed = 1;
pNew->fExor = 0;
pNew->p0 = NULL;
pNew->p1 = NULL;
pNew->pNext = NULL;
Vec_PtrPush( p->vForest, pNew );
if ( fPrecompute )
Rwt_ListAddToTail( p->pTable + uTruth, pNew );
return pNew;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwt_Node_t * Rwt_ManAddNode( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1, int fExor, int Level, int Volume )
{
Rwt_Node_t * pNew;
unsigned uTruth;
// compute truth table, leve, volume
p->nConsidered++;
if ( fExor )
uTruth = (p0->uTruth ^ p1->uTruth);
else
uTruth = (Rwt_IsComplement(p0)? ~Rwt_Regular(p0)->uTruth : Rwt_Regular(p0)->uTruth) &
(Rwt_IsComplement(p1)? ~Rwt_Regular(p1)->uTruth : Rwt_Regular(p1)->uTruth) & 0xFFFF;
// create the new node
pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode );
pNew->Id = p->vForest->nSize;
pNew->TravId = 0;
pNew->uTruth = uTruth;
pNew->Level = Level;
pNew->Volume = Volume;
pNew->fUsed = 0;
pNew->fExor = fExor;
pNew->p0 = p0;
pNew->p1 = p1;
pNew->pNext = NULL;
Vec_PtrPush( p->vForest, pNew );
// do not add if the node is not essential
if ( uTruth != p->puCanons[uTruth] )
return pNew;
// add to the list
p->nAdded++;
if ( p->pTable[uTruth] == NULL )
p->nClasses++;
Rwt_ListAddToTail( p->pTable + uTruth, pNew );
return pNew;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_Trav_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, int * pVolume )
{
if ( pNode->fUsed || pNode->TravId == p->nTravIds )
return;
pNode->TravId = p->nTravIds;
(*pVolume)++;
if ( pNode->fExor )
(*pVolume)++;
Rwt_Trav_rec( p, Rwt_Regular(pNode->p0), pVolume );
Rwt_Trav_rec( p, Rwt_Regular(pNode->p1), pVolume );
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManIncTravId( Rwt_Man_t * p )
{
Rwt_Node_t * pNode;
int i;
if ( p->nTravIds++ < 0x8FFFFFFF )
return;
Vec_PtrForEachEntry( p->vForest, pNode, i )
pNode->TravId = 0;
p->nTravIds = 1;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Rwt_ManNodeVolume( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1 )
{
int Volume = 0;
Rwt_ManIncTravId( p );
Rwt_Trav_rec( p, p0, &Volume );
Rwt_Trav_rec( p, p1, &Volume );
return Volume;
}
/**Function*************************************************************
Synopsis [Loads data.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose )
{
unsigned short * pArray = s_RwtAigSubgraphs;
Rwt_Node_t * p0, * p1;
unsigned Entry0, Entry1;
int Level, Volume, nEntries, fExor;
int i, clk = clock();
// reconstruct the forest
for ( i = 0; ; i++ )
{
Entry0 = pArray[2*i + 0];
Entry1 = pArray[2*i + 1];
if ( Entry0 == 0 && Entry1 == 0 )
break;
// get EXOR flag
fExor = (Entry0 & 1);
Entry0 >>= 1;
// get the nodes
p0 = p->vForest->pArray[Entry0 >> 1];
p1 = p->vForest->pArray[Entry1 >> 1];
// compute the level and volume of the new nodes
Level = 1 + RWT_MAX( p0->Level, p1->Level );
Volume = 1 + Rwt_ManNodeVolume( p, p0, p1 );
// set the complemented attributes
p0 = Rwt_NotCond( p0, (Entry0 & 1) );
p1 = Rwt_NotCond( p1, (Entry1 & 1) );
// add the node
// Rwt_ManTryNode( p, p0, p1, Level, Volume );
Rwt_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor );
}
nEntries = i - 1;
if ( fVerbose )
{
printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded );
printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk );
}
}
/**Function*************************************************************
Synopsis [Create practical classes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Rwt_ManGetPractical( Rwt_Man_t * p )
{
char * pPractical;
int i;
pPractical = ALLOC( char, p->nFuncs );
memset( pPractical, 0, sizeof(char) * p->nFuncs );
pPractical[0] = 1;
for ( i = 1; ; i++ )
{
if ( s_RwtPracticalClasses[i] == 0 )
break;
pPractical[ s_RwtPracticalClasses[i] ] = 1;
}
return pPractical;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
// the following 135 practical NPN classes of 4-variable functions were computed
// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks
static unsigned short s_RwtPracticalClasses[] =
{
0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b,
0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff,
0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c,
0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183,
0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab,
0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe,
0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368,
0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5,
0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669,
0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2,
0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8,
0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4,
0x1ee1, 0x3cc3, 0x6996, 0x0000
};
static unsigned short s_RwtAigSubgraphs[] =
{
0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002,
0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002,
0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004,
0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002,
0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004,
0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006,
0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007,
0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009,
0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007,
0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005,
0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006,
0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008,
0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006,
0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008,
0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006,
0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004,
0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009,
0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e,
0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005,
0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f,
0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009,
0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e,
0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005,
0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008,
0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013,
0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008,
0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012,
0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003,
0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009,
0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013,
0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002,
0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d,
0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c,
0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007,
0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012,
0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002,
0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008,
0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f,
0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019,
0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002,
0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008,
0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011,
0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017,
0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d,
0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009,
0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019,
0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024,
0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004,
0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b,
0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021,
0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024,
0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009,
0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024,
0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004,
0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d,
0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020,
0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024,
0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027,
0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f,
0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d,
0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024,
0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006,
0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015,
0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f,
0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002,
0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016,
0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025,
0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b,
0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a,
0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003,
0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f,
0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018,
0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b,
0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003,
0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006,
0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019,
0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022,
0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f,
0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004,
0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f,
0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017,
0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f,
0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002,
0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011,
0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037,
0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010,
0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b,
0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002,
0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005,
0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d,
0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011,
0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012,
0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039,
0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005,
0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011,
0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017,
0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b,
0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009,
0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037,
0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010,
0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030,
0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009,
0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d,
0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008,
0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010,
0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030,
0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044,
0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011,
0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043,
0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017,
0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a,
0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f,
0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f,
0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023,
0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007,
0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033,
0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b,
0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037,
0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d,
0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067,
0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038,
0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d,
0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006,
0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025,
0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014,
0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f,
0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008,
0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d,
0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058,
0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008,
0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d,
0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059,
0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b,
0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b,
0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019,
0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043,
0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061,
0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007,
0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004,
0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045,
0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d,
0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009,
0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044,
0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044,
0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097,
0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f,
0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048,
0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a,
0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009,
0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044,
0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a,
0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029,
0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a,
0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013,
0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5,
0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f,
0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095,
0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009,
0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f,
0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013,
0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095,
0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030,
0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6,
0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e,
0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061,
0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc,
0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044,
0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a,
0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008,
0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8,
0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095,
0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004,
0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029,
0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068,
0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c,
0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029,
0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c,
0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013,
0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067,
0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf,
0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d,
0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003,
0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f,
0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099,
0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf,
0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f,
0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176,
0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3,
0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b,
0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f,
0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008,
0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095,
0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b,
0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec,
0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3,
0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009,
0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009,
0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a,
0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030,
0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009,
0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033,
0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e,
0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158,
0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a,
0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d,
0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168,
0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e,
0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133,
0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b,
0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f,
0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da,
0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d,
0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef,
0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181,
0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027,
0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a,
0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f,
0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181,
0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205,
0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033,
0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225,
0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0,
0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1,
0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d,
0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006,
0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a,
0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b,
0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033,
0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231,
0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4,
0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e,
0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec,
0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e,
0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3,
0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a,
0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef,
0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175,
0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0,
0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f,
0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3,
0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e,
0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086,
0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5,
0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e,
0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181,
0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0,
0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095,
0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b,
0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276,
0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4,
0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006,
0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3,
0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d,
0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103,
0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234,
0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d,
0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106,
0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8,
0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044,
0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0,
0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a,
0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6,
0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238,
0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e,
0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067,
0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020,
0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021,
0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183,
0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268,
0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc,
0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213,
0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023,
0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b,
0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da,
0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287,
0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce,
0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf,
0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338,
0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328,
0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003,
0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330,
0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282,
0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a,
0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9,
0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247,
0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d,
0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce,
0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0,
0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004,
0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315,
0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d,
0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd,
0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb,
0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f,
0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173,
0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029,
0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3,
0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053,
0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030,
0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021,
0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2,
0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9,
0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285,
0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b,
0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a,
0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315,
0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f,
0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c,
0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e,
0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089,
0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021,
0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354,
0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f,
0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095,
0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3,
0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e,
0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009,
0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009,
0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b,
0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381,
0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008,
0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb,
0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5,
0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027,
0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030,
0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb,
0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a,
0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009,
0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027,
0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d,
0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271,
0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f,
0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009,
0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009,
0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f,
0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9,
0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235,
0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d,
0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085,
0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3,
0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043,
0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7,
0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f,
0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059,
0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d,
0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009,
0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b,
0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061,
0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9,
0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027,
0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019,
0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1,
0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b,
0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7,
0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb,
0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d,
0x0000,0x0000
};
/**CFile****************************************************************
FileName [vec.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resizable arrays.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __VEC_H__
#define __VEC_H__
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
#define inline __inline // compatible with MS VS 6.0
#endif
#include "vecInt.h"
#include "vecStr.h"
#include "vecPtr.h"
#include "vecVec.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [vecInt.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resizable arrays.]
Synopsis [Resizable arrays of integers.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __VEC_INT_H__
#define __VEC_INT_H__
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Vec_Int_t_ Vec_Int_t;
struct Vec_Int_t_
{
int nCap;
int nSize;
int * pArray;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define Vec_IntForEachEntry( vVec, Entry, i ) \
for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
#define Vec_IntForEachEntryStart( vVec, Entry, i, Start ) \
for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
#define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \
for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ )
#define Vec_IntForEachEntryReverse( vVec, pEntry, i ) \
for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntAlloc( int nCap )
{
Vec_Int_t * p;
p = ALLOC( Vec_Int_t, 1 );
if ( nCap > 0 && nCap < 16 )
nCap = 16;
p->nSize = 0;
p->nCap = nCap;
p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL;
return p;
}
/**Function*************************************************************
Synopsis [Allocates a vector with the given size and cleans it.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntStart( int nSize )
{
Vec_Int_t * p;
p = Vec_IntAlloc( nSize );
p->nSize = nSize;
memset( p->pArray, 0, sizeof(int) * nSize );
return p;
}
/**Function*************************************************************
Synopsis [Creates the vector from an integer array of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize )
{
Vec_Int_t * p;
p = ALLOC( Vec_Int_t, 1 );
p->nSize = nSize;
p->nCap = nSize;
p->pArray = pArray;
return p;
}
/**Function*************************************************************
Synopsis [Creates the vector from an integer array of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntAllocArrayCopy( int * pArray, int nSize )
{
Vec_Int_t * p;
p = ALLOC( Vec_Int_t, 1 );
p->nSize = nSize;
p->nCap = nSize;
p->pArray = ALLOC( int, nSize );
memcpy( p->pArray, pArray, sizeof(int) * nSize );
return p;
}
/**Function*************************************************************
Synopsis [Duplicates the integer array.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec )
{
Vec_Int_t * p;
p = ALLOC( Vec_Int_t, 1 );
p->nSize = pVec->nSize;
p->nCap = pVec->nCap;
p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL;
memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize );
return p;
}
/**Function*************************************************************
Synopsis [Transfers the array into another vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntDupArray( Vec_Int_t * pVec )
{
Vec_Int_t * p;
p = ALLOC( Vec_Int_t, 1 );
p->nSize = pVec->nSize;
p->nCap = pVec->nCap;
p->pArray = pVec->pArray;
pVec->nSize = 0;
pVec->nCap = 0;
pVec->pArray = NULL;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntFree( Vec_Int_t * p )
{
FREE( p->pArray );
FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int * Vec_IntReleaseArray( Vec_Int_t * p )
{
int * pArray = p->pArray;
p->nCap = 0;
p->nSize = 0;
p->pArray = NULL;
return pArray;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int * Vec_IntArray( Vec_Int_t * p )
{
return p->pArray;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntSize( Vec_Int_t * p )
{
return p->nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntEntry( Vec_Int_t * p, int i )
{
assert( i >= 0 && i < p->nSize );
return p->pArray[i];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry )
{
assert( i >= 0 && i < p->nSize );
p->pArray[i] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
{
assert( i >= 0 && i < p->nSize );
p->pArray[i] += Addition;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntEntryLast( Vec_Int_t * p )
{
assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
/**Function*************************************************************
Synopsis [Resizes the vector to the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
{
if ( p->nCap >= nCapMin )
return;
p->pArray = REALLOC( int, p->pArray, nCapMin );
assert( p->pArray );
p->nCap = nCapMin;
}
/**Function*************************************************************
Synopsis [Fills the vector with given number of entries.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Entry )
{
int i;
Vec_IntGrow( p, nSize );
for ( i = 0; i < nSize; i++ )
p->pArray[i] = Entry;
p->nSize = nSize;
}
/**Function*************************************************************
Synopsis [Fills the vector with given number of entries.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Entry )
{
int i;
if ( p->nSize >= nSize )
return;
Vec_IntGrow( p, nSize );
for ( i = p->nSize; i < nSize; i++ )
p->pArray[i] = Entry;
p->nSize = nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew )
{
assert( p->nSize >= nSizeNew );
p->nSize = nSizeNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntClear( Vec_Int_t * p )
{
p->nSize = 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
{
if ( p->nSize == p->nCap )
{
if ( p->nCap < 16 )
Vec_IntGrow( p, 16 );
else
Vec_IntGrow( p, 2 * p->nCap );
}
p->pArray[p->nSize++] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry )
{
int i;
if ( p->nSize == p->nCap )
{
if ( p->nCap < 16 )
Vec_IntGrow( p, 16 );
else
Vec_IntGrow( p, 2 * p->nCap );
}
p->nSize++;
for ( i = p->nSize - 1; i >= 1; i-- )
p->pArray[i] = p->pArray[i-1];
p->pArray[0] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int Entry )
{
if ( p->nSize == p->nCap )
{
int * pArray;
int i;
if ( p->nSize == 0 )
p->nCap = 1;
pArray = (int *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 );
// pArray = ALLOC( int, p->nCap * 2 );
if ( p->pArray )
{
for ( i = 0; i < p->nSize; i++ )
pArray[i] = p->pArray[i];
Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 );
// free( p->pArray );
}
p->nCap *= 2;
p->pArray = pArray;
}
p->pArray[p->nSize++] = Entry;
}
/**Function*************************************************************
Synopsis [Inserts the entry while preserving the increasing order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry )
{
int i;
if ( p->nSize == p->nCap )
{
if ( p->nCap < 16 )
Vec_IntGrow( p, 16 );
else
Vec_IntGrow( p, 2 * p->nCap );
}
p->nSize++;
for ( i = p->nSize-2; i >= 0; i-- )
if ( p->pArray[i] > Entry )
p->pArray[i+1] = p->pArray[i];
else
break;
p->pArray[i+1] = Entry;
}
/**Function*************************************************************
Synopsis [Inserts the entry while preserving the increasing order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
return 1;
Vec_IntPushOrder( p, Entry );
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
return 1;
Vec_IntPush( p, Entry );
return 0;
}
/**Function*************************************************************
Synopsis [Returns the last entry and removes it from the list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntPop( Vec_Int_t * p )
{
assert( p->nSize > 0 );
return p->pArray[--p->nSize];
}
/**Function*************************************************************
Synopsis [Find entry.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntFind( Vec_Int_t * p, int Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
return i;
return -1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntRemove( Vec_Int_t * p, int Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
break;
if ( i == p->nSize )
return 0;
assert( i < p->nSize );
for ( i++; i < p->nSize; i++ )
p->pArray[i-1] = p->pArray[i];
p->nSize--;
return 1;
}
/**Function*************************************************************
Synopsis [Comparison procedure for two integers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntSortCompare1( int * pp1, int * pp2 )
{
// for some reason commenting out lines (as shown) led to crashing of the release version
if ( *pp1 < *pp2 )
return -1;
if ( *pp1 > *pp2 ) //
return 1;
return 0; //
}
/**Function*************************************************************
Synopsis [Comparison procedure for two integers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntSortCompare2( int * pp1, int * pp2 )
{
// for some reason commenting out lines (as shown) led to crashing of the release version
if ( *pp1 > *pp2 )
return -1;
if ( *pp1 < *pp2 ) //
return 1;
return 0; //
}
/**Function*************************************************************
Synopsis [Sorting the entries by their integer value.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntSort( Vec_Int_t * p, int fReverse )
{
if ( fReverse )
qsort( (void *)p->pArray, p->nSize, sizeof(int),
(int (*)(const void *, const void *)) Vec_IntSortCompare2 );
else
qsort( (void *)p->pArray, p->nSize, sizeof(int),
(int (*)(const void *, const void *)) Vec_IntSortCompare1 );
}
/**Function*************************************************************
Synopsis [Comparison procedure for two integers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntSortCompareUnsigned( unsigned * pp1, unsigned * pp2 )
{
if ( *pp1 < *pp2 )
return -1;
if ( *pp1 > *pp2 )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Sorting the entries by their integer value.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntSortUnsigned( Vec_Int_t * p )
{
qsort( (void *)p->pArray, p->nSize, sizeof(int),
(int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned );
}
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [vecPtr.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resizable arrays.]
Synopsis [Resizable arrays of generic pointers.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: vecPtr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __VEC_PTR_H__
#define __VEC_PTR_H__
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Vec_Ptr_t_ Vec_Ptr_t;
struct Vec_Ptr_t_
{
int nCap;
int nSize;
void ** pArray;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// iterators through entries
#define Vec_PtrForEachEntry( vVec, pEntry, i ) \
for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
#define Vec_PtrForEachEntryStart( vVec, pEntry, i, Start ) \
for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \
for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
#define Vec_PtrForEachEntryStartStop( vVec, pEntry, i, Start, Stop ) \
for ( i = Start; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
#define Vec_PtrForEachEntryReverse( vVec, pEntry, i ) \
for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i-- )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Ptr_t * Vec_PtrAlloc( int nCap )
{
Vec_Ptr_t * p;
p = ALLOC( Vec_Ptr_t, 1 );
if ( nCap > 0 && nCap < 8 )
nCap = 8;
p->nSize = 0;
p->nCap = nCap;
p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
return p;
}
/**Function*************************************************************
Synopsis [Allocates a vector with the given size and cleans it.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Ptr_t * Vec_PtrStart( int nSize )
{
Vec_Ptr_t * p;
p = Vec_PtrAlloc( nSize );
p->nSize = nSize;
memset( p->pArray, 0, sizeof(void *) * nSize );
return p;
}
/**Function*************************************************************
Synopsis [Creates the vector from an integer array of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Ptr_t * Vec_PtrAllocArray( void ** pArray, int nSize )
{
Vec_Ptr_t * p;
p = ALLOC( Vec_Ptr_t, 1 );
p->nSize = nSize;
p->nCap = nSize;
p->pArray = pArray;
return p;
}
/**Function*************************************************************
Synopsis [Creates the vector from an integer array of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Ptr_t * Vec_PtrAllocArrayCopy( void ** pArray, int nSize )
{
Vec_Ptr_t * p;
p = ALLOC( Vec_Ptr_t, 1 );
p->nSize = nSize;
p->nCap = nSize;
p->pArray = ALLOC( void *, nSize );
memcpy( p->pArray, pArray, sizeof(void *) * nSize );
return p;
}
/**Function*************************************************************
Synopsis [Duplicates the integer array.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Ptr_t * Vec_PtrDup( Vec_Ptr_t * pVec )
{
Vec_Ptr_t * p;
p = ALLOC( Vec_Ptr_t, 1 );
p->nSize = pVec->nSize;
p->nCap = pVec->nCap;
p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
memcpy( p->pArray, pVec->pArray, sizeof(void *) * pVec->nSize );
return p;
}
/**Function*************************************************************
Synopsis [Transfers the array into another vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Ptr_t * Vec_PtrDupArray( Vec_Ptr_t * pVec )
{
Vec_Ptr_t * p;
p = ALLOC( Vec_Ptr_t, 1 );
p->nSize = pVec->nSize;
p->nCap = pVec->nCap;
p->pArray = pVec->pArray;
pVec->nSize = 0;
pVec->nCap = 0;
pVec->pArray = NULL;
return p;
}
/**Function*************************************************************
Synopsis [Frees the vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrFree( Vec_Ptr_t * p )
{
FREE( p->pArray );
FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void ** Vec_PtrReleaseArray( Vec_Ptr_t * p )
{
void ** pArray = p->pArray;
p->nCap = 0;
p->nSize = 0;
p->pArray = NULL;
return pArray;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void ** Vec_PtrArray( Vec_Ptr_t * p )
{
return p->pArray;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_PtrSize( Vec_Ptr_t * p )
{
return p->nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i )
{
assert( i >= 0 && i < p->nSize );
return p->pArray[i];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry )
{
assert( i >= 0 && i < p->nSize );
p->pArray[i] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p )
{
assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
/**Function*************************************************************
Synopsis [Resizes the vector to the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrGrow( Vec_Ptr_t * p, int nCapMin )
{
if ( p->nCap >= nCapMin )
return;
p->pArray = REALLOC( void *, p->pArray, nCapMin );
p->nCap = nCapMin;
}
/**Function*************************************************************
Synopsis [Fills the vector with given number of entries.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrFill( Vec_Ptr_t * p, int nSize, void * Entry )
{
int i;
Vec_PtrGrow( p, nSize );
for ( i = 0; i < nSize; i++ )
p->pArray[i] = Entry;
p->nSize = nSize;
}
/**Function*************************************************************
Synopsis [Fills the vector with given number of entries.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Entry )
{
int i;
if ( p->nSize >= nSize )
return;
Vec_PtrGrow( p, nSize );
for ( i = p->nSize; i < nSize; i++ )
p->pArray[i] = Entry;
p->nSize = nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrShrink( Vec_Ptr_t * p, int nSizeNew )
{
assert( p->nSize >= nSizeNew );
p->nSize = nSizeNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrClear( Vec_Ptr_t * p )
{
p->nSize = 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrPush( Vec_Ptr_t * p, void * Entry )
{
if ( p->nSize == p->nCap )
{
if ( p->nCap < 16 )
Vec_PtrGrow( p, 16 );
else
Vec_PtrGrow( p, 2 * p->nCap );
}
p->pArray[p->nSize++] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_PtrPushUnique( Vec_Ptr_t * p, void * Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
return 1;
Vec_PtrPush( p, Entry );
return 0;
}
/**Function*************************************************************
Synopsis [Returns the last entry and removes it from the list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void * Vec_PtrPop( Vec_Ptr_t * p )
{
assert( p->nSize > 0 );
return p->pArray[--p->nSize];
}
/**Function*************************************************************
Synopsis [Find entry.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
return i;
return -1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
break;
assert( i < p->nSize );
for ( i++; i < p->nSize; i++ )
p->pArray[i-1] = p->pArray[i];
p->nSize--;
}
/**Function*************************************************************
Synopsis [Moves the first nItems to the end.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems )
{
assert( nItems < p->nSize );
Vec_PtrGrow( p, nItems + p->nSize );
memmove( (char **)p->pArray + p->nSize, p->pArray, nItems * sizeof(void*) );
memmove( p->pArray, (char **)p->pArray + nItems, p->nSize * sizeof(void*) );
}
/**Function*************************************************************
Synopsis [Sorting the entries by their integer value.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() )
{
qsort( (void *)p->pArray, p->nSize, sizeof(void *),
(int (*)(const void *, const void *)) Vec_PtrSortCompare );
}
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [vecStr.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resizable arrays.]
Synopsis [Resizable arrays of characters.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: vecStr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __VEC_STR_H__
#define __VEC_STR_H__
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Vec_Str_t_ Vec_Str_t;
struct Vec_Str_t_
{
int nCap;
int nSize;
char * pArray;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define Vec_StrForEachEntry( vVec, Entry, i ) \
for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Str_t * Vec_StrAlloc( int nCap )
{
Vec_Str_t * p;
p = ALLOC( Vec_Str_t, 1 );
if ( nCap > 0 && nCap < 16 )
nCap = 16;
p->nSize = 0;
p->nCap = nCap;
p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL;
return p;
}
/**Function*************************************************************
Synopsis [Allocates a vector with the given size and cleans it.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Str_t * Vec_StrStart( int nSize )
{
Vec_Str_t * p;
p = Vec_StrAlloc( nSize );
p->nSize = nSize;
memset( p->pArray, 0, sizeof(char) * nSize );
return p;
}
/**Function*************************************************************
Synopsis [Creates the vector from an integer array of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize )
{
Vec_Str_t * p;
p = ALLOC( Vec_Str_t, 1 );
p->nSize = nSize;
p->nCap = nSize;
p->pArray = pArray;
return p;
}
/**Function*************************************************************
Synopsis [Creates the vector from an integer array of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Str_t * Vec_StrAllocArrayCopy( char * pArray, int nSize )
{
Vec_Str_t * p;
p = ALLOC( Vec_Str_t, 1 );
p->nSize = nSize;
p->nCap = nSize;
p->pArray = ALLOC( char, nSize );
memcpy( p->pArray, pArray, sizeof(char) * nSize );
return p;
}
/**Function*************************************************************
Synopsis [Duplicates the integer array.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Str_t * Vec_StrDup( Vec_Str_t * pVec )
{
Vec_Str_t * p;
p = ALLOC( Vec_Str_t, 1 );
p->nSize = pVec->nSize;
p->nCap = pVec->nCap;
p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL;
memcpy( p->pArray, pVec->pArray, sizeof(char) * pVec->nSize );
return p;
}
/**Function*************************************************************
Synopsis [Transfers the array into another vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Str_t * Vec_StrDupArray( Vec_Str_t * pVec )
{
Vec_Str_t * p;
p = ALLOC( Vec_Str_t, 1 );
p->nSize = pVec->nSize;
p->nCap = pVec->nCap;
p->pArray = pVec->pArray;
pVec->nSize = 0;
pVec->nCap = 0;
pVec->pArray = NULL;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrFree( Vec_Str_t * p )
{
FREE( p->pArray );
FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline char * Vec_StrReleaseArray( Vec_Str_t * p )
{
char * pArray = p->pArray;
p->nCap = 0;
p->nSize = 0;
p->pArray = NULL;
return pArray;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline char * Vec_StrArray( Vec_Str_t * p )
{
return p->pArray;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_StrSize( Vec_Str_t * p )
{
return p->nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline char Vec_StrEntry( Vec_Str_t * p, int i )
{
assert( i >= 0 && i < p->nSize );
return p->pArray[i];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry )
{
assert( i >= 0 && i < p->nSize );
p->pArray[i] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline char Vec_StrEntryLast( Vec_Str_t * p )
{
assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
/**Function*************************************************************
Synopsis [Resizes the vector to the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrGrow( Vec_Str_t * p, int nCapMin )
{
if ( p->nCap >= nCapMin )
return;
p->pArray = REALLOC( char, p->pArray, 2 * nCapMin );
p->nCap = 2 * nCapMin;
}
/**Function*************************************************************
Synopsis [Fills the vector with given number of entries.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrFill( Vec_Str_t * p, int nSize, char Entry )
{
int i;
Vec_StrGrow( p, nSize );
p->nSize = nSize;
for ( i = 0; i < p->nSize; i++ )
p->pArray[i] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrShrink( Vec_Str_t * p, int nSizeNew )
{
assert( p->nSize >= nSizeNew );
p->nSize = nSizeNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrClear( Vec_Str_t * p )
{
p->nSize = 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrPush( Vec_Str_t * p, char Entry )
{
if ( p->nSize == p->nCap )
{
if ( p->nCap < 16 )
Vec_StrGrow( p, 16 );
else
Vec_StrGrow( p, 2 * p->nCap );
}
p->pArray[p->nSize++] = Entry;
}
/**Function*************************************************************
Synopsis [Appends the string to the char vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrAppend( Vec_Str_t * p, char * pString )
{
int i, nLength = strlen(pString);
Vec_StrGrow( p, p->nSize + nLength );
for ( i = 0; i < nLength; i++ )
p->pArray[p->nSize + i] = pString[i];
p->nSize += nLength;
}
/**Function*************************************************************
Synopsis [Returns the last entry and removes it from the list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline char Vec_StrPop( Vec_Str_t * p )
{
assert( p->nSize > 0 );
return p->pArray[--p->nSize];
}
/**Function*************************************************************
Synopsis [Comparison procedure for two clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_StrSortCompare1( char * pp1, char * pp2 )
{
// for some reason commenting out lines (as shown) led to crashing of the release version
if ( *pp1 < *pp2 )
return -1;
if ( *pp1 > *pp2 ) //
return 1;
return 0; //
}
/**Function*************************************************************
Synopsis [Comparison procedure for two clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_StrSortCompare2( char * pp1, char * pp2 )
{
// for some reason commenting out lines (as shown) led to crashing of the release version
if ( *pp1 > *pp2 )
return -1;
if ( *pp1 < *pp2 ) //
return 1;
return 0; //
}
/**Function*************************************************************
Synopsis [Sorting the entries by their integer value.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrSort( Vec_Str_t * p, int fReverse )
{
if ( fReverse )
qsort( (void *)p->pArray, p->nSize, sizeof(char),
(int (*)(const void *, const void *)) Vec_StrSortCompare2 );
else
qsort( (void *)p->pArray, p->nSize, sizeof(char),
(int (*)(const void *, const void *)) Vec_StrSortCompare1 );
}
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [vecVec.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resizable arrays.]
Synopsis [Resizable vector of resizable vectors.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __VEC_VEC_H__
#define __VEC_VEC_H__
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Vec_Vec_t_ Vec_Vec_t;
struct Vec_Vec_t_
{
int nCap;
int nSize;
void ** pArray;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// iterators through levels
#define Vec_VecForEachLevel( vGlob, vVec, i ) \
for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \
for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \
for ( i = LevelStart; (i <= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ )
#define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \
for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- )
// iteratores through entries
#define Vec_VecForEachEntry( vGlob, pEntry, i, k ) \
for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
#define Vec_VecForEachEntryStart( vGlob, pEntry, i, k, LevelStart ) \
for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
#define Vec_VecForEachEntryStartStop( vGlob, pEntry, i, k, LevelStart, LevelStop ) \
for ( i = LevelStart; i <= LevelStop; i++ ) \
Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
#define Vec_VecForEachEntryReverse( vGlob, pEntry, i, k ) \
for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
#define Vec_VecForEachEntryReverseReverse( vGlob, pEntry, i, k ) \
for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \
Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Vec_t * Vec_VecAlloc( int nCap )
{
Vec_Vec_t * p;
p = ALLOC( Vec_Vec_t, 1 );
if ( nCap > 0 && nCap < 8 )
nCap = 8;
p->nSize = 0;
p->nCap = nCap;
p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
return p;
}
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Vec_t * Vec_VecStart( int nSize )
{
Vec_Vec_t * p;
int i;
p = Vec_VecAlloc( nSize );
for ( i = 0; i < nSize; i++ )
p->pArray[i] = Vec_PtrAlloc( 0 );
p->nSize = nSize;
return p;
}
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_VecExpand( Vec_Vec_t * p, int Level )
{
int i;
if ( p->nSize >= Level + 1 )
return;
Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
for ( i = p->nSize; i <= Level; i++ )
p->pArray[i] = Vec_PtrAlloc( 0 );
p->nSize = Level + 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_VecSize( Vec_Vec_t * p )
{
return p->nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void * Vec_VecEntry( Vec_Vec_t * p, int i )
{
assert( i >= 0 && i < p->nSize );
return p->pArray[i];
}
/**Function*************************************************************
Synopsis [Frees the vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_VecFree( Vec_Vec_t * p )
{
Vec_Ptr_t * vVec;
int i;
Vec_VecForEachLevel( p, vVec, i )
Vec_PtrFree( vVec );
Vec_PtrFree( (Vec_Ptr_t *)p );
}
/**Function*************************************************************
Synopsis [Frees the vector of vectors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_VecSizeSize( Vec_Vec_t * p )
{
Vec_Ptr_t * vVec;
int i, Counter = 0;
Vec_VecForEachLevel( p, vVec, i )
Counter += vVec->nSize;
return Counter;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_VecClear( Vec_Vec_t * p )
{
Vec_Ptr_t * vVec;
int i;
Vec_VecForEachLevel( p, vVec, i )
Vec_PtrClear( vVec );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry )
{
if ( p->nSize < Level + 1 )
{
int i;
Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
for ( i = p->nSize; i < Level + 1; i++ )
p->pArray[i] = Vec_PtrAlloc( 0 );
p->nSize = Level + 1;
}
Vec_PtrPush( (Vec_Ptr_t*)p->pArray[Level], Entry );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry )
{
if ( p->nSize < Level + 1 )
Vec_VecPush( p, Level, Entry );
else
Vec_PtrPushUnique( (Vec_Ptr_t*)p->pArray[Level], Entry );
}
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
SRC += src/opt/xyz/xyzBuild.c \
src/opt/xyz/xyzCore.c \
src/opt/xyz/xyzMan.c \
src/opt/xyz/xyzMinEsop.c \
src/opt/xyz/xyzMinMan.c \
src/opt/xyz/xyzMinSop.c \
src/opt/xyz/xyzMinUtil.c \
src/opt/xyz/xyzTest.c
SRC += src/temp/xyz/xyzBuild.c \
src/temp/xyz/xyzCore.c \
src/temp/xyz/xyzMan.c \
src/temp/xyz/xyzMinEsop.c \
src/temp/xyz/xyzMinMan.c \
src/temp/xyz/xyzMinSop.c \
src/temp/xyz/xyzMinUtil.c \
src/temp/xyz/xyzTest.c
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment