Exemple #1
0
ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Implements the function.]

  Description [Returns the node implementing this function.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p )
{
    extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
    unsigned * pTruth;
    Abc_Obj_t * pObjNew;
    int i;
    if ( p->fMark )
        pMan->nMuxes++;
    else
        pMan->nDsds++;
    // create the new node
    pObjNew = Abc_NtkCreateNode( pNtk );
    for ( i = 0; i < (int)p->nVars; i++ )
        Abc_ObjAddFanin( pObjNew, Abc_ObjRegular((Abc_Obj_t *)Vec_PtrEntry(vLeaves, p->pFanins[i])) );
    Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) );
    // assign the node's function
    pTruth = Lpk_FunTruth(p, 0);
    if ( p->nVars == 0 )
    {
        pObjNew->pData = Hop_NotCond( Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc), !(pTruth[0] & 1) );
        return pObjNew;
    }
    if ( p->nVars == 1 )
    {
        pObjNew->pData = Hop_NotCond( Hop_ManPi((Hop_Man_t *)pNtk->pManFunc, 0), (pTruth[0] & 1) );
        return pObjNew;
    }
    // create the logic function
    pObjNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtk->pManFunc, pTruth, p->nVars, NULL );
    return pObjNew;
}
Exemple #2
0
/**Function*************************************************************

  Synopsis    [Cleans the data pointers for the nodes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Hop_ManCleanData( Hop_Man_t * p )
{
    Hop_Obj_t * pObj;
    int i;
    p->nTravIds = 1;
    Hop_ManConst1(p)->pData = NULL;
    Hop_ManForEachPi( p, pObj, i )
        pObj->pData = NULL;
    Hop_ManForEachPo( p, pObj, i )
        pObj->pData = NULL;
    Hop_ManForEachNode( p, pObj, i )
        pObj->pData = NULL;
}
Exemple #3
0
/**Function*************************************************************

  Synopsis    [Computes the max number of levels in the manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Hop_ManCountLevels( Hop_Man_t * p )
{
    Vec_Ptr_t * vNodes;
    Hop_Obj_t * pObj;
    int i, LevelsMax, Level0, Level1;
    // initialize the levels
    Hop_ManConst1(p)->pData = NULL;
    Hop_ManForEachPi( p, pObj, i )
        pObj->pData = NULL;
    // compute levels in a DFS order
    vNodes = Hop_ManDfs( p );
    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
    {
        Level0 = (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData;
        Level1 = (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData;
        pObj->pData = (void *)(ABC_PTRUINT_T)(1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Level0, Level1));
    }
Exemple #4
0
/**Function*************************************************************

  Synopsis    [Converts AIG from Aig_Man_t into Hop_Obj_t.]

  Description [Assumes that Aig_Man_t has exactly one primary outputs.
  Returns the pointer to the root node (Hop_Obj_t) in Hop_Man_t.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Hop_Obj_t * Abc_MfsConvertAigToHop( Aig_Man_t * pMan, Hop_Man_t * pHop )
{
    Aig_Obj_t * pRoot, * pObj;
    int i;
    assert( Aig_ManPoNum(pMan) == 1 );
    pRoot = Aig_ManPo( pMan, 0 );
    // check the case of a constant
    if ( Aig_ObjIsConst1( Aig_ObjFanin0(pRoot) ) )
        return Hop_NotCond( Hop_ManConst1(pHop), Aig_ObjFaninC0(pRoot) );
    // set the PI mapping
    Aig_ManCleanData( pMan );
    Aig_ManForEachPi( pMan, pObj, i )
        pObj->pData = Hop_IthVar( pHop, i );
    // construct the AIG
    Abc_MfsConvertAigToHop_rec( Aig_ObjFanin0(pRoot), pHop );
    return Hop_NotCond( (Hop_Obj_t *)Aig_ObjFanin0(pRoot)->pData, Aig_ObjFaninC0(pRoot) );
}
Exemple #5
0
/**Function*************************************************************

  Synopsis    [Converts the network from the AIG manager into ABC.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk )
{
    Hop_Man_t * pMan;
    Abc_Obj_t * pObj;
    int i;
    // create the manager
    pMan = Hop_ManStart();
    // transfer the pointers to the basic nodes
    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan);
    Abc_NtkForEachCi( pNtk, pObj, i )
        pObj->pCopy = (Abc_Obj_t *)Hop_ObjCreatePi(pMan);
    // perform the conversion of the internal nodes (assumes DFS ordering)
    Abc_NtkForEachNode( pNtk, pObj, i )
        pObj->pCopy = (Abc_Obj_t *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) );
    // create the POs
    Abc_NtkForEachCo( pNtk, pObj, i )
        Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) );
    Hop_ManCleanup( pMan );
    return pMan;
}
Exemple #6
0
ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Transforms the decomposition graph into the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph )
{
    Kit_Node_t * pNode = NULL;
    Hop_Obj_t * pAnd0, * pAnd1;
    int i;
    // check for constant function
    if ( Kit_GraphIsConst(pGraph) )
        return Hop_NotCond( Hop_ManConst1(pMan), Kit_GraphIsComplement(pGraph) );
    // check for a literal
    if ( Kit_GraphIsVar(pGraph) )
        return Hop_NotCond( (Hop_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) );
    // build the AIG nodes corresponding to the AND gates of the graph
    Kit_GraphForEachNode( pGraph, pNode, i )
    {
        pAnd0 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); 
        pAnd1 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); 
        pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 );
    }
//    pNtk->nLatches = Aig_ManRegNum(p);
//    pNtk->nTruePis = Nwk_ManCiNum(pNtk) - pNtk->nLatches;
//    pNtk->nTruePos = Nwk_ManCoNum(pNtk) - pNtk->nLatches;
    Aig_ManForEachObj( p, pObj, i )
    {
        pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i );
        if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) )
            continue;
        if ( Aig_ObjIsNode(pObj) )
        {
            pCutBest = If_ObjCutBest( pIfObj );
            nLeaves  = If_CutLeaveNum( pCutBest );
            ppLeaves = If_CutLeaves( pCutBest );
            // create node
            pObjNew = Nwk_ManCreateNode( pNtk, nLeaves, pIfObj->nRefs );
            for ( k = 0; k < nLeaves; k++ )
            {
                pObjRepr = (Aig_Obj_t *)Vec_PtrEntry( vIfToAig, ppLeaves[k] );
                Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)pObjRepr->pData );
            }
            // get the functionality
            pObjNew->pFunc = Nwk_NodeIfToHop( pNtk->pManHop, pIfMan, pIfObj );
        }
        else if ( Aig_ObjIsCi(pObj) )
            pObjNew = Nwk_ManCreateCi( pNtk, pIfObj->nRefs );
        else if ( Aig_ObjIsCo(pObj) )
        {
            pObjNew = Nwk_ManCreateCo( pNtk );
            pObjNew->fInvert = Aig_ObjFaninC0(pObj);
            Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData );
//printf( "%d ", pObjNew->Id );
        }
        else if ( Aig_ObjIsConst1(pObj) )
        {
            pObjNew = Nwk_ManCreateNode( pNtk, 0, pIfObj->nRefs );
            pObjNew->pFunc = Hop_ManConst1( pNtk->pManHop );
        }
        else
            assert( 0 );
        pObj->pData = pObjNew;
    }
Exemple #8
0
int Abc_NtkTestTimNodeStrash( Gia_Man_t * pGia, Abc_Obj_t * pNode )
{
    Hop_Man_t * pMan;
    Hop_Obj_t * pRoot;
    Abc_Obj_t * pFanin;
    int i;
    assert( Abc_ObjIsNode(pNode) );
    assert( Abc_NtkIsAigLogic(pNode->pNtk) );
    // get the local AIG manager and the local root node
    pMan = (Hop_Man_t *)pNode->pNtk->pManFunc;
    pRoot = (Hop_Obj_t *)pNode->pData;
    // check the constant case
    if ( Abc_NodeIsConst(pNode) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) )
        return !Hop_IsComplement(pRoot);
    // set elementary variables
    Abc_ObjForEachFanin( pNode, pFanin, i )
        Hop_IthVar(pMan, i)->iData = pFanin->iTemp;
    // strash the AIG of this node
    Abc_NtkTestTimNodeStrash_rec( pGia, Hop_Regular(pRoot) );
    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
    // return the final node with complement if needed
    return Abc_LitNotCond( Hop_Regular(pRoot)->iData, Hop_IsComplement(pRoot) );
}
/**Function*************************************************************

  Synopsis    [Stops the AIG manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Hop_ManStop( Hop_Man_t * p )
{
    Hop_Obj_t * pObj;
    int i;
    // make sure the nodes have clean marks
    pObj = Hop_ManConst1(p);
    assert( !pObj->fMarkA && !pObj->fMarkB );
    Hop_ManForEachPi( p, pObj, i )
        assert( !pObj->fMarkA && !pObj->fMarkB );
    Hop_ManForEachPo( p, pObj, i )
        assert( !pObj->fMarkA && !pObj->fMarkB );
    Hop_ManForEachNode( p, pObj, i )
        assert( !pObj->fMarkA && !pObj->fMarkB );
    // print time
    if ( p->time1 ) { PRT( "time1", p->time1 ); }
    if ( p->time2 ) { PRT( "time2", p->time2 ); }
//    Hop_TableProfile( p );
    if ( p->vChunks )  Hop_ManStopMemory( p );
    if ( p->vPis )     Vec_PtrFree( p->vPis );
    if ( p->vPos )     Vec_PtrFree( p->vPos );
    if ( p->vObjs )    Vec_PtrFree( p->vObjs );
    free( p->pTable );
    free( p );
}
Exemple #10
0
/**Function*************************************************************

  Synopsis    [Converts the network from the AIG manager into ABC.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtk, Hop_Man_t * pMan )
{
    Vec_Ptr_t * vNodes;
    Abc_Ntk_t * pNtkNew;
    Hop_Obj_t * pObj;
    int i;
    // perform strashing
    pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
    // transfer the pointers to the basic nodes
    Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
    Hop_ManForEachPi( pMan, pObj, i )
        pObj->pData = Abc_NtkCi(pNtkNew, i);
    // rebuild the AIG
    vNodes = Hop_ManDfs( pMan );
    Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
        pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) );
    Vec_PtrFree( vNodes );
    // connect the PO nodes
    Hop_ManForEachPo( pMan, pObj, i )
        Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) );
    if ( !Abc_NtkCheck( pNtkNew ) )
        fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" );
    return pNtkNew;
}
Exemple #11
0
/**Function*************************************************************

  Synopsis    [Parser of the formula encountered in assign statements.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage )
{
    char * pTemp;
    Hop_Obj_t * bFunc, * bTemp;
    int nParans, Flag;
	int Oper, Oper1, Oper2;
    int v;

    // clear the stacks and the names
    Vec_PtrClear( vNames );
    Vec_PtrClear( vStackFn );
    Vec_IntClear( vStackOp );

    if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1\'b0") )
        return Hop_ManConst0((Hop_Man_t *)pMan);
    if ( !strcmp(pFormula, "1") || !strcmp(pFormula, "1\'b1") )
        return Hop_ManConst1((Hop_Man_t *)pMan);

    // make sure that the number of opening and closing parantheses is the same
    nParans = 0;
    for ( pTemp = pFormula; *pTemp; pTemp++ )
        if ( *pTemp == '(' )
            nParans++;
        else if ( *pTemp == ')' )
            nParans--;
    if ( nParans != 0 )
    {
        sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." );
        return NULL;
    }
 
    // add parantheses
    pTemp = pFormula + strlen(pFormula) + 2;
    *pTemp-- = 0; *pTemp = ')';
    while ( --pTemp != pFormula )
        *pTemp = *(pTemp - 1);
    *pTemp = '(';

    // perform parsing
    Flag = VER_PARSE_FLAG_START;
    for ( pTemp = pFormula; *pTemp; pTemp++ )
	{
		switch ( *pTemp )
	    {
		// skip all spaces, tabs, and end-of-lines
        case ' ':
        case '\t':
        case '\r':
        case '\n':
			continue;
/*
		// treat Constant 0 as a variable
		case VER_PARSE_SYM_CONST0:
		    Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) );  // Cudd_Ref( Hop_ManConst0(pMan) );
			if ( Flag == VER_PARSE_FLAG_VAR )
			{
				sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." );
				Flag = VER_PARSE_FLAG_ERROR; 
                break;
			}
            Flag = VER_PARSE_FLAG_VAR; 
            break;

		// the same for Constant 1
		case VER_PARSE_SYM_CONST1:
		    Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) );  //  Cudd_Ref( Hop_ManConst1(pMan) );
			if ( Flag == VER_PARSE_FLAG_VAR )
			{
				sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." );
				Flag = VER_PARSE_FLAG_ERROR; 
                break;
			}
            Flag = VER_PARSE_FLAG_VAR; 
            break;
*/
		case VER_PARSE_SYM_NEGBEF1:
		case VER_PARSE_SYM_NEGBEF2:
			if ( Flag == VER_PARSE_FLAG_VAR )
			{// if NEGBEF follows a variable, AND is assumed
				sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." );
				Flag = VER_PARSE_FLAG_ERROR; 
                break;
			}
    		Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG );
			break;

        case VER_PARSE_SYM_AND:
        case VER_PARSE_SYM_OR:
        case VER_PARSE_SYM_XOR:
        case VER_PARSE_SYM_MUX1:
        case VER_PARSE_SYM_MUX2:
			if ( Flag != VER_PARSE_FLAG_VAR )
			{
				sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." );
				Flag = VER_PARSE_FLAG_ERROR; 
                break;
			}
			if ( *pTemp == VER_PARSE_SYM_AND )
				Vec_IntPush( vStackOp, VER_PARSE_OPER_AND );
			else if ( *pTemp == VER_PARSE_SYM_OR )
				Vec_IntPush( vStackOp, VER_PARSE_OPER_OR );
			else if ( *pTemp == VER_PARSE_SYM_XOR )
				Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR );
			else if ( *pTemp == VER_PARSE_SYM_MUX1 )
				Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX );
//			else if ( *pTemp == VER_PARSE_SYM_MUX2 )
//				Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX );
			Flag = VER_PARSE_FLAG_OPER; 
            break;

        case VER_PARSE_SYM_OPEN:
			if ( Flag == VER_PARSE_FLAG_VAR )
			{
				sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." );
				Flag = VER_PARSE_FLAG_ERROR; 
                break;
			}
			Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK );
			// after an opening bracket, it feels like starting over again
			Flag = VER_PARSE_FLAG_START; 
            break;

		case VER_PARSE_SYM_CLOSE:
			if ( Vec_IntSize( vStackOp ) )
            {
				while ( 1 )
			    {
				    if ( !Vec_IntSize( vStackOp ) )
					{
						sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" );
						Flag = VER_PARSE_FLAG_ERROR; 
                        break;
					}
					Oper = Vec_IntPop( vStackOp );
					if ( Oper == VER_PARSE_OPER_MARK )
						break;
                    // skip the second MUX operation
//                    if ( Oper == VER_PARSE_OPER_MUX2 )
//                    {
//					    Oper = Vec_IntPop( vStackOp );
//                        assert( Oper == VER_PARSE_OPER_MUX1 );
//                    }

                    // perform the given operation
                    if ( Ver_FormulaParserTopOper( (Hop_Man_t *)pMan, vStackFn, Oper ) == NULL )
	                {
		                sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" );
		                return NULL;
	                }
			    }
            }
		    else
			{
				sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" );
				Flag = VER_PARSE_FLAG_ERROR; 
                break;
			}
			if ( Flag != VER_PARSE_FLAG_ERROR )
			    Flag = VER_PARSE_FLAG_VAR; 
			break;


		default:
            // scan the next name
            v = Ver_FormulaParserFindVar( pTemp, vNames );
            if ( *pTemp == '\\' )
                pTemp++;
            pTemp += (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*v ) - 1;

			// assume operation AND, if vars follow one another
			if ( Flag == VER_PARSE_FLAG_VAR )
            {
		        sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." );
                return NULL;
            }
            bTemp = Hop_IthVar( (Hop_Man_t *)pMan, v );
			Vec_PtrPush( vStackFn, bTemp ); //  Cudd_Ref( bTemp );
            Flag = VER_PARSE_FLAG_VAR; 
            break;
	    }

		if ( Flag == VER_PARSE_FLAG_ERROR )
			break;      // error exit
		else if ( Flag == VER_PARSE_FLAG_START )
			continue;  //  go on parsing
		else if ( Flag == VER_PARSE_FLAG_VAR )
			while ( 1 )
			{  // check if there are negations in the OpStack     
				if ( !Vec_IntSize(vStackOp) )
					break;
                Oper = Vec_IntPop( vStackOp );
				if ( Oper != VER_PARSE_OPER_NEG )
                {
					Vec_IntPush( vStackOp, Oper );
					break;
                }
				else
				{
//      				Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) );
      				Vec_PtrPush( vStackFn, Hop_Not((Hop_Obj_t *)Vec_PtrPop(vStackFn)) );
				}
			}
		else // if ( Flag == VER_PARSE_FLAG_OPER )
			while ( 1 )
			{  // execute all the operations in the OpStack
			   // with precedence higher or equal than the last one
				Oper1 = Vec_IntPop( vStackOp ); // the last operation
				if ( !Vec_IntSize(vStackOp) ) 
				{  // if it is the only operation, push it back
					Vec_IntPush( vStackOp, Oper1 );
					break;
				}
				Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one
				if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) )  
				{  // if Oper2 precedence is higher or equal, execute it
                    if ( Ver_FormulaParserTopOper( (Hop_Man_t *)pMan, vStackFn, Oper2 ) == NULL )
	                {
		                sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" );
		                return NULL;
	                }
					Vec_IntPush( vStackOp,  Oper1 );     // push the last operation back
				}
				else
				{  // if Oper2 precedence is lower, push them back and done
					Vec_IntPush( vStackOp, Oper2 );
					Vec_IntPush( vStackOp, Oper1 );
					break;
				}
			}
    }

	if ( Flag != VER_PARSE_FLAG_ERROR )
    {
		if ( Vec_PtrSize(vStackFn) )
	    {	
			bFunc = (Hop_Obj_t *)Vec_PtrPop(vStackFn);
			if ( !Vec_PtrSize(vStackFn) )
				if ( !Vec_IntSize(vStackOp) )
                {
//                    Cudd_Deref( bFunc );
					return bFunc;
                }
				else
					sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" );
			else
				sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" );
	    }
	    else
			sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" );
    }
//    Cudd_Ref( bFunc );
//    Cudd_RecursiveDeref( dd, bFunc );
	return NULL;
}