/**CFile****************************************************************

  FileName    [cbaReadBlif.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Hierarchical word-level netlist.]

  Synopsis    [BLIF parser.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - November 29, 2014.]

  Revision    [$Id: cbaReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]

***********************************************************************/

#include "cba.h"
#include "cbaPrs.h"

ABC_NAMESPACE_IMPL_START

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

// BLIF keywords
typedef enum { 
    PRS_BLIF_NONE = 0, // 0:   unused
    PRS_BLIF_MODEL,    // 1:   .model
    PRS_BLIF_INOUTS,   // 2:   .inouts
    PRS_BLIF_INPUTS,   // 3:   .inputs
    PRS_BLIF_OUTPUTS,  // 4:   .outputs
    PRS_BLIF_NAMES,    // 5:   .names
    PRS_BLIF_SUBCKT,   // 6:   .subckt
    PRS_BLIF_GATE,     // 7:   .gate
    PRS_BLIF_LATCH,    // 8:   .latch
    PRS_BLIF_SHORT,    // 9:   .short
    PRS_BLIF_END,      // 10:  .end
    PRS_BLIF_UNKNOWN   // 11:  unknown
} Cba_BlifType_t;

static const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = {
    NULL,              // 0:   unused
    ".model",          // 1:   .model   
    ".inouts",         // 2:   .inputs
    ".inputs",         // 3:   .inputs
    ".outputs",        // 4:   .outputs
    ".names",          // 5:   .names
    ".subckt",         // 6:   .subckt
    ".gate",           // 7:   .gate
    ".latch",          // 8:   .latch
    ".short",          // 9:   .short
    ".end",            // 10:  .end
    NULL               // 11:  unknown
};

static inline void Prs_NtkAddBlifDirectives( Prs_Man_t * p )
{
    int i;
    for ( i = 1; s_BlifTypes[i]; i++ )
        Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL );
    assert( Abc_NamObjNumMax(p->pStrs) == i );
}


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

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

  Synopsis    [Reading characters.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int  Prs_CharIsSpace( char c )                { return c == ' ' || c == '\t' || c == '\r';              }
static inline int  Prs_CharIsStop( char c )                 { return c == '#' || c == '\\' || c == '\n' || c == '=';  }
static inline int  Prs_CharIsLit( char c )                  { return c == '0' || c == '1'  || c == '-';               }

static inline int  Prs_ManIsSpace( Prs_Man_t * p )          { return Prs_CharIsSpace(*p->pCur);                       }
static inline int  Prs_ManIsStop( Prs_Man_t * p )           { return Prs_CharIsStop(*p->pCur);                        }
static inline int  Prs_ManIsLit( Prs_Man_t * p )            { return Prs_CharIsLit(*p->pCur);                         }

static inline int  Prs_ManIsChar( Prs_Man_t * p, char c )   { return *p->pCur == c;                                   }
static inline int  Prs_ManIsChar2( Prs_Man_t * p, char c )  { return *p->pCur++ == c;                                 }

static inline void Prs_ManSkip( Prs_Man_t * p )             { p->pCur++;                                              }
static inline char Prs_ManSkip2( Prs_Man_t * p )            { return *p->pCur++;                                      }


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

  Synopsis    [Reading names.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Prs_ManSkipToChar( Prs_Man_t * p, char c )  
{ 
    while ( !Prs_ManIsChar(p, c) ) 
        Prs_ManSkip(p);
}
static inline void Prs_ManSkipSpaces( Prs_Man_t * p )
{
    while ( 1 )
    {
        while ( Prs_ManIsSpace(p) )
            Prs_ManSkip(p);
        if ( Prs_ManIsChar(p, '\\') )
        {
            Prs_ManSkipToChar( p, '\n' );
            Prs_ManSkip(p);
            continue;
        }
        if ( Prs_ManIsChar(p, '#') )  
            Prs_ManSkipToChar( p, '\n' );
        break;
    }
    assert( !Prs_ManIsSpace(p) );
}
static inline int Prs_ManReadName( Prs_Man_t * p )
{
    char * pStart;
    Prs_ManSkipSpaces( p );
    if ( Prs_ManIsChar(p, '\n') )
        return 0;
    pStart = p->pCur;
    while ( !Prs_ManIsSpace(p) && !Prs_ManIsStop(p) )
        Prs_ManSkip(p);
    if ( pStart == p->pCur )
        return 0;
    return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
}
static inline int Prs_ManReadList( Prs_Man_t * p, Vec_Int_t * vOrder, int Type )
{
    int iToken;
    Vec_IntClear( &p->vTemp );
    while ( (iToken = Prs_ManReadName(p)) )
    {
        Vec_IntPush( &p->vTemp, iToken );
        Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) );
    }
    if ( Vec_IntSize(&p->vTemp) == 0 )                return Prs_ManErrorSet(p, "Signal list is empty.", 1);
    return 0;
}
static inline int Prs_ManReadList2( Prs_Man_t * p )
{
    int iToken;
    Vec_IntClear( &p->vTemp );
    while ( (iToken = Prs_ManReadName(p)) )
        Vec_IntPushTwo( &p->vTemp, 0, iToken );
    if ( Vec_IntSize(&p->vTemp) == 0 )                return Prs_ManErrorSet(p, "Signal list is empty.", 1);
    return 0;
}
static inline int Prs_ManReadList3( Prs_Man_t * p )
{
    Vec_IntClear( &p->vTemp );
    while ( !Prs_ManIsChar(p, '\n') )
    {
        int iToken = Prs_ManReadName(p);
        if ( iToken == 0 )              return Prs_ManErrorSet(p, "Cannot read formal name.", 1);
        Vec_IntPush( &p->vTemp, iToken );
        Prs_ManSkipSpaces( p );
        if ( !Prs_ManIsChar2(p, '=') )  return Prs_ManErrorSet(p, "Cannot find symbol \"=\".", 1);
        iToken = Prs_ManReadName(p);
        if ( iToken == 0 )              return Prs_ManErrorSet(p, "Cannot read actual name.", 1);
        Vec_IntPush( &p->vTemp, iToken );
        Prs_ManSkipSpaces( p );
    }
    if ( Vec_IntSize(&p->vTemp) == 0 )  return Prs_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1);
    if ( Vec_IntSize(&p->vTemp) % 2  )  return Prs_ManErrorSet(p, "The number of formal/actual names is not even.", 1);
    return 0;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Prs_ManReadCube( Prs_Man_t * p )
{
    assert( Prs_ManIsLit(p) );
    while ( Prs_ManIsLit(p) )
        Vec_StrPush( &p->vCover, Prs_ManSkip2(p) );
    Prs_ManSkipSpaces( p );
    if ( Prs_ManIsChar(p, '\n') )
    {
        if ( Vec_StrSize(&p->vCover) != 1 )           return Prs_ManErrorSet(p, "Cannot read cube.", 1);
        // fix single literal cube by adding space
        Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) );
        Vec_StrWriteEntry( &p->vCover, 0, ' ' );
        Vec_StrPush( &p->vCover, '\n' );
        return 0;
    }
    if ( !Prs_ManIsLit(p) )                           return Prs_ManErrorSet(p, "Cannot read output literal.", 1);
    Vec_StrPush( &p->vCover, ' ' );
    Vec_StrPush( &p->vCover, Prs_ManSkip2(p) );
    Vec_StrPush( &p->vCover, '\n' );
    Prs_ManSkipSpaces( p );
    if ( !Prs_ManIsChar(p, '\n') )                    return Prs_ManErrorSet(p, "Cannot read end of cube.", 1);
    return 0;
}
static inline void Prs_ManSaveCover( Prs_Man_t * p )
{
    int iToken;
    if ( Vec_StrSize(&p->vCover) == 0 )
        p->pNtk->fHasC0s = 1;
    else if ( Vec_StrSize(&p->vCover) == 2 )
    {
        if ( Vec_StrEntryLast(&p->vCover) == '0' )
            p->pNtk->fHasC0s = 1;
        else if ( Vec_StrEntryLast(&p->vCover) == '1' )
            p->pNtk->fHasC1s = 1;
        else assert( 0 );
    }
    assert( Vec_StrSize(&p->vCover) > 0 );
    Vec_StrPush( &p->vCover, '\0' );
//    iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) );
    iToken = Abc_NamStrFindOrAdd( p->pFuns, Vec_StrArray(&p->vCover), NULL );
    Vec_StrClear( &p->vCover );
    // set the cover to the module of this box
    assert( Prs_BoxNtk(p->pNtk, Prs_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0
    Prs_BoxSetNtk( p->pNtk, Prs_NtkBoxNum(p->pNtk)-1, iToken );
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Prs_ManReadInouts( Prs_Man_t * p )
{
    if ( Prs_ManReadList(p, &p->pNtk->vOrder, 3) )    return 1;
    Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp );
    return 0;
}
static inline int Prs_ManReadInputs( Prs_Man_t * p )
{
    if ( Prs_ManReadList(p, &p->pNtk->vOrder, 1) )    return 1;
    Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp );
    return 0;
}
static inline int Prs_ManReadOutputs( Prs_Man_t * p )
{
    if ( Prs_ManReadList(p, &p->pNtk->vOrder, 2) )    return 1;
    Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp );
    return 0;
}
static inline int Prs_ManReadNode( Prs_Man_t * p )
{
    if ( Prs_ManReadList2(p) )   return 1;
    // save results
    Prs_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function
    return 0;
}
static inline int Prs_ManReadBox( Prs_Man_t * p, int fGate )
{
    int iToken = Prs_ManReadName(p);
    if ( iToken == 0 )           return Prs_ManErrorSet(p, "Cannot read model name.", 1);
    if ( Prs_ManReadList3(p) )   return 1;
    // save results
    Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
    if ( fGate ) p->pNtk->fMapped = 1;
    return 0;
}
static inline int Prs_ManReadLatch( Prs_Man_t * p )
{
    int iToken = Prs_ManReadName(p);
    Vec_IntClear( &p->vTemp );
    if ( iToken == 0 )                 return Prs_ManErrorSet(p, "Cannot read latch input.", 1);
    Vec_IntWriteEntry( &p->vTemp, 1, iToken );
    iToken = Prs_ManReadName(p);
    if ( iToken == 0 )                 return Prs_ManErrorSet(p, "Cannot read latch output.", 1);
    Vec_IntWriteEntry( &p->vTemp, 0, iToken );
    Prs_ManSkipSpaces( p );
    if ( Prs_ManIsChar(p, '0') )
        iToken = 0;
    else if ( Prs_ManIsChar(p, '1') )
        iToken = 1;
    else 
        iToken = 2;
    Prs_ManSkipToChar( p, '\n' );
    // save results
    Prs_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch
    return 0;
}
static inline int Prs_ManReadShort( Prs_Man_t * p )
{
    int iToken = Prs_ManReadName(p);
    Vec_IntClear( &p->vTemp );
    if ( iToken == 0 )                 return Prs_ManErrorSet(p, "Cannot read .short input.", 1);
    Vec_IntWriteEntry( &p->vTemp, 1, iToken );
    iToken = Prs_ManReadName(p);
    if ( iToken == 0 )                 return Prs_ManErrorSet(p, "Cannot read .short output.", 1);
    Vec_IntWriteEntry( &p->vTemp, 0, iToken );
    Prs_ManSkipSpaces( p );
    if ( !Prs_ManIsChar(p, '\n') )     return Prs_ManErrorSet(p, "Trailing symbols on .short line.", 1);
    // save results
    iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL );
    Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
    return 0;
}
static inline int Prs_ManReadModel( Prs_Man_t * p )
{
    int iToken;
    if ( p->pNtk != NULL )                         return Prs_ManErrorSet(p, "Parsing previous model is unfinished.", 1);
    iToken = Prs_ManReadName(p);
    if ( iToken == 0 )                             return Prs_ManErrorSet(p, "Cannot read model name.", 1);
    Prs_ManInitializeNtk( p, iToken, 0 );
    Prs_ManSkipSpaces( p );
    if ( !Prs_ManIsChar(p, '\n') )                 return Prs_ManErrorSet(p, "Trailing symbols on .model line.", 1);
    return 0;
}
static inline int Prs_ManReadEnd( Prs_Man_t * p )
{
    if ( p->pNtk == 0 )                            return Prs_ManErrorSet(p, "Directive .end without .model.", 1);
    //printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) );
    Prs_ManFinalizeNtk( p );
    Prs_ManSkipSpaces( p );
    if ( !Prs_ManIsChar(p, '\n') )                 return Prs_ManErrorSet(p, "Trailing symbols on .end line.", 1);
    return 0;
}

static inline int Prs_ManReadDirective( Prs_Man_t * p )
{
    int iToken;
    if ( !Prs_ManIsChar(p, '.') )
        return Prs_ManReadCube( p );
    if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node
        Prs_ManSaveCover( p );
    iToken = Prs_ManReadName( p );  
    if ( iToken == PRS_BLIF_MODEL )
        return Prs_ManReadModel( p );
    if ( iToken == PRS_BLIF_INOUTS )
        return Prs_ManReadInouts( p );
    if ( iToken == PRS_BLIF_INPUTS )
        return Prs_ManReadInputs( p );
    if ( iToken == PRS_BLIF_OUTPUTS )
        return Prs_ManReadOutputs( p );
    if ( iToken == PRS_BLIF_NAMES )
        return Prs_ManReadNode( p );
    if ( iToken == PRS_BLIF_SUBCKT )
        return Prs_ManReadBox( p, 0 );
    if ( iToken == PRS_BLIF_GATE )
        return Prs_ManReadBox( p, 1 );
    if ( iToken == PRS_BLIF_LATCH )
        return Prs_ManReadLatch( p );
    if ( iToken == PRS_BLIF_SHORT )
        return Prs_ManReadShort( p );
    if ( iToken == PRS_BLIF_END )
        return Prs_ManReadEnd( p );
    printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
    return 1;
}
static inline int Prs_ManReadLines( Prs_Man_t * p )
{
    while ( p->pCur[1] != '\0' )
    {
        assert( Prs_ManIsChar(p, '\n') );
        Prs_ManSkip(p);
        Prs_ManSkipSpaces( p );
        if ( Prs_ManIsChar(p, '\n') )
            continue;
        if ( Prs_ManReadDirective(p) )   
            return 1;
    }
    return 0;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Vec_Ptr_t * Prs_ManReadBlif( char * pFileName )
{
    Vec_Ptr_t * vPrs = NULL;
    Prs_Man_t * p = Prs_ManAlloc( pFileName );
    if ( p == NULL )
        return NULL;
    Abc_NamStrFindOrAdd( p->pFuns, " 0\n", NULL );
    Abc_NamStrFindOrAdd( p->pFuns, " 1\n", NULL );
    Prs_NtkAddBlifDirectives( p );
    Prs_ManReadLines( p );
    if ( Prs_ManErrorPrint(p) )
        ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
    Prs_ManFree( p );
    return vPrs;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Prs_ManReadBlifTest( char * pFileName )
{
    abctime clk = Abc_Clock();
    Vec_Ptr_t * vPrs = Prs_ManReadBlif( pFileName );
    if ( !vPrs ) return;
    printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
    printf( "NameIDs = %d. ", Abc_NamObjNumMax(Prs_ManNameMan(vPrs)) );
    printf( "Memory = %.2f MB. ", 1.0*Prs_ManMemory(vPrs)/(1<<20) );
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
//    Abc_NamPrint( p->pStrs );
    Prs_ManWriteBlif( Extra_FileNameGenericAppend(pFileName, "_out.blif"), vPrs );
    Prs_ManVecFree( vPrs );
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Prs_CreateBlifFindFon( Cba_Ntk_t * p, int NameId )
{
    int iFon = Cba_NtkGetMap( p, NameId );
    if ( iFon )
        return iFon;
    printf( "Network \"%s\": Signal \"%s\" is not driven.\n", Cba_NtkName(p), Cba_NtkStr(p, NameId) );
    return 0;
}
void Prs_CreateBlifPio( Cba_Ntk_t * p, Prs_Ntk_t * pNtk )
{
    int i, NameId, iObj, iFon;
    Cba_NtkCleanObjFuncs( p );
    Cba_NtkCleanObjNames( p );
    Cba_NtkCleanFonNames( p );
    // create inputs
    Prs_NtkForEachPi( pNtk, NameId, i )
    {
        iObj = Cba_ObjAlloc( p, CBA_OBJ_PI, 0, 1 );
        Cba_ObjSetName( p, iObj, NameId );
        iFon = Cba_ObjFon0(p, iObj);
        Cba_FonSetName( p, iFon, NameId );
        Cba_NtkSetMap( p, NameId, iFon );
        Vec_IntPush( &p->vOrder, iObj );
    }
    // create outputs
    Prs_NtkForEachPo( pNtk, NameId, i )
    {
        iObj = Cba_ObjAlloc( p, CBA_OBJ_PO, 1, 0 );
        Cba_ObjSetName( p, iObj, NameId );
        Vec_IntPush( &p->vOrder, iObj );
    }
}
int Prs_CreateBlifNtk( Cba_Ntk_t * p, Prs_Ntk_t * pNtk )
{
    Vec_Int_t * vBox;
    int i, k, iObj, iTerm, iFon, FormId, ActId;
    // map inputs
    Cba_NtkCleanMap( p );
    Cba_NtkForEachPi( p, iObj, i )
        Cba_NtkSetMap( p, Cba_ObjName(p, iObj), Cba_ObjFon0(p, iObj) );
    // create objects
    Prs_NtkForEachBox( pNtk, vBox, i )
    {
        int FuncId = Prs_BoxNtk(pNtk, i);
        assert( Prs_BoxIONum(pNtk, i) > 0 );
        assert( Vec_IntSize(vBox) % 2 == 0 );
        if ( FuncId == -1 ) // latch
        {
            iObj = Cba_ObjAlloc( p, CBA_BOX_DFFRS, 4, 1 );
            Cba_NtkSetMap( p, Vec_IntEntry(vBox, 3), Cba_ObjFon0(p, iObj) ); // latch output
            Cba_ObjSetFunc( p, iObj, Prs_BoxName(pNtk, i)+1 ); // init + 1
        }
        else if ( Prs_BoxIsNode(pNtk, i) ) // node
        {
            iObj = Cba_ObjAlloc( p, CBA_BOX_NODE, Prs_BoxIONum(pNtk, i)-1, 1 );
            Cba_FonSetName( p, Cba_ObjFon0(p, iObj), Vec_IntEntryLast(vBox) ); // node output
            Cba_NtkSetMap( p, Vec_IntEntryLast(vBox), Cba_ObjFon0(p, iObj) );
            Cba_ObjSetFunc( p, iObj, FuncId );
        }
        else // box
        {
            Cba_Ntk_t * pBox = Cba_ManNtkFind( p->pDesign, Prs_NtkStr(pNtk, FuncId) );
            iObj = Cba_ObjAlloc( p, CBA_OBJ_BOX, Cba_NtkPiNum(pBox), Cba_NtkPoNum(pBox) );
            Cba_ObjSetFunc( p, iObj, Cba_NtkId(pBox) );
            // mark PO objects
            Cba_NtkCleanMap2( p );
            Cba_NtkForEachPo( pBox, iTerm, k )
                Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 );
            // map box fons
            Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
                if ( Cba_NtkGetMap2(p, FormId) )
                {
                    iFon = Cba_ObjFon(p, iObj, Cba_NtkGetMap2(p, FormId)-1);
                    Cba_FonSetName( p, iFon, ActId );
                    Cba_NtkSetMap( p, ActId, iFon );
                }
        }
    }
    // connect objects
    Prs_NtkForEachBox( pNtk, vBox, i )
    {
        iObj = Cba_NtkPiNum(p) + Cba_NtkPoNum(p) + i + 1;
        if ( Prs_BoxNtk(pNtk, i) == -1 ) // latch
        {
            assert( Cba_ObjType(p, iObj) == CBA_BOX_DFFRS );
            iFon = Prs_CreateBlifFindFon( p, Vec_IntEntry(vBox, 1) ); // latch input
            if ( iFon )
                Cba_ObjSetFinFon( p, iObj, 0, iFon );
        }
        else if ( Prs_BoxIsNode(pNtk, i) ) // node
        {
            assert( Cba_ObjType(p, iObj) == CBA_BOX_NODE );
            Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
            {
                if ( k == 2 * Cba_ObjFinNum(p, iObj) ) // stop at node output
                    break;
                iFon = Prs_CreateBlifFindFon( p, ActId );
                if ( iFon )
                    Cba_ObjSetFinFon( p, iObj, k/2, iFon ); 
            }
        }
        else // box
        {
            // mark PI objects
            Cba_Ntk_t * pBox = Cba_ObjNtk(p, iObj);
            assert( Cba_NtkPiNum(pBox) == Cba_ObjFinNum(p, iObj) );
            assert( Cba_NtkPoNum(pBox) == Cba_ObjFonNum(p, iObj) );
            Cba_NtkCleanMap2( p );
            Cba_NtkForEachPi( pBox, iTerm, k )
                Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 );
            // connect box fins
            Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
                if ( Cba_NtkGetMap2(p, FormId) )
                {
                    iFon = Prs_CreateBlifFindFon( p, ActId );
                    if ( iFon )
                        Cba_ObjSetFinFon( p, iObj, Cba_NtkGetMap2(p, FormId)-1, iFon );
                }
        }
    }
    // connect outputs
    Cba_NtkForEachPo( p, iObj, i )
    {
        iFon = Prs_CreateBlifFindFon( p, Cba_ObjName(p, iObj) );
        if ( iFon )
            Cba_ObjSetFinFon( p, iObj, 0, iFon );
    }
    return 0;
}
Cba_Man_t * Prs_ManBuildCbaBlif( char * pFileName, Vec_Ptr_t * vDes )
{
    Prs_Ntk_t * pPrsNtk; int i, fError = 0;
    Prs_Ntk_t * pPrsRoot = Prs_ManRoot(vDes);
    // start the manager
    Abc_Nam_t * pStrs = Abc_NamRef(pPrsRoot->pStrs);
    Abc_Nam_t * pFuns = Abc_NamRef(pPrsRoot->pFuns);
    Abc_Nam_t * pMods = Abc_NamStart( 100, 24 );
    Cba_Man_t * p = Cba_ManAlloc( pFileName, Vec_PtrSize(vDes), pStrs, pFuns, pMods );
    // initialize networks
    Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i )
    {
        Cba_Ntk_t * pNtk = Cba_NtkAlloc( p, Prs_NtkId(pPrsNtk), Prs_NtkPiNum(pPrsNtk), Prs_NtkPoNum(pPrsNtk), Prs_NtkObjNum(pPrsNtk), 100, 100 );
        Prs_CreateBlifPio( pNtk, pPrsNtk );
        Cba_NtkAdd( p, pNtk );
    }
    // create networks
    Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i )
    {
        printf( "Elaboration module \"%s\"...\n", Prs_NtkName(pPrsNtk) );
        fError = Prs_CreateBlifNtk( Cba_ManNtk(p, i+1), pPrsNtk );
        if ( fError )
            break;
    }
    if ( fError )
        printf( "Quitting because of errors.\n" );
    else
        Cba_ManPrepareSeq( p );
    return p;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Cba_Man_t * Cba_ManReadBlif( char * pFileName )
{
    Cba_Man_t * p = NULL;
    Vec_Ptr_t * vDes = Prs_ManReadBlif( pFileName );
    if ( vDes && Vec_PtrSize(vDes) )
        p = Prs_ManBuildCbaBlif( pFileName, vDes );
    if ( vDes )
        Prs_ManVecFree( vDes );
    return p;
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END

