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

  FileName    [wlnRtl.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Word-level network.]

  Synopsis    [Constructing WLN network from Rtl data structure.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - September 23, 2018.]

  Revision    [$Id: wlnRtl.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $]

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

#include "wln.h"
#include "aig/aig/aig.h"
#include "aig/gia/giaAig.h"
#include "base/io/ioAbc.h"
#include "base/main/main.h"

#ifdef WIN32
#include <process.h> 
#define unlink _unlink
#else
#include <unistd.h>
#endif

ABC_NAMESPACE_IMPL_START

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

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

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
#define MAX_LINE 1000000

void Rtl_NtkCleanFile( char * pFileName )
{
    char * pBuffer, * pFileName2 = "_temp__.rtlil"; 
    FILE * pFile = fopen( pFileName, "rb" );
    FILE * pFile2;
    if ( pFile == NULL )
    {
        printf( "Cannot open file \"%s\" for reading.\n", pFileName );
        return;
    }
    pFile2 = fopen( pFileName2, "wb" );
    if ( pFile2 == NULL )
    {
        fclose( pFile );
        printf( "Cannot open file \"%s\" for writing.\n", pFileName2 );
        return;
    }
    pBuffer = ABC_ALLOC( char, MAX_LINE );
    while ( fgets( pBuffer, MAX_LINE, pFile ) != NULL )
        if ( !strstr(pBuffer, "attribute \\src") )
            fputs( pBuffer, pFile2 );
    ABC_FREE( pBuffer );
    fclose( pFile );
    fclose( pFile2 );
}

void Rtl_NtkCleanFile2( char * pFileName )
{
    char * pBuffer, * pFileName2 = "_temp__.v"; 
    FILE * pFile = fopen( pFileName, "rb" );
    FILE * pFile2;
    if ( pFile == NULL )
    {
        printf( "Cannot open file \"%s\" for reading.\n", pFileName );
        return;
    }
    pFile2 = fopen( pFileName2, "wb" );
    if ( pFile2 == NULL )
    {
        fclose( pFile );
        printf( "Cannot open file \"%s\" for writing.\n", pFileName2 );
        return;
    }
    pBuffer = ABC_ALLOC( char, MAX_LINE );
    while ( fgets( pBuffer, MAX_LINE, pFile ) != NULL )
        if ( !strstr(pBuffer, "//") )
            fputs( pBuffer, pFile2 );
    ABC_FREE( pBuffer );
    fclose( pFile );
    fclose( pFile2 );
}

char * Wln_GetYosysName()
{
    char * pYosysName = NULL;
    char * pYosysNameWin = "yosys.exe";
    char * pYosysNameUnix = "yosys";
    if ( Abc_FrameReadFlag("yosyswin") )
        pYosysNameWin = Abc_FrameReadFlag("yosyswin");
    if ( Abc_FrameReadFlag("yosysunix") )
        pYosysNameUnix = Abc_FrameReadFlag("yosysunix");
#ifdef WIN32
    pYosysName = pYosysNameWin;
#else
    pYosysName = pYosysNameUnix;
#endif
    return pYosysName;
}
int Wln_ConvertToRtl( char * pCommand, char * pFileTemp )
{
#if defined(__wasm)
    return 0;
#else
    FILE * pFile;
    if ( system( pCommand ) == -1 )
    {
        fprintf( stdout, "Cannot execute \"%s\".\n", pCommand );
        return 0;
    }
    if ( (pFile = fopen(pFileTemp, "r")) == NULL )
    {
        fprintf( stdout, "Cannot open intermediate file \"%s\".\n", pFileTemp );
        return 0;
    }
    fclose( pFile );
    return 1;
#endif
}
Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fCollapse, int fVerbose )
{
    Rtl_Lib_t * pNtk = NULL;
    char Command[1000];
    char * pFileTemp = "_temp_.rtlil";
    int fSVlog = strstr(pFileName, ".sv") != NULL;
    if ( strstr(pFileName, ".rtl") )
        return Rtl_LibReadFile( pFileName, pFileName );
    sprintf( Command, "%s -qp \"read_verilog %s%s %s%s; hierarchy %s%s; %sproc; memory -nomap; memory_map; write_rtlil %s\"",
        Wln_GetYosysName(), 
        pDefines   ? "-D"       : "",
        pDefines   ? pDefines   : "",
        fSVlog     ? "-sv "     : "",
        pFileName,
        pTopModule ? "-top "    : "", 
        pTopModule ? pTopModule : "", 
        fCollapse  ? "flatten; ": "",
        pFileTemp );
    if ( fVerbose )
    printf( "%s\n", Command );
    if ( !Wln_ConvertToRtl(Command, pFileTemp) )
        return NULL;
    pNtk = Rtl_LibReadFile( pFileTemp, pFileName );
    if ( pNtk == NULL )
    {
        printf( "Dumped the design into file \"%s\".\n", pFileTemp );
        return NULL;
    }
    Rtl_NtkCleanFile( pFileTemp );
    unlink( pFileTemp );
    return pNtk;
}
Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pFileName2, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose )
{
    Gia_Man_t * pGia = NULL;
    char Command[1000];
    char * pFileTemp = "_temp_.aig";
    int fRtlil = strstr(pFileName, ".rtl") != NULL;
    int fSVlog = strstr(pFileName, ".sv")  != NULL || (pFileName2 && strstr(pFileName2, ".sv") != NULL);
    sprintf( Command, "%s -qp \"%s %s%s %s%s%s%s; hierarchy %s%s; flatten; proc; opt; async2sync; opt; setundef -undriven -zero; %s%smemory -nomap; memory_map; dffunmap; opt_clean; opt_expr; %saigmap; write_aiger -symbols %s\"",
        Wln_GetYosysName(), 
        fRtlil ? "read_rtlil"   : "read_verilog",
        pDefines  ? "-D"        : "",
        pDefines  ? pDefines    : "",
        fSVlog    ? "-sv "      : "",
        pFileName,
        pFileName2 ? " "        : "",
        pFileName2 ? pFileName2 : "",
        pTopModule ? "-top "    : "-auto-top",
        pTopModule ? pTopModule : "", 
        fTechMap ? (fLibInDir ? "techmap -map techmap.v; " : "techmap; ") : "",
        fSetUndef ? "setundef -init -zero; " : "",
        pFileName2 ? "delete t:\\$scopeinfo; " : "",
        pFileTemp );
    if ( fVerbose )
    printf( "%s\n", Command );
    if ( !Wln_ConvertToRtl(Command, pFileTemp) )
        return NULL;
    if ( pFileName2 )
    {
        extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
        Aig_Man_t * pAig = NULL;
        Abc_Ntk_t * pNtk = Io_Read( pFileTemp, IO_FILE_AIGER, 1, 0 );
        if ( pNtk == NULL )
        {
            printf( "Reading AIGER from file \"%s\" has failed.\n", pFileTemp );
            return NULL;
        }
        pAig = Abc_NtkToDar( pNtk, 0, 1 );
        Abc_NtkDelete( pNtk );
        if ( pAig == NULL )
        {
            printf( "Converting the AIGER network into an internal AIG has failed.\n" );
            return NULL;
        }
        pGia = fSkipStrash ? Gia_ManFromAigSimple(pAig) : Gia_ManFromAig(pAig);
        Aig_ManStop( pAig );
    }
    else
        pGia = Gia_AigerRead( pFileTemp, 0, fSkipStrash, 0 );
    if ( pGia == NULL )
    {
        printf( "Converting to AIG has failed.\n" );
        return NULL;
    }
    ABC_FREE( pGia->pName );
    pGia->pName = pTopModule ? Abc_UtilStrsav(pTopModule) :
        Extra_FileNameGeneric( Extra_FileNameWithoutPath(pFileName) );
    unlink( pFileTemp );
    // complement the outputs
    if ( fInvert )
    {
        Gia_Obj_t * pObj; int i;
        Gia_ManForEachPo( pGia, pObj, i )
            Gia_ObjFlipFaninC0( pObj );
    }
    return pGia;
}
Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose )
{
    Abc_Ntk_t * pNtk = NULL;
    char Command[1000];
    char * pFileTemp = "_temp_.blif";
    int fSVlog = strstr(pFileName, ".sv")  != NULL;
    sprintf( Command, "%s -qp \"read_liberty -lib %s; read %s %s%s %s; hierarchy %s%s; flatten; proc; memory -nomap; memory_map; write_blif %s%s -impltf -gates %s\"",
        Wln_GetYosysName(),
        pLibrary,
        fSVlog    ? "-sv "      : "-vlog95",
        pDefines  ? "-D"        : "",
        pDefines  ? pDefines    : "",
        pFileName,
        pTopModule ? "-top "    : "-auto-top",
        pTopModule ? pTopModule : "",
        pTopModule ? "-top "    : "",
        pTopModule ? pTopModule : "",
        pFileTemp );
    if ( fVerbose )
    printf( "%s\n", Command );
    if ( !Wln_ConvertToRtl(Command, pFileTemp) )
        return NULL;
    sprintf( Command, "read_lib %s", pLibrary );
    if ( Cmd_CommandExecute( Abc_FrameReadGlobalFrame(), Command ) )
    {
        fprintf( stdout, "Cannot execute ABC command \"%s\".\n", Command );
        unlink( pFileTemp );
        return NULL;
    }
    pNtk = Io_Read( pFileTemp, IO_FILE_BLIF, 1, 0 );
    if ( pNtk == NULL )
    {
        printf( "Reading mapped BLIF from file \"%s\" has failed.\n", pFileTemp );
        return NULL;
    }
    if ( pTopModule ) {
        ABC_FREE( pNtk->pName );
        pNtk->pName = Abc_UtilStrsav(pTopModule);
    }
    unlink( pFileTemp );
    return pNtk;
}

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


ABC_NAMESPACE_IMPL_END
