diff options
Diffstat (limited to 'abc70930/src/base/io')
29 files changed, 13071 insertions, 0 deletions
diff --git a/abc70930/src/base/io/io.c b/abc70930/src/base/io/io.c new file mode 100644 index 00000000..7a5e4a5d --- /dev/null +++ b/abc70930/src/base/io/io.c @@ -0,0 +1,1954 @@ +/**CFile**************************************************************** + + FileName [io.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Command file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "mainInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int IoCommandRead ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBench ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadDsd ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadEdif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadInit ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadTruth ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVer ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVerLib ( Abc_Frame_t * pAbc, int argc, char **argv ); + +static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteDot ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteGml ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteList ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteVerLib ( Abc_Frame_t * pAbc, int argc, char **argv ); + +extern int glo_fMapped; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_Init( Abc_Frame_t * pAbc ) +{ + Cmd_CommandAdd( pAbc, "I/O", "read", IoCommandRead, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_aiger", IoCommandReadAiger, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_baf", IoCommandReadBaf, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_blif", IoCommandReadBlif, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_blif_mv", IoCommandReadBlifMv, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_bench", IoCommandReadBench, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_dsd", IoCommandReadDsd, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_eqn", IoCommandReadEqn, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_init", IoCommandReadInit, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_truth", IoCommandReadTruth, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_ver", IoCommandReadVer, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_verlib", IoCommandReadVerLib, 0 ); + + Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_aiger", IoCommandWriteAiger, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_baf", IoCommandWriteBaf, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_counter", IoCommandWriteCounter, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_dot", IoCommandWriteDot, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_eqn", IoCommandWriteEqn, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 ); +// Cmd_CommandAdd( pAbc, "I/O", "write_list", IoCommandWriteList, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_verilog", IoCommandWriteVerilog, 0 ); +// Cmd_CommandAdd( pAbc, "I/O", "write_verlib", IoCommandWriteVerLib, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_End() +{ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read [-mch] <file>\n" ); + fprintf( pAbc->Err, "\t replaces the current network by the network read from <file>\n" ); + fprintf( pAbc->Err, "\t by calling the parser that matches the extension of <file>\n" ); + fprintf( pAbc->Err, "\t (to read a hierarchical design, use \"read_hie\")\n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_AIGER, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_aiger [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BAF, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_baf [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in Binary Aig Format (BAF)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fReadAsAig; + int fCheck; + int c; + extern Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ); + + fCheck = 1; + fReadAsAig = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fReadAsAig ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + if ( fReadAsAig ) + pNtk = Io_ReadBlifAsAig( pFileName, fCheck ); + else +// pNtk = Io_Read( pFileName, IO_FILE_BLIF, fCheck ); + { + Abc_Ntk_t * pTemp; + pNtk = Io_ReadBlif( pFileName, fCheck ); + pNtk = Abc_NtkToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + } + + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_blif [-ach] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in binary BLIF format\n" ); + fprintf( pAbc->Err, "\t-a : toggle creating AIG while reading the file [default = %s]\n", fReadAsAig? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BLIFMV, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_blif_mv [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in BLIF-MV format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BENCH, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_bench [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pString; + int fCheck; + int c; + extern Abc_Ntk_t * Io_ReadDsd( char * pFormula ); + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pString = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_ReadDsd( pString ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_dsd [-h] <formula>\n" ); + fprintf( pAbc->Err, "\t parses a formula representing DSD of a function\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tformula : the formula representing disjoint-support decomposition (DSD)\n" ); + fprintf( pAbc->Err, "\t Example of a formula: !(a*(b+CA(!d,e*f,c))*79B3(g,h,i,k))\n" ); + fprintf( pAbc->Err, "\t where \'!\' is an INV, \'*\' is an AND, \'+\' is an XOR, \n" ); + fprintf( pAbc->Err, "\t CA and 79B3 are hexadecimal representations of truth tables\n" ); + fprintf( pAbc->Err, "\t (in this case CA=11001010 is truth table of MUX(Data0,Data1,Ctrl))\n" ); + fprintf( pAbc->Err, "\t The lower chars (a,b,c,etc) are reserved for elementary variables.\n" ); + fprintf( pAbc->Err, "\t The upper chars (A,B,C,etc) are reserved for hexadecimal digits.\n" ); + fprintf( pAbc->Err, "\t No spaces are allowed in formulas. In parantheses, LSB goes first.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_EDIF, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_edif [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in EDIF (works only for ISCAS benchmarks)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_EQN, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_eqn [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in equation format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + extern void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Abc_NtkDup( pNtk ); + Io_ReadBenchInit( pNtk, pFileName ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_init [-h] <file>\n" ); + fprintf( pAbc->Err, "\t reads initial state of the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_PLA, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_pla [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in PLA\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pSopCover; + int fHex; + int c; + + fHex = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF ) + { + switch ( c ) + { + case 'x': + fHex ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // convert truth table to SOP + if ( fHex ) + pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]); + else + pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]); + if ( pSopCover == NULL ) + { + fprintf( pAbc->Err, "Reading truth table has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkCreateWithNode( pSopCover ); + free( pSopCover ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Deriving the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_truth [-xh] <truth>\n" ); + fprintf( pAbc->Err, "\t creates network with node having given truth table\n" ); + fprintf( pAbc->Err, "\t-x : toggles between bin and hex representation [default = %s]\n", fHex? "hex":"bin" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\ttruth : truth table with most signficant bit first (e.g. 1000 for AND(a,b))\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_VERILOG, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_verilog [-mch] <file>\n" ); + fprintf( pAbc->Err, "\t read the network in Verilog (IWLS 2002/2005 subset)\n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVer( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkNew; + Abc_Lib_t * pDesign; + char * pFileName; + FILE * pFile; + int fCheck; + int c; + extern Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ); + extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + + printf( "Stand-alone structural Verilog reader is available as command \"read_verilog\".\n" ); + return 0; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pDesign = Ver_ParseFile( pFileName, Abc_FrameReadLibVer(), fCheck, 1 ); + if ( pDesign == NULL ) + { + fprintf( pAbc->Err, "Reading network from the verilog file has failed.\n" ); + return 1; + } + + // derive root design + pNtk = Abc_LibDeriveRoot( pDesign ); + Abc_LibFree( pDesign, NULL ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Deriving root module has failed.\n" ); + return 1; + } + + // derive the AIG network from this design + pNtkNew = Abc_LibDeriveAig( pNtk, Abc_FrameReadLibVer() ); + Abc_NtkDelete( pNtk ); + if ( pNtkNew == NULL ) + { + fprintf( pAbc->Err, "Converting root module to AIG has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_ver [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read a network in structural verilog (using current library)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVerLib( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Lib_t * pLibrary; + char * pFileName; + FILE * pFile; + int fCheck; + int c; + extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pLibrary = Ver_ParseFile( pFileName, NULL, fCheck, 0 ); + if ( pLibrary == NULL ) + { + fprintf( pAbc->Err, "Reading library from the verilog file has failed.\n" ); + return 1; + } + printf( "The library contains %d gates.\n", st_count(pLibrary->tModules) ); + // free old library + if ( Abc_FrameReadLibVer() ) + Abc_LibFree( Abc_FrameReadLibVer(), NULL ); + // read new library + Abc_FrameSetLibVer( pLibrary ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_verlib [-ch] <file>\n" ); + fprintf( pAbc->Err, "\t read a gate library in structural verilog\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWrite( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write [-h] <file>\n" ); + fprintf( pAbc->Err, "\t writes the current network into <file> by calling\n" ); + fprintf( pAbc->Err, "\t the writer that matches the extension of <file>\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteHie( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pBaseName, * pFileName; + int c; + + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 2 ) + goto usage; + // get the output file name + pBaseName = argv[globalUtilOptind]; + pFileName = argv[globalUtilOptind+1]; + // call the corresponding file writer +// Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); + Io_WriteHie( pAbc->pNtkCur, pBaseName, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_hie [-h] <orig> <file>\n" ); + fprintf( pAbc->Err, "\t writes the current network into <file> by calling\n" ); + fprintf( pAbc->Err, "\t the hierarchical writer that matches the extension of <file>\n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog for <orig> [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\torig : the name of the original file with the hierarchical design\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteAiger( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fWriteSymbols; + int c; + + fWriteSymbols = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fWriteSymbols ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( fWriteSymbols ) + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_AIGER ); + else + { + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); + return 1; + } + Io_WriteAiger( pAbc->pNtkCur, pFileName, 0 ); + } + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_aiger [-sh] <file>\n" ); + fprintf( pAbc->Err, "\t write the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); + fprintf( pAbc->Err, "\t-s : toggle saving I/O names [default = %s]\n", fWriteSymbols? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aig)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BAF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_baf [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .baf)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_blif [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .blif)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBlifMv( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIFMV ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_blif_mv [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF-MV file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .mv)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fUseLuts; + int c; + + fUseLuts = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLuts ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( !fUseLuts ) + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BENCH ); + else + { + Abc_Ntk_t * pNtkTemp; + pNtkTemp = Abc_NtkToNetlist( pAbc->pNtkCur ); + Abc_NtkToAig( pNtkTemp ); + Io_WriteBenchLut( pNtkTemp, pFileName ); + Abc_NtkDelete( pNtkTemp ); + } + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_bench [-lh] <file>\n" ); + fprintf( pAbc->Err, "\t write the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-l : toggle using LUTs in the output [default = %s]\n", fUseLuts? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .bench)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + extern void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pAbc->Out, "The network should be a logic network (if it an AIG, use command \"logic\")\n" ); + return 0; + } + Io_WriteCellNet( pNtk, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_cellnet [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the network is the cellnet format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + int fAllPrimes; + int fNewAlgo; + extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ); + + fNewAlgo = 1; + fAllPrimes = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fNewAlgo ^= 1; + break; + case 'p': + fAllPrimes ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // check if the feature will be used + if ( Abc_NtkIsStrash(pAbc->pNtkCur) && fAllPrimes ) + { + fAllPrimes = 0; + printf( "Warning: Selected option to write all primes has no effect when deriving CNF from AIG.\n" ); + } + // call the corresponding file writer + if ( fNewAlgo ) + Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName ); + else if ( fAllPrimes ) + Io_WriteCnf( pAbc->pNtkCur, pFileName, 1 ); + else + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_CNF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_cnf [-nph] <file>\n" ); + fprintf( pAbc->Err, "\t write the miter cone into a CNF file\n" ); + fprintf( pAbc->Err, "\t-n : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" ); + fprintf( pAbc->Err, "\t-p : toggle using all primes to enhance implicativity [default = %s]\n", fAllPrimes? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_DOT ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_dot [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current network into a DOT file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fNames; + + fNames = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + // get the input file name + pFileName = argv[globalUtilOptind]; + + if ( pNtk->pModel == NULL ) + { + fprintf( pAbc->Out, "Counter-example is not available.\n" ); + return 0; + } + + // write the counter-example into the file + { + Abc_Obj_t * pObj; + FILE * pFile = fopen( pFileName, "w" ); + int i; + if ( pFile == NULL ) + { + fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName ); + return 1; + } + if ( fNames ) + { + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%s=%c ", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) ); + } + else + { + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) ); + } + fprintf( pFile, "\n" ); + fclose( pFile ); + } + + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_counter [-nh] <file>\n" ); + fprintf( pAbc->Err, "\t writes the counter-example derived by \"prove\" or \"sat\"\n" ); + fprintf( pAbc->Err, "\t the file contains values for each PI in the natural order\n" ); + fprintf( pAbc->Err, "\t-n : write input names into the file [default = %s]\n", fNames? "yes": "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_EQN ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_eqn [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current network in the equation format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_GML ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_gml [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fUseHost; + int c; + + printf( "This command currently does not work.\n" ); + return 0; + + fUseHost = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fUseHost ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } +/* + if ( !Abc_NtkIsSeq(pAbc->pNtkCur) ) + { + fprintf( stdout, "IoCommandWriteList(): Can write adjacency list for sequential AIGs only.\n" ); + return 0; + } +*/ + // get the input file name + pFileName = argv[globalUtilOptind]; + // write the file + Io_WriteList( pAbc->pNtkCur, pFileName, fUseHost ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_list [-nh] <file>\n" ); + fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); + fprintf( pAbc->Err, "\t-n : toggle writing host node [default = %s]\n", fUseHost? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_PLA ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_pla [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the collapsed network into a PLA file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_verilog [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current network in Verilog format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteVerLib( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Lib_t * pLibrary; + char * pFileName; + int c; + extern void Io_WriteVerilogLibrary( Abc_Lib_t * pLibrary, char * pFileName ); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // derive the netlist + pLibrary = Abc_FrameReadLibVer(); + if ( pLibrary == NULL ) + { + fprintf( pAbc->Out, "Verilog library is not specified.\n" ); + return 0; + } +// Io_WriteVerilogLibrary( pLibrary, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_verlib [-h] <file>\n" ); + fprintf( pAbc->Err, "\t write the current verilog library\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/io.h b/abc70930/src/base/io/io.h new file mode 100644 index 00000000..45762b77 --- /dev/null +++ b/abc70930/src/base/io/io.h @@ -0,0 +1,146 @@ +/**CFile**************************************************************** + + FileName [io.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IO_H__ +#define __IO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// network functionality +typedef enum { + IO_FILE_NONE = 0, + IO_FILE_AIGER, + IO_FILE_BAF, + IO_FILE_BLIF, + IO_FILE_BLIFMV, + IO_FILE_BENCH, + IO_FILE_CNF, + IO_FILE_DOT, + IO_FILE_EDIF, + IO_FILE_EQN, + IO_FILE_GML, + IO_FILE_LIST, + IO_FILE_PLA, + IO_FILE_VERILOG, + IO_FILE_UNKNOWN +} Io_FileType_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IO_WRITE_LINE_LENGTH 78 // the output line length + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== abcReadAiger.c ==========================================================*/ +extern Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ); +/*=== abcReadBaf.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ); +/*=== abcReadBlif.c ===========================================================*/ +extern Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ); +/*=== abcReadBlifMv.c =========================================================*/ +extern Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ); +/*=== abcReadBench.c ==========================================================*/ +extern Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ); +/*=== abcReadEdif.c ===========================================================*/ +extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ); +/*=== abcReadEqn.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ); +/*=== abcReadPla.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ); +/*=== abcReadVerilog.c ========================================================*/ +extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ); +/*=== abcWriteAiger.c =========================================================*/ +extern void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ); +/*=== abcWriteBaf.c ===========================================================*/ +extern void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteBlif.c ==========================================================*/ +extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); +/*=== abcWriteBlifMv.c ==========================================================*/ +extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteBench.c =========================================================*/ +extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); +extern int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteCnf.c ===========================================================*/ +extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes ); +/*=== abcWriteDot.c ===========================================================*/ +extern void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ); +extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); +extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); +/*=== abcWriteEqn.c ===========================================================*/ +extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteGml.c ===========================================================*/ +extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteList.c ==========================================================*/ +extern void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ); +/*=== abcWritePla.c ===========================================================*/ +extern int Io_WritePla( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteVerilog.c =======================================================*/ +extern void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcUtil.c ===============================================================*/ +extern Io_FileType_t Io_ReadFileType( char * pFileName ); +extern Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ); +extern Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck ); +extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ); +extern void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ); +extern Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ); +extern Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ); +extern Abc_Obj_t * Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv ); +extern Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ); +extern Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 ); +extern Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); +extern Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); +extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/io/ioInt.h b/abc70930/src/base/io/ioInt.h new file mode 100644 index 00000000..3daf3c75 --- /dev/null +++ b/abc70930/src/base/io/ioInt.h @@ -0,0 +1,49 @@ +/**CFile**************************************************************** + + FileName [ioInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IO_INT_H__ +#define __IO_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/io/ioReadAiger.c b/abc70930/src/base/io/ioReadAiger.c new file mode 100644 index 00000000..d3c4c878 --- /dev/null +++ b/abc70930/src/base/io/ioReadAiger.c @@ -0,0 +1,310 @@ +/**CFile**************************************************************** + + FileName [ioReadAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +unsigned Io_ReadAigerDecode( char ** ppPos ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) +{ + ProgressBar * pProgress; + FILE * pFile; + Vec_Ptr_t * vNodes, * vTerms; + Abc_Obj_t * pObj, * pNode0, * pNode1; + Abc_Ntk_t * pNtkNew; + int nTotal, nInputs, nOutputs, nLatches, nAnds, nFileSize, iTerm, nDigits, i; + char * pContents, * pDrivers, * pSymbols, * pCur, * pName, * pType; + unsigned uLit0, uLit1, uLit; + + // read the file into the buffer + nFileSize = Extra_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ALLOC( char, nFileSize ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + // check if the input file format is correct + if ( strncmp(pContents, "aig", 3) != 0 ) + { + fprintf( stdout, "Wrong input file format.\n" ); + return NULL; + } + + // allocate the empty AIG + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pName = Extra_FileNameGeneric( pFileName ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); + free( pName ); + + + // read the file type + pCur = pContents; while ( *pCur++ != ' ' ); + // read the number of objects + nTotal = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of inputs + nInputs = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of latches + nLatches = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of outputs + nOutputs = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of nodes + nAnds = atoi( pCur ); while ( *pCur++ != '\n' ); + // check the parameters + if ( nTotal != nInputs + nLatches + nAnds ) + { + fprintf( stdout, "The paramters are wrong.\n" ); + return NULL; + } + + // prepare the array of nodes + vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); + Vec_PtrPush( vNodes, Abc_ObjNot( Abc_AigConst1(pNtkNew) ) ); + + // create the PIs + for ( i = 0; i < nInputs; i++ ) + { + pObj = Abc_NtkCreatePi(pNtkNew); + Vec_PtrPush( vNodes, pObj ); + } + // create the POs + for ( i = 0; i < nOutputs; i++ ) + { + pObj = Abc_NtkCreatePo(pNtkNew); + } + // create the latches + nDigits = Extra_Base10Log( nLatches ); + for ( i = 0; i < nLatches; i++ ) + { + pObj = Abc_NtkCreateLatch(pNtkNew); + Abc_LatchSetInit0( pObj ); + pNode0 = Abc_NtkCreateBi(pNtkNew); + pNode1 = Abc_NtkCreateBo(pNtkNew); + Abc_ObjAddFanin( pObj, pNode0 ); + Abc_ObjAddFanin( pNode1, pObj ); + Vec_PtrPush( vNodes, pNode1 ); + // assign names to latch and its input +// Abc_ObjAssignName( pObj, Abc_ObjNameDummy("_L", i, nDigits), NULL ); +// printf( "Creating latch %s with input %d and output %d.\n", Abc_ObjName(pObj), pNode0->Id, pNode1->Id ); + } + + // remember the beginning of latch/PO literals + pDrivers = pCur; + + // scroll to the beginning of the binary data + for ( i = 0; i < nLatches + nOutputs; ) + if ( *pCur++ == '\n' ) + i++; + + // create the AND gates + pProgress = Extra_ProgressBarStart( stdout, nAnds ); + for ( i = 0; i < nAnds; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + uLit = ((i + 1 + nInputs + nLatches) << 1); + uLit1 = uLit - Io_ReadAigerDecode( &pCur ); + uLit0 = uLit1 - Io_ReadAigerDecode( &pCur ); +// assert( uLit1 > uLit0 ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); + pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); + assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); + Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) ); + } + Extra_ProgressBarStop( pProgress ); + + // remember the place where symbols begin + pSymbols = pCur; + + // read the latch driver literals + pCur = pDrivers; + Abc_NtkForEachLatchInput( pNtkNew, pObj, i ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Abc_ObjAddFanin( pObj, pNode0 ); + +// printf( "Adding input %d to latch input %d.\n", pNode0->Id, pObj->Id ); + + } + // read the PO driver literals + Abc_NtkForEachPo( pNtkNew, pObj, i ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Abc_ObjAddFanin( pObj, pNode0 ); + } + + // read the names if present + pCur = pSymbols; + if ( *pCur != 'c' ) + { + int Counter = 0; + while ( pCur < pContents + nFileSize && *pCur != 'c' ) + { + // get the terminal type + pType = pCur; + if ( *pCur == 'i' ) + vTerms = pNtkNew->vPis; + else if ( *pCur == 'l' ) + vTerms = pNtkNew->vBoxes; + else if ( *pCur == 'o' ) + vTerms = pNtkNew->vPos; + else + { + fprintf( stdout, "Wrong terminal type.\n" ); + return NULL; + } + // get the terminal number + iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' ); + // get the node + if ( iTerm >= Vec_PtrSize(vTerms) ) + { + fprintf( stdout, "The number of terminal is out of bound.\n" ); + return NULL; + } + pObj = Vec_PtrEntry( vTerms, iTerm ); + if ( *pType == 'l' ) + pObj = Abc_ObjFanout0(pObj); + // assign the name + pName = pCur; while ( *pCur++ != '\n' ); + // assign this name + *(pCur-1) = 0; + Abc_ObjAssignName( pObj, pName, NULL ); + if ( *pType == 'l' ) + { + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); + Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); + } + // mark the node as named + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + } + + // assign the remaining names + Abc_NtkForEachPi( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Counter++; + } + Abc_NtkForEachLatchOutput( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); + Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); + Counter++; + } + Abc_NtkForEachPo( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Counter++; + } + if ( Counter ) + printf( "Io_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); + } + else + { +// printf( "Io_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); + Abc_NtkShortNames( pNtkNew ); + } + + // read the name of the model if given + if ( *pCur == 'c' ) + { + if ( !strncmp( pCur + 2, ".model", 6 ) ) + { + char * pTemp; + for ( pTemp = pCur + 9; *pTemp && *pTemp != '\n'; pTemp++ ); + *pTemp = 0; + free( pNtkNew->pName ); + pNtkNew->pName = Extra_UtilStrsav( pCur + 9 ); + } + } + + + // skipping the comments + free( pContents ); + Vec_PtrFree( vNodes ); + + // remove the extra nodes + Abc_AigCleanup( pNtkNew->pManFunc ); + + // check the result + if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) + { + printf( "Io_ReadAiger: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Extracts one unsigned AIG edge from the input buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "unsigned decode (FILE * file)". ] + + SideEffects [Updates the current reading position.] + + SeeAlso [] + +***********************************************************************/ +unsigned Io_ReadAigerDecode( char ** ppPos ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + +// while ((ch = getnoneofch (file)) & 0x80) + while ((ch = *(*ppPos)++) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + + return x | (ch << (7 * i)); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBaf.c b/abc70930/src/base/io/ioReadBaf.c new file mode 100644 index 00000000..8dce54af --- /dev/null +++ b/abc70930/src/base/io/ioReadBaf.c @@ -0,0 +1,171 @@ +/**CFile**************************************************************** + + FileName [ioReadBaf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read AIG in the binary format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ) +{ + ProgressBar * pProgress; + FILE * pFile; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNode0, * pNode1; + Abc_Ntk_t * pNtkNew; + int nInputs, nOutputs, nLatches, nAnds, nFileSize, Num, i; + char * pContents, * pName, * pCur; + unsigned * pBufferNode; + + // read the file into the buffer + nFileSize = Extra_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ALLOC( char, nFileSize ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + // skip the comments (comment lines begin with '#' and end with '\n') + for ( pCur = pContents; *pCur == '#'; ) + while ( *pCur++ != '\n' ); + + // read the name + pName = pCur; while ( *pCur++ ); + // read the number of inputs + nInputs = atoi( pCur ); while ( *pCur++ ); + // read the number of outputs + nOutputs = atoi( pCur ); while ( *pCur++ ); + // read the number of latches + nLatches = atoi( pCur ); while ( *pCur++ ); + // read the number of nodes + nAnds = atoi( pCur ); while ( *pCur++ ); + + // allocate the empty AIG + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); + + // prepare the array of nodes + vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); + Vec_PtrPush( vNodes, Abc_AigConst1(pNtkNew) ); + + // create the PIs + for ( i = 0; i < nInputs; i++ ) + { + pObj = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + Vec_PtrPush( vNodes, pObj ); + } + // create the POs + for ( i = 0; i < nOutputs; i++ ) + { + pObj = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + } + // create the latches + for ( i = 0; i < nLatches; i++ ) + { + pObj = Abc_NtkCreateLatch(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + + pNode0 = Abc_NtkCreateBi(pNtkNew); + Abc_ObjAssignName( pNode0, pCur, NULL ); while ( *pCur++ ); + + pNode1 = Abc_NtkCreateBo(pNtkNew); + Abc_ObjAssignName( pNode1, pCur, NULL ); while ( *pCur++ ); + Vec_PtrPush( vNodes, pNode1 ); + + Abc_ObjAddFanin( pObj, pNode0 ); + Abc_ObjAddFanin( pNode1, pObj ); + } + + // get the pointer to the beginning of the node array + pBufferNode = (int *)(pContents + (nFileSize - (2 * nAnds + nOutputs + nLatches) * sizeof(int)) ); + // make sure we are at the place where the nodes begin + if ( pBufferNode != (int *)pCur ) + { + free( pContents ); + Vec_PtrFree( vNodes ); + Abc_NtkDelete( pNtkNew ); + printf( "Warning: Internal reader error.\n" ); + return NULL; + } + + // create the AND gates + pProgress = Extra_ProgressBarStart( stdout, nAnds ); + for ( i = 0; i < nAnds; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+0] >> 1), pBufferNode[2*i+0] & 1 ); + pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+1] >> 1), pBufferNode[2*i+1] & 1 ); + Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) ); + } + Extra_ProgressBarStop( pProgress ); + + // read the POs + Abc_NtkForEachCo( pNtkNew, pObj, i ) + { + Num = pBufferNode[2*nAnds+i]; + if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + { + Abc_ObjSetData( Abc_ObjFanout0(pObj), (void *)(Num & 3) ); + Num >>= 2; + } + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, Num >> 1), Num & 1 ); + Abc_ObjAddFanin( pObj, pNode0 ); + } + free( pContents ); + Vec_PtrFree( vNodes ); + + // remove the extra nodes +// Abc_AigCleanup( pNtkNew->pManFunc ); + + // check the result + if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) + { + printf( "Io_ReadBaf: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; + +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBench.c b/abc70930/src/base/io/ioReadBench.c new file mode 100644 index 00000000..007147bc --- /dev/null +++ b/abc70930/src/base/io/ioReadBench.c @@ -0,0 +1,360 @@ +/**CFile**************************************************************** + + FileName [ioReadBench.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BENCH files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a BENCH file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t,()=" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadBenchNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBench: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode, * pNet; + Vec_Str_t * vString; + unsigned uTruth[8]; + char * pType, ** ppNames, * pString; + int iLine, nNames, nDigits, fLutsPresent = 0; + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + vString = Vec_StrAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + if ( vTokens->nSize == 1 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + // get the type of the line + if ( strncmp( vTokens->pArray[0], "INPUT", 5 ) == 0 ) + Io_ReadCreatePi( pNtk, vTokens->pArray[1] ); + else if ( strncmp( vTokens->pArray[0], "OUTPUT", 5 ) == 0 ) + Io_ReadCreatePo( pNtk, vTokens->pArray[1] ); + else + { + // get the node name and the node type + pType = vTokens->pArray[1]; + if ( strncmp(pType, "DFF", 3) == 0 ) // works for both DFF and DFFRSE + { + pNode = Io_ReadCreateLatch( pNtk, vTokens->pArray[2], vTokens->pArray[0] ); +// Abc_LatchSetInit0( pNode ); + if ( pType[3] == '0' ) + Abc_LatchSetInit0( pNode ); + else if ( pType[3] == '1' ) + Abc_LatchSetInit1( pNode ); + else + Abc_LatchSetInitDc( pNode ); + } + else if ( strcmp(pType, "LUT") == 0 ) + { + fLutsPresent = 1; + ppNames = (char **)vTokens->pArray + 3; + nNames = vTokens->nSize - 3; + // check the number of inputs + if ( nNames > 8 ) + { + printf( "%s: Currently cannot read truth tables with more than 8 inputs (%d).\n", Extra_FileReaderGetFileName(p), nNames ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + // get the hex string + pString = vTokens->pArray[2]; + if ( strncmp( pString, "0x", 2 ) ) + { + printf( "%s: The LUT signature (%s) does not look like a hexadecimal beginning with \"0x\".\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + pString += 2; + // pad the string with zero's if needed + nDigits = (1 << nNames) / 4; + if ( nDigits == 0 ) + nDigits = 1; + if ( strlen(pString) < (unsigned)nDigits ) + { + Vec_StrFill( vString, nDigits - strlen(pString), '0' ); + Vec_StrPrintStr( vString, pString ); + Vec_StrPush( vString, 0 ); + pString = Vec_StrArray( vString ); + } + // read the hex number from the string + if ( !Extra_ReadHexadecimal( uTruth, pString, nNames ) ) + { + printf( "%s: Reading hexadecimal number (%s) has failed.\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + // check if the node is a constant node + if ( Extra_TruthIsConst0(uTruth, nNames) ) + { + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 ); + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) ); + } + else if ( Extra_TruthIsConst1(uTruth, nNames) ) + { + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 ); + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) ); + } + else + { + // create the node + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames ); + assert( nNames > 0 ); + if ( nNames > 1 ) + Abc_ObjSetData( pNode, Abc_SopCreateFromTruth(pNtk->pManFunc, nNames, uTruth) ); + else if ( pString[0] == '2' ) + Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); + else if ( pString[0] == '1' ) + Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) ); + else + { + printf( "%s: Reading truth table (%s) of single-input node has failed.\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + } + else + { + // create a new node and add it to the network + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 2; + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames ); + // assign the cover + if ( strcmp(pType, "AND") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateAnd(pNtk->pManFunc, nNames, NULL) ); + else if ( strcmp(pType, "OR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateOr(pNtk->pManFunc, nNames, NULL) ); + else if ( strcmp(pType, "NAND") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNand(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "NOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNor(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "XOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateXor(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "NXOR") == 0 || strcmp(pType, "XNOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNxor(pNtk->pManFunc, nNames) ); + else if ( strncmp(pType, "BUF", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); + else if ( strcmp(pType, "NOT") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) ); + else if ( strncmp(pType, "MUX", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, "1-0 1\n-11 1\n") ); + else if ( strncmp(pType, "gnd", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) ); + else if ( strncmp(pType, "vdd", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) ); + else + { + printf( "Io_ReadBenchNetwork(): Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + } + } + Extra_ProgressBarStop( pProgress ); + Vec_StrFree( vString ); + + // check if constant 0 is present + if ( (pNet = Abc_NtkFindNet( pNtk, "gnd" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + Io_ReadCreateConst( pNtk, "gnd", 0 ); + } + if ( (pNet = Abc_NtkFindNet( pNtk, "1" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + printf( "Io_ReadBenchNetwork(): Adding constant 0 fanin to non-driven net \"1\".\n" ); + Io_ReadCreateConst( pNtk, "1", 0 ); + } + } + // check if constant 1 is present + if ( (pNet = Abc_NtkFindNet( pNtk, "vdd" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + Io_ReadCreateConst( pNtk, "vdd", 1 ); + } + if ( (pNet = Abc_NtkFindNet( pNtk, "2" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + printf( "Io_ReadBenchNetwork(): Adding constant 1 fanin to non-driven net \"2\".\n" ); + Io_ReadCreateConst( pNtk, "2", 1 ); + } + } + + Abc_NtkFinalizeRead( pNtk ); + + // if LUTs are present, collapse the truth tables into cubes + if ( fLutsPresent ) + { + if ( !Abc_NtkToBdd(pNtk) ) + { + printf( "Io_ReadBenchNetwork(): Converting to BDD has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( !Abc_NtkToSop(pNtk, 0) ) + { + printf( "Io_ReadBenchNetwork(): Converting to SOP has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + return pNtk; +} + + +/**Function************************************************************* + + Synopsis [Reads initial state in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ) +{ + char pBuffer[1000]; + FILE * pFile; + char * pToken; + Abc_Obj_t * pObj; + int Num; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Io_ReadBenchInit(): Failed to open file \"%s\".\n", pFileName ); + return; + } + while ( fgets( pBuffer, 999, pFile ) ) + { + pToken = strtok( pBuffer, " \n\t\r" ); + // find the latch output + Num = Nm_ManFindIdByName( pNtk->pManName, pToken, ABC_OBJ_BO ); + if ( Num < 0 ) + { + printf( "Io_ReadBenchInit(): Cannot find register with output %s.\n", pToken ); + continue; + } + pObj = Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + if ( !Abc_ObjIsLatch(pObj) ) + { + printf( "Io_ReadBenchInit(): The signal is not a register output %s.\n", pToken ); + continue; + } + // assign the new init state + pToken = strtok( NULL, " \n\t\r" ); + if ( pToken[0] == '0' ) + Abc_LatchSetInit0( pObj ); + else if ( pToken[0] == '1' ) + Abc_LatchSetInit1( pObj ); + else if ( pToken[0] == '2' ) + Abc_LatchSetInitDc( pObj ); + else + { + printf( "Io_ReadBenchInit(): The signal %s has unknown initial value (%s).\n", + Abc_ObjName(Abc_ObjFanout0(pObj)), pToken ); + continue; + } + } + fclose( pFile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadBlif.c b/abc70930/src/base/io/ioReadBlif.c new file mode 100644 index 00000000..d0750178 --- /dev/null +++ b/abc70930/src/base/io/ioReadBlif.c @@ -0,0 +1,1105 @@ +/**CFile**************************************************************** + + FileName [ioReadBlif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Io_ReadBlif_t_ Io_ReadBlif_t; // all reading info +struct Io_ReadBlif_t_ +{ + // general info about file + char * pFileName; // the name of the file + Extra_FileReader_t * pReader; // the input file reader + // current processing info + Abc_Ntk_t * pNtkMaster; // the primary network + Abc_Ntk_t * pNtkCur; // the primary network + int LineCur; // the line currently parsed + // temporary storage for tokens + Vec_Ptr_t * vTokens; // the current tokens + Vec_Ptr_t * vNewTokens; // the temporary storage for the tokens + Vec_Str_t * vCubes; // the temporary storage for the tokens + // the error message + FILE * Output; // the output stream + char sError[1000]; // the error string generated during parsing + int fError; // set to 1 when error occurs +}; + +static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ); +static void Io_ReadBlifFree( Io_ReadBlif_t * p ); +static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ); +static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ); +static char * Io_ReadBlifCleanName( char * pName ); + +static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ); +static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ); +static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ); +static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the (hierarchical) network from the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) +{ + Io_ReadBlif_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Io_ReadBlifFile( pFileName ); + if ( p == NULL ) + return NULL; + + // read the hierarchical network + pNtk = Io_ReadBlifNetwork( p ); + if ( pNtk == NULL ) + { + Io_ReadBlifFree( p ); + return NULL; + } + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + Abc_NtkTimeInitialize( pNtk ); + Io_ReadBlifFree( p ); + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBlif: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Iteratively reads several networks in the hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) +{ + Abc_Ntk_t * pNtk, * pNtkMaster; + + // read the name of the master network + p->vTokens = Io_ReadBlifGetTokens(p); + if ( p->vTokens == NULL || strcmp( p->vTokens->pArray[0], ".model" ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Wrong input file format." ); + Io_ReadBlifPrintErrorMessage( p ); + return NULL; + } + + // read networks (with EXDC) + pNtkMaster = NULL; + while ( p->vTokens ) + { + // read the network and its EXDC if present + pNtk = Io_ReadBlifNetworkOne( p ); + if ( pNtk == NULL ) + break; + if ( p->vTokens && strcmp(p->vTokens->pArray[0], ".exdc") == 0 ) + { + pNtk->pExdc = Io_ReadBlifNetworkOne( p ); + Abc_NtkFinalizeRead( pNtk->pExdc ); + if ( pNtk->pExdc == NULL ) + break; + } + // add this network as part of the hierarchy + if ( pNtkMaster == NULL ) // no master network so far + { + p->pNtkMaster = pNtkMaster = pNtk; + continue; + } +/* + // make sure hierarchy does not have the network with this name + if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName ); + Io_ReadBlifPrintErrorMessage( p ); + Abc_NtkDelete( pNtk ); + Abc_NtkDelete( pNtkMaster ); + pNtkMaster = NULL; + return NULL; + } + // add the network to the hierarchy + if ( pNtkMaster->tName2Model == NULL ) + pNtkMaster->tName2Model = stmm_init_table(strcmp, stmm_strhash); + stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk ); +*/ + } +/* + // if there is a hierarchy, connect the boxes + if ( pNtkMaster && pNtkMaster->tName2Model ) + { + if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) ) + { + Abc_NtkDelete( pNtkMaster ); + return NULL; + } + } + else +*/ + if ( !p->fError ) + Abc_NtkFinalizeRead( pNtkMaster ); + // return the master network + return pNtkMaster; +} + +/**Function************************************************************* + + Synopsis [Reads one (main or exdc) network from the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtk; + char * pDirective; + int iLine, fTokensReady, fStatus; + + // make sure the tokens are present + assert( p->vTokens != NULL ); + + // create the new network + p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + // read the model name + if ( strcmp( p->vTokens->pArray[0], ".model" ) == 0 ) + pNtk->pName = Extra_UtilStrsav( p->vTokens->pArray[1] ); + else if ( strcmp( p->vTokens->pArray[0], ".exdc" ) != 0 ) + { + printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName, + Extra_FileReaderGetLineNumber(p->pReader, 0), p->vTokens->pArray[0] ); + Abc_NtkDelete(pNtk); + p->pNtkCur = NULL; + return NULL; + } + + // read the inputs/outputs + if ( p->pNtkMaster == NULL ) + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); + fTokensReady = fStatus = 0; + for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) + { + if ( p->pNtkMaster == NULL && iLine % 1000 == 0 ) + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); + + // consider different line types + fTokensReady = 0; + pDirective = p->vTokens->pArray[0]; + if ( !strcmp( pDirective, ".names" ) ) + { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; } + else if ( !strcmp( pDirective, ".gate" ) ) + fStatus = Io_ReadBlifNetworkGate( p, p->vTokens ); + else if ( !strcmp( pDirective, ".latch" ) ) + fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens ); + else if ( !strcmp( pDirective, ".inputs" ) ) + fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens ); + else if ( !strcmp( pDirective, ".outputs" ) ) + fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens ); + else if ( !strcmp( pDirective, ".asserts" ) ) + fStatus = Io_ReadBlifNetworkAsserts( p, p->vTokens ); + else if ( !strcmp( pDirective, ".input_arrival" ) ) + fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens ); + else if ( !strcmp( pDirective, ".default_input_arrival" ) ) + fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens ); +// else if ( !strcmp( pDirective, ".subckt" ) ) +// fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens ); + else if ( !strcmp( pDirective, ".exdc" ) ) + break; + else if ( !strcmp( pDirective, ".end" ) ) + { + p->vTokens = Io_ReadBlifGetTokens(p); + break; + } + else if ( !strcmp( pDirective, ".blackbox" ) ) + { + pNtk->ntkType = ABC_NTK_NETLIST; + pNtk->ntkFunc = ABC_FUNC_BLACKBOX; + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = NULL; + } + else + printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName, + Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective ); + if ( p->vTokens == NULL ) // some files do not have ".end" in the end + break; + if ( fStatus == 1 ) + { + Extra_ProgressBarStop( pProgress ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + if ( p->pNtkMaster == NULL ) + Extra_ProgressBarStop( pProgress ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePi( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePo( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreateAssert( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Ntk_t * pNtk = p->pNtkCur; + Abc_Obj_t * pLatch; + int ResetValue; + if ( vTokens->nSize < 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .latch line does not have enough tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the latch + pLatch = Io_ReadCreateLatch( pNtk, vTokens->pArray[1], vTokens->pArray[2] ); + // get the latch reset value + if ( vTokens->nSize == 3 ) + Abc_LatchSetInitDc( pLatch ); + else + { + ResetValue = atoi(vTokens->pArray[vTokens->nSize-1]); + if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .latch line has an unknown reset value (%s).", vTokens->pArray[3] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + if ( ResetValue == 0 ) + Abc_LatchSetInit0( pLatch ); + else if ( ResetValue == 1 ) + Abc_LatchSetInit1( pLatch ); + else if ( ResetValue == 2 ) + Abc_LatchSetInitDc( pLatch ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) +{ + Vec_Ptr_t * vTokens = *pvTokens; + Abc_Ntk_t * pNtk = p->pNtkCur; + Abc_Obj_t * pNode; + char * pToken, Char, ** ppNames; + int nFanins, nNames; + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .names line has less than two tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create the node + ppNames = (char **)vTokens->pArray + 1; + nNames = vTokens->nSize - 2; + pNode = Io_ReadCreateNode( pNtk, ppNames[nNames], ppNames, nNames ); + + // derive the functionality of the node + p->vCubes->nSize = 0; + nFanins = vTokens->nSize - 2; + if ( nFanins == 0 ) + { + while ( vTokens = Io_ReadBlifGetTokens(p) ) + { + pToken = vTokens->pArray[0]; + if ( pToken[0] == '.' ) + break; + // read the cube + if ( vTokens->nSize != 1 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of tokens in the constant cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the cube + Char = ((char *)vTokens->pArray[0])[0]; + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, Char ); + Vec_StrPush( p->vCubes, '\n' ); + } + } + else + { + while ( vTokens = Io_ReadBlifGetTokens(p) ) + { + pToken = vTokens->pArray[0]; + if ( pToken[0] == '.' ) + break; + // read the cube + if ( vTokens->nSize != 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of tokens in the cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the cube + Vec_StrAppend( p->vCubes, vTokens->pArray[0] ); + // check the char + Char = ((char *)vTokens->pArray[1])[0]; + if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The output character in the constant cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, Char ); + Vec_StrPush( p->vCubes, '\n' ); + } + } + // if there is nothing there + if ( p->vCubes->nSize == 0 ) + { + // create an empty cube + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, '0' ); + Vec_StrPush( p->vCubes, '\n' ); + } + Vec_StrPush( p->vCubes, 0 ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, p->vCubes->pArray) ); + + // check the size + if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum(Abc_ObjData(pNode)) ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).", + Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum(Abc_ObjData(pNode)) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // return the last array of tokens + *pvTokens = vTokens; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Mio_Library_t * pGenlib; + Mio_Gate_t * pGate; + Abc_Obj_t * pNode; + char ** ppNames; + int i, nNames; + + // check that the library is available + pGenlib = Abc_FrameReadLibGen(); + if ( pGenlib == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The current library is not available." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .gate line has less than two tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // get the gate + pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] ); + if ( pGate == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Cannot find gate \"%s\" in the library.", vTokens->pArray[1] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // if this is the first line with gate, update the network type + if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) + { + assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); + p->pNtkCur->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( p->pNtkCur->pManFunc ); + p->pNtkCur->pManFunc = pGenlib; + } + + // remove the formal parameter names + for ( i = 2; i < vTokens->nSize; i++ ) + { + vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] ); + if ( vTokens->pArray[i] == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Invalid gate input assignment." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + } + + // create the node + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 3; + pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, pGate ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates a multi-input multi-output box in the hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Obj_t * pBox; + Vec_Ptr_t * vNames; + char * pName; + int i; + + // create a new node and add it to the network + if ( vTokens->nSize < 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .subcircuit line has less than three tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // store the names of formal/actual inputs/outputs of the box + vNames = Vec_PtrAlloc( 10 ); + Vec_PtrForEachEntryStart( vTokens, pName, i, 1 ) +// Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) ); + Vec_PtrPush( vNames, Extra_UtilStrsav(pName) ); // memory leak!!! + + // create a new box and add it to the network + pBox = Abc_NtkCreateBlackbox( p->pNtkCur ); + // set the pointer to the node names + Abc_ObjSetData( pBox, vNames ); + // remember the line of the file + pBox->pCopy = (void *)Extra_FileReaderGetLineNumber(p->pReader, 0); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_ReadBlifCleanName( char * pName ) +{ + int i, Length; + Length = strlen(pName); + for ( i = 0; i < Length; i++ ) + if ( pName[i] == '=' ) + return pName + i + 1; + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Obj_t * pNet; + char * pFoo1, * pFoo2; + double TimeRise, TimeFall; + + // make sure this is indeed the .inputs line + assert( strncmp( vTokens->pArray[0], ".input_arrival", 14 ) == 0 ); + if ( vTokens->nSize != 4 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Wrong number of arguments on .input_arrival line." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindNet( p->pNtkCur, vTokens->pArray[1] ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Cannot find object corresponding to %s on .input_arrival line.", vTokens->pArray[1] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + TimeRise = strtod( vTokens->pArray[2], &pFoo1 ); + TimeFall = strtod( vTokens->pArray[3], &pFoo2 ); + if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_arrival line.", vTokens->pArray[2], vTokens->pArray[3] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // set the arrival time + Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + char * pFoo1, * pFoo2; + double TimeRise, TimeFall; + + // make sure this is indeed the .inputs line + assert( strncmp( vTokens->pArray[0], ".default_input_arrival", 23 ) == 0 ); + if ( vTokens->nSize != 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Wrong number of arguments on .default_input_arrival line." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + TimeRise = strtod( vTokens->pArray[1], &pFoo1 ); + TimeFall = strtod( vTokens->pArray[2], &pFoo2 ); + if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_arrival line.", vTokens->pArray[1], vTokens->pArray[2] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // set the arrival time + Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) +{ + p->fError = 1; + if ( p->LineCur == 0 ) // the line number is not given + fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); + else // print the error message with the line number + fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError ); +} + +/**Function************************************************************* + + Synopsis [Gets the tokens taking into account the line breaks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) +{ + Vec_Ptr_t * vTokens; + char * pLastToken; + int i; + + // get rid of the old tokens + if ( p->vNewTokens->nSize > 0 ) + { + for ( i = 0; i < p->vNewTokens->nSize; i++ ) + free( p->vNewTokens->pArray[i] ); + p->vNewTokens->nSize = 0; + } + + // get the new tokens + vTokens = Extra_FileReaderGetTokens(p->pReader); + if ( vTokens == NULL ) + return vTokens; + + // check if there is a transfer to another line + pLastToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) + return vTokens; + + // remove the slash + pLastToken[ strlen(pLastToken)-1 ] = 0; + if ( pLastToken[0] == 0 ) + vTokens->nSize--; + // load them into the new array + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + + // load as long as there is the line break + while ( 1 ) + { + // get the new tokens + vTokens = Extra_FileReaderGetTokens(p->pReader); + if ( vTokens->nSize == 0 ) + return p->vNewTokens; + // check if there is a transfer to another line + pLastToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) + { + // remove the slash + pLastToken[ strlen(pLastToken)-1 ] = 0; + if ( pLastToken[0] == 0 ) + vTokens->nSize--; + // load them into the new array + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + continue; + } + // otherwise, load them and break + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + break; + } + return p->vNewTokens; +} + +/**Function************************************************************* + + Synopsis [Starts the reading data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) +{ + Extra_FileReader_t * pReader; + Io_ReadBlif_t * p; + + // start the reader + pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" ); + + if ( pReader == NULL ) + return NULL; + + // start the reading data structure + p = ALLOC( Io_ReadBlif_t, 1 ); + memset( p, 0, sizeof(Io_ReadBlif_t) ); + p->pFileName = pFileName; + p->pReader = pReader; + p->Output = stdout; + p->vNewTokens = Vec_PtrAlloc( 100 ); + p->vCubes = Vec_StrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifFree( Io_ReadBlif_t * p ) +{ + Extra_FileReaderFree( p->pReader ); + Vec_PtrFree( p->vNewTokens ); + Vec_StrFree( p->vCubes ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Connect one box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model ) +{ + Vec_Ptr_t * pNames; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj, * pNet; + char * pName, * pActual; + int i, Length, Start; + + // get the model for this box + pNames = pBox->pData; + if ( !stmm_lookup( tName2Model, Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find the model for subcircuit %s.", Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create the fanins of the box + Abc_NtkForEachPi( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + if ( Abc_NtkPiNum(pNtkModel) == 0 ) + Start = 1; + else + { + Vec_PtrForEachEntryStart( pNames, pName, i, 1 ) + { + pActual = Io_ReadBlifCleanName(pName); + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Length = pActual - pName - 1; + pName[Length] = 0; + // find the PI net with this name + pObj = Abc_NtkFindNet( pNtkModel, pName ); + if ( pObj == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // get the PI + pObj = Abc_ObjFanin0(pObj); + // quit if this is not a PI net + if ( !Abc_ObjIsPi(pObj) ) + { + pName[Length] = '='; + Start = i; + break; + } + // remember the actual name in the net + if ( pObj->pCopy != NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pObj->pCopy = (void *)pActual; + // quit if we processed all PIs + if ( i == Abc_NtkPiNum(pNtkModel) ) + { + Start = i+1; + break; + } + } + } + // create the fanins of the box + Abc_NtkForEachPi( pNtkModel, pObj, i ) + { + pActual = (void *)pObj->pCopy; + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); + Abc_ObjAddFanin( pBox, pNet ); + } + Abc_NtkForEachPi( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + + // create the fanouts of the box + Abc_NtkForEachPo( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + Vec_PtrForEachEntryStart( pNames, pName, i, Start ) + { + pActual = Io_ReadBlifCleanName(pName); + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Length = pActual - pName - 1; + pName[Length] = 0; + // find the PO net with this name + pObj = Abc_NtkFindNet( pNtkModel, pName ); + if ( pObj == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // get the PO + pObj = Abc_ObjFanout0(pObj); + if ( pObj->pCopy != NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pObj->pCopy = (void *)pActual; + } + // create the fanouts of the box + Abc_NtkForEachPo( pNtkModel, pObj, i ) + { + pActual = (void *)pObj->pCopy; + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); + Abc_ObjAddFanin( pNet, pBox ); + } + Abc_NtkForEachPo( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + + // remove the array of names, assign the pointer to the model + Vec_PtrForEachEntry( pBox->pData, pName, i ) + free( pName ); + Vec_PtrFree( pBox->pData ); + pBox->pData = pNtkModel; + return 0; +} + +/**Function************************************************************* + + Synopsis [Connect the boxes in the hierarchy of networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model ) +{ + Abc_Obj_t * pBox; + int i; + // go through the boxes + Abc_NtkForEachBlackbox( pNtk, pBox, i ) + if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) ) + return 1; + Abc_NtkFinalizeRead( pNtk ); + return 0; +} + +#if 0 + +/**Function************************************************************* + + Synopsis [Connect the boxes in the hierarchy of networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) +{ + stmm_generator * gen; + Abc_Ntk_t * pNtk; + char * pName; + // connect the master network + if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) ) + return 1; + // connect other networks + stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk ) + if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) ) + return 1; + return 0; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBlifAig.c b/abc70930/src/base/io/ioReadBlifAig.c new file mode 100644 index 00000000..c448bab6 --- /dev/null +++ b/abc70930/src/base/io/ioReadBlifAig.c @@ -0,0 +1,1013 @@ +/**CFile**************************************************************** + + FileName [ioReadBlifAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF file into AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 23, 2006.] + + Revision [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "extra.h" +#include "vecPtr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// latch initial values +typedef enum { + IO_BLIF_INIT_NONE = 0, // 0: unknown + IO_BLIF_INIT_ZERO, // 1: zero + IO_BLIF_INIT_ONE, // 2: one + IO_BLIF_INIT_DC // 3: don't-care +} Io_BlifInit_t; + +typedef struct Io_BlifObj_t_ Io_BlifObj_t; // parsing object +struct Io_BlifObj_t_ +{ + unsigned fPi : 1; // the object is a primary input + unsigned fPo : 1; // the object is a primary output + unsigned fLi : 1; // the object is a latch input + unsigned fLo : 1; // the object is a latch output + unsigned fDef : 1; // the object is defined as a table (node, PO, LI) + unsigned fLoop : 1; // flag for loop detection + unsigned Init : 2; // the latch initial state + unsigned Offset : 24; // temporary number + char * pName; // the name of this object + void * pEquiv; // the AIG node representing this line + Io_BlifObj_t * pNext; // the next obj in the hash table +}; + +typedef struct Io_BlifMan_t_ Io_BlifMan_t; // parsing manager +struct Io_BlifMan_t_ +{ + // general info about file + char * pFileName; // the name of the file + char * pBuffer; // the begining of the file buffer + Vec_Ptr_t * vLines; // the line beginnings + // temporary objects + Io_BlifObj_t * pObjects; // the storage for objects + int nObjects; // the number of objects allocated + int iObjNext; // the next free object + // file lines + char * pModel; // .model line + Vec_Ptr_t * vInputs; // .inputs lines + Vec_Ptr_t * vOutputs; // .outputs lines + Vec_Ptr_t * vLatches; // .latches lines + Vec_Ptr_t * vNames; // .names lines + // network objects + Vec_Ptr_t * vPis; // the PI structures + Vec_Ptr_t * vPos; // the PO structures + Vec_Ptr_t * vLis; // the LI structures + Vec_Ptr_t * vLos; // the LO structures + // mapping of names into objects + Io_BlifObj_t ** pTable; // the hash table + int nTableSize; // the hash table size + // current processing info + Abc_Ntk_t * pAig; // the network under construction + Vec_Ptr_t * vTokens; // the current tokens + char sError[512]; // the error string generated during parsing + // statistics + int nTablesRead; // the number of processed tables + int nTablesLeft; // the number of dangling tables +}; + +// static functions +static Io_BlifMan_t * Io_BlifAlloc(); +static void Io_BlifFree( Io_BlifMan_t * p ); +static char * Io_BlifLoadFile( char * pFileName ); +static void Io_BlifReadPreparse( Io_BlifMan_t * p ); +static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ); +static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseConstruct( Io_BlifMan_t * p ); +static int Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from the BLIF file as an AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ) +{ + FILE * pFile; + Io_BlifMan_t * p; + Abc_Ntk_t * pAig; + + // check that the file is available + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_Blif(): The file is unavailable (absent or open).\n" ); + return 0; + } + fclose( pFile ); + + // start the file reader + p = Io_BlifAlloc(); + p->pFileName = pFileName; + p->pBuffer = Io_BlifLoadFile( pFileName ); + if ( p->pBuffer == NULL ) + { + Io_BlifFree( p ); + return NULL; + } + // prepare the file for parsing + Io_BlifReadPreparse( p ); + // construct the network + pAig = Io_BlifParse( p ); + if ( p->sError[0] ) + fprintf( stdout, "%s\n", p->sError ); + if ( pAig == NULL ) + return NULL; + Io_BlifFree( p ); + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pAig ) ) + { + printf( "Io_Blif: The network check has failed.\n" ); + Abc_NtkDelete( pAig ); + return NULL; + } + return pAig; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifMan_t * Io_BlifAlloc() +{ + Io_BlifMan_t * p; + p = ALLOC( Io_BlifMan_t, 1 ); + memset( p, 0, sizeof(Io_BlifMan_t) ); + p->vLines = Vec_PtrAlloc( 512 ); + p->vInputs = Vec_PtrAlloc( 512 ); + p->vOutputs = Vec_PtrAlloc( 512 ); + p->vLatches = Vec_PtrAlloc( 512 ); + p->vNames = Vec_PtrAlloc( 512 ); + p->vTokens = Vec_PtrAlloc( 512 ); + p->vPis = Vec_PtrAlloc( 512 ); + p->vPos = Vec_PtrAlloc( 512 ); + p->vLis = Vec_PtrAlloc( 512 ); + p->vLos = Vec_PtrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifFree( Io_BlifMan_t * p ) +{ + if ( p->pAig ) + Abc_NtkDelete( p->pAig ); + if ( p->pBuffer ) free( p->pBuffer ); + if ( p->pObjects ) free( p->pObjects ); + if ( p->pTable ) free( p->pTable ); + Vec_PtrFree( p->vLines ); + Vec_PtrFree( p->vInputs ); + Vec_PtrFree( p->vOutputs ); + Vec_PtrFree( p->vLatches ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vTokens ); + Vec_PtrFree( p->vPis ); + Vec_PtrFree( p->vPos ); + Vec_PtrFree( p->vLis ); + Vec_PtrFree( p->vLos ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Hashing for character strings.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static unsigned Io_BlifHashString( char * pName, int TableSize ) +{ + static int s_Primes[10] = { + 1291, 1699, 2357, 4177, 5147, + 5647, 6343, 7103, 7873, 8147 + }; + unsigned i, Key = 0; + for ( i = 0; pName[i] != '\0'; i++ ) + Key ^= s_Primes[i%10]*pName[i]*pName[i]; + return Key % TableSize; +} + +/**Function************************************************************* + + Synopsis [Checks if the given name exists in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName ) +{ + Io_BlifObj_t ** ppEntry; + for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) + if ( !strcmp((*ppEntry)->pName, pName) ) + return ppEntry; + return ppEntry; +} + +/**Function************************************************************* + + Synopsis [Finds or add the given name to the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName ) +{ + Io_BlifObj_t ** ppEntry; + ppEntry = Io_BlifHashLookup( p, pName ); + if ( *ppEntry == NULL ) + { + assert( p->iObjNext < p->nObjects ); + *ppEntry = p->pObjects + p->iObjNext++; + (*ppEntry)->pName = pName; + } + return *ppEntry; +} + + +/**Function************************************************************* + + Synopsis [Collects the already split tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) +{ + char * pCur; + Vec_PtrClear( vTokens ); + for ( pCur = pInput; pCur < pOutput; pCur++ ) + { + if ( *pCur == 0 ) + continue; + Vec_PtrPush( vTokens, pCur ); + while ( *++pCur ); + } +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_BlifCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_BlifCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Returns the 1-based number of the line in which the token occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken ) +{ + char * pLine; + int i; + Vec_PtrForEachEntry( p->vLines, pLine, i ) + if ( pToken < pLine ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Conservatively estimates the number of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifEstimatePiNum( Io_BlifMan_t * p ) +{ + char * pCur; + int i, fSpaces; + int Counter = 0; + Vec_PtrForEachEntry( p->vInputs, pCur, i ) + for ( fSpaces = 0; *pCur; pCur++ ) + { + if ( Io_BlifCharIsSpace(*pCur) ) + { + if ( !fSpaces ) + Counter++; + fSpaces = 1; + } + else + fSpaces = 0; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Conservatively estimates the number of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifEstimateAndNum( Io_BlifMan_t * p ) +{ + Io_BlifObj_t * pObj; + char * pCur; + int i, CounterOne, Counter = 0; + for ( i = 0; i < p->iObjNext; i++ ) + { + pObj = p->pObjects + i; + if ( !pObj->fDef ) + continue; + CounterOne = 0; + for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ ) + if ( *pCur == '0' || *pCur == '1' ) + CounterOne++; + if ( CounterOne ) + Counter += CounterOne - 1; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reads the file into a character buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_BlifLoadFile( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + char * pContents; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize == 0 ) + { + printf( "Io_BlifLoadFile(): The file is empty.\n" ); + return NULL; + } + pContents = ALLOC( char, nFileSize + 10 ); + rewind( pFile ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + // finish off the file with the spare .end line + // some benchmarks suddenly break off without this line + strcpy( pContents + nFileSize, "\n.end\n" ); + return pContents; +} + +/**Function************************************************************* + + Synopsis [Prepares the parsing.] + + Description [Performs several preliminary operations: + - Cuts the file buffer into separate lines. + - Removes comments and line extenders. + - Sorts lines by directives. + - Estimates the number of objects. + - Allocates room for the objects. + - Allocates room for the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifReadPreparse( Io_BlifMan_t * p ) +{ + char * pCur, * pPrev; + int i, fComment = 0; + // parse the buffer into lines and remove comments + Vec_PtrPush( p->vLines, p->pBuffer ); + for ( pCur = p->pBuffer; *pCur; pCur++ ) + { + if ( *pCur == '\n' ) + { + *pCur = 0; + fComment = 0; + Vec_PtrPush( p->vLines, pCur + 1 ); + } + else if ( *pCur == '#' ) + fComment = 1; + // remove comments + if ( fComment ) + *pCur = 0; + } + + // unfold the line extensions and sort lines by directive + Vec_PtrForEachEntry( p->vLines, pCur, i ) + { + if ( *pCur == 0 ) + continue; + // find previous non-space character + for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) + if ( !Io_BlifCharIsSpace(*pPrev) ) + break; + // if it is the line extender, overwrite it with spaces + if ( *pPrev == '\\' ) + { + for ( ; *pPrev; pPrev++ ) + *pPrev = ' '; + *pPrev = ' '; + continue; + } + // skip spaces at the beginning of the line + while ( Io_BlifCharIsSpace(*pCur++) ); + // parse directives + if ( *(pCur-1) != '.' ) + continue; + if ( !strncmp(pCur, "names", 5) ) + Vec_PtrPush( p->vNames, pCur ); + else if ( !strncmp(pCur, "latch", 5) ) + Vec_PtrPush( p->vLatches, pCur ); + else if ( !strncmp(pCur, "inputs", 6) ) + Vec_PtrPush( p->vInputs, pCur ); + else if ( !strncmp(pCur, "outputs", 7) ) + Vec_PtrPush( p->vOutputs, pCur ); + else if ( !strncmp(pCur, "model", 5) ) + p->pModel = pCur; + else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) ) + break; + else + { + pCur--; + if ( pCur[strlen(pCur)-1] == '\r' ) + pCur[strlen(pCur)-1] = 0; + fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur ); + } + } + + // count the number of objects + p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512; + + // allocate memory for objects + p->pObjects = ALLOC( Io_BlifObj_t, p->nObjects ); + memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) ); + + // allocate memory for the hash table + p->nTableSize = p->nObjects/2 + 1; + p->pTable = ALLOC( Io_BlifObj_t *, p->nTableSize ); + memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) ); +} + + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ) +{ + Abc_Ntk_t * pAig; + char * pLine; + int i; + // parse the model + if ( !Io_BlifParseModel( p, p->pModel ) ) + return NULL; + // parse the inputs + Vec_PtrForEachEntry( p->vInputs, pLine, i ) + if ( !Io_BlifParseInputs( p, pLine ) ) + return NULL; + // parse the outputs + Vec_PtrForEachEntry( p->vOutputs, pLine, i ) + if ( !Io_BlifParseOutputs( p, pLine ) ) + return NULL; + // parse the latches + Vec_PtrForEachEntry( p->vLatches, pLine, i ) + if ( !Io_BlifParseLatch( p, pLine ) ) + return NULL; + // parse the nodes + Vec_PtrForEachEntry( p->vNames, pLine, i ) + if ( !Io_BlifParseNames( p, pLine ) ) + return NULL; + // reconstruct the network from the parsed data + if ( !Io_BlifParseConstruct( p ) ) + return NULL; + // return the network + pAig = p->pAig; + p->pAig = NULL; + return pAig; +} + +/**Function************************************************************* + + Synopsis [Parses the model line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ) +{ + char * pToken; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry( p->vTokens, 0 ); + assert( !strcmp(pToken, "model") ); + if ( Vec_PtrSize(p->vTokens) != 2 ) + { + sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) ); + return 0; + } + p->pModel = Vec_PtrEntry( p->vTokens, 1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the inputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int i; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens, 0); + assert( !strcmp(pToken, "inputs") ); + Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 ) + { + pObj = Io_BlifHashFindOrAdd( p, pToken ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken ); + return 0; + } + pObj->fPi = 1; + Vec_PtrPush( p->vPis, pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the outputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int i; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens, 0); + assert( !strcmp(pToken, "outputs") ); + Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 ) + { + pObj = Io_BlifHashFindOrAdd( p, pToken ); + if ( pObj->fPo ) + fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken ); + pObj->fPo = 1; + Vec_PtrPush( p->vPos, pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the latches line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int Init; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens,0); + assert( !strcmp(pToken, "latch") ); + if ( Vec_PtrSize(p->vTokens) < 3 ) + { + sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) ); + return 0; + } + // get initial value + if ( Vec_PtrSize(p->vTokens) > 3 ) + Init = atoi( Vec_PtrEntry(p->vTokens,3) ); + else + Init = 2; + if ( Init < 0 || Init > 2 ) + { + sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,3) ); + return 0; + } + if ( Init == 0 ) + Init = IO_BLIF_INIT_ZERO; + else if ( Init == 1 ) + Init = IO_BLIF_INIT_ONE; + else // if ( Init == 2 ) + Init = IO_BLIF_INIT_DC; + // get latch input + pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,1) ); + pObj->fLi = 1; + Vec_PtrPush( p->vLis, pObj ); + pObj->Init = Init; + // get latch output + pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,2) ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) ); + return 0; + } + if ( pObj->fLo ) + { + sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) ); + return 0; + } + pObj->fLo = 1; + Vec_PtrPush( p->vLos, pObj ); + pObj->Init = Init; + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pName; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + assert( !strcmp(Vec_PtrEntry(p->vTokens,0), "names") ); + pName = Vec_PtrEntryLast( p->vTokens ); + pObj = Io_BlifHashFindOrAdd( p, pName ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + if ( pObj->fLo ) + { + sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + if ( pObj->fDef ) + { + sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + pObj->fDef = 1; + // remember offset to the first fanin name + pObj->pName = pName; + pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins ) +{ + char * pProduct, * pOutput; + Abc_Obj_t * pRes, * pCube; + int i, k, Polarity = -1; + + p->nTablesRead++; + // get the tokens + Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' ); + if ( Vec_PtrSize(p->vTokens) == 0 ) + return Abc_ObjNot( Abc_AigConst1(p->pAig) ); + if ( Vec_PtrSize(p->vTokens) == 1 ) + { + pOutput = Vec_PtrEntry( p->vTokens, 0 ); + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput ); + return NULL; + } + return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' ); + } + pProduct = Vec_PtrEntry( p->vTokens, 0 ); + if ( Vec_PtrSize(p->vTokens) % 2 == 1 ) + { + sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) ); + return NULL; + } + // parse the table + pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) ); + for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ ) + { + pProduct = Vec_PtrEntry( p->vTokens, 2*i + 0 ); + pOutput = Vec_PtrEntry( p->vTokens, 2*i + 1 ); + if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) ) + { + sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) ); + return NULL; + } + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput ); + return NULL; + } + if ( Polarity == -1 ) + Polarity = pOutput[0] - '0'; + else if ( Polarity != pOutput[0] - '0' ) + { + sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity ); + return NULL; + } + // parse one product product + pCube = Abc_AigConst1(p->pAig); + for ( k = 0; pProduct[k]; k++ ) + { + if ( pProduct[k] == '0' ) + pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Abc_ObjNot(Vec_PtrEntry(vFanins,k)) ); + else if ( pProduct[k] == '1' ) + pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Vec_PtrEntry(vFanins,k) ); + else if ( pProduct[k] != '-' ) + { + sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] ); + return NULL; + } + } + pRes = Abc_AigOr( p->pAig->pManFunc, pRes, pCube ); + } + pRes = Abc_ObjNotCond( pRes, Polarity == 0 ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName ) +{ + Vec_Ptr_t * vFanins; + Abc_Obj_t * pFaninAbc; + Io_BlifObj_t * pObjIo; + char * pNameFanin; + int i; + // get the IO object with this name + pObjIo = *Io_BlifHashLookup( p, pName ); + if ( pObjIo == NULL ) + { + sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName ); + return NULL; + } + // loop detection + if ( pObjIo->fLoop ) + { + sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName ); + return NULL; + } + // check if the AIG is already constructed + if ( pObjIo->pEquiv ) + return pObjIo->pEquiv; + // mark this node on the path + pObjIo->fLoop = 1; + // construct the AIGs for the fanins + vFanins = Vec_PtrAlloc( 8 ); + Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName ); + Vec_PtrForEachEntry( vFanins, pNameFanin, i ) + { + pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin ); + if ( pFaninAbc == NULL ) + { + Vec_PtrFree( vFanins ); + return NULL; + } + Vec_PtrWriteEntry( vFanins, i, pFaninAbc ); + } + // construct the node + pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins ); + Vec_PtrFree( vFanins ); + // unmark this node on the path + pObjIo->fLoop = 0; + // remember the new node + return pObjIo->pEquiv; +} + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseConstruct( Io_BlifMan_t * p ) +{ + Abc_Ntk_t * pAig; + Io_BlifObj_t * pObjIo, * pObjIoInput; + Abc_Obj_t * pObj, * pLatch; + int i; + // allocate the empty AIG + pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pAig->pName = Extra_UtilStrsav( p->pModel ); + pAig->pSpec = Extra_UtilStrsav( p->pFileName ); + // create PIs + Vec_PtrForEachEntry( p->vPis, pObjIo, i ) + { + pObj = Abc_NtkCreatePi( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + pObjIo->pEquiv = pObj; + } + // create POs + Vec_PtrForEachEntry( p->vPos, pObjIo, i ) + { + pObj = Abc_NtkCreatePo( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + } + // create latches + Vec_PtrForEachEntry( p->vLos, pObjIo, i ) + { + // add the latch input terminal + pObj = Abc_NtkCreateBi( pAig ); + pObjIoInput = Vec_PtrEntry( p->vLis, i ); + Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL ); + + // add the latch box + pLatch = Abc_NtkCreateLatch( pAig ); + pLatch->pData = (void *)pObjIo->Init; + Abc_ObjAssignName( pLatch, pObjIo->pName, "L" ); + Abc_ObjAddFanin( pLatch, pObj ); + + // add the latch output terminal + pObj = Abc_NtkCreateBo( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + Abc_ObjAddFanin( pObj, pLatch ); + // set the value of the latch output +// pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init ); + pObjIo->pEquiv = pObj; + } + // traverse the nodes from the POs + Vec_PtrForEachEntry( p->vPos, pObjIo, i ) + { + pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); + if ( pObj == NULL ) + return 0; + Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj ); + } + // traverse the nodes from the latch inputs + Vec_PtrForEachEntry( p->vLis, pObjIo, i ) + { + pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); + if ( pObj == NULL ) + return 0; +// pObj = Abc_ObjNotCond( pObj, pObjIo->Init ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj ); + } + p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead; + if ( p->nTablesLeft ) + printf( "The number of dangling tables = %d.\n", p->nTablesLeft ); + printf( "AND nodes = %6d. Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBlifMv.c b/abc70930/src/base/io/ioReadBlifMv.c new file mode 100644 index 00000000..18578cbb --- /dev/null +++ b/abc70930/src/base/io/ioReadBlifMv.c @@ -0,0 +1,1696 @@ +/**CFile**************************************************************** + + FileName [ioReadBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF-MV file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 8, 2007.] + + Revision [$Id: ioReadBlifMv.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "extra.h" +#include "vecPtr.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IO_BLIFMV_MAXVALUES 256 + +typedef struct Io_MvVar_t_ Io_MvVar_t; // parsing var +typedef struct Io_MvMod_t_ Io_MvMod_t; // parsing model +typedef struct Io_MvMan_t_ Io_MvMan_t; // parsing manager + +struct Io_MvVar_t_ +{ + int nValues; // the number of values + char ** pNames; // the value names +}; + +struct Io_MvMod_t_ +{ + // file lines + char * pName; // .model line + Vec_Ptr_t * vInputs; // .inputs lines + Vec_Ptr_t * vOutputs; // .outputs lines + Vec_Ptr_t * vLatches; // .latch lines + Vec_Ptr_t * vResets; // .reset lines + Vec_Ptr_t * vNames; // .names lines + Vec_Ptr_t * vSubckts; // .subckt lines + Vec_Ptr_t * vMvs; // .mv lines + int fBlackBox; // indicates blackbox model + // the resulting network + Abc_Ntk_t * pNtk; + Abc_Obj_t * pResetLatch; + // the parent manager + Io_MvMan_t * pMan; +}; + +struct Io_MvMan_t_ +{ + // general info about file + int fBlifMv; // the file is BLIF-MV + int fUseReset; // the reset circuitry is added + char * pFileName; // the name of the file + char * pBuffer; // the contents of the file + Vec_Ptr_t * vLines; // the line beginnings + // the results of reading + Abc_Lib_t * pDesign; // the design under construction + int nNDnodes; // the counter of ND nodes + // intermediate storage for models + Vec_Ptr_t * vModels; // vector of models + Io_MvMod_t * pLatest; // the current model + // current processing info + Vec_Ptr_t * vTokens; // the current tokens + Vec_Ptr_t * vTokens2; // the current tokens + Vec_Str_t * vFunc; // the local function + // error reporting + char sError[512]; // the error string generated during parsing + // statistics + int nTablesRead; // the number of processed tables + int nTablesLeft; // the number of dangling tables +}; + +// static functions +static Io_MvMan_t * Io_MvAlloc(); +static void Io_MvFree( Io_MvMan_t * p ); +static Io_MvMod_t * Io_MvModAlloc(); +static void Io_MvModFree( Io_MvMod_t * p ); +static char * Io_MvLoadFile( char * pFileName ); +static void Io_MvReadPreparse( Io_MvMan_t * p ); +static void Io_MvReadInterfaces( Io_MvMan_t * p ); +static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p ); +static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ); +static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ); +static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ); + +static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } +static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; } + +extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from the BLIF or BLIF-MV file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ) +{ + FILE * pFile; + Io_MvMan_t * p; + Abc_Ntk_t * pNtk; + Abc_Lib_t * pDesign; + char * pDesignName; + int RetValue, i; + + // check that the file is available + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" ); + return 0; + } + fclose( pFile ); + + // start the file reader + p = Io_MvAlloc(); + p->fBlifMv = fBlifMv; + p->fUseReset = 0; + p->pFileName = pFileName; + p->pBuffer = Io_MvLoadFile( pFileName ); + if ( p->pBuffer == NULL ) + { + Io_MvFree( p ); + return NULL; + } + // set the design name + pDesignName = Extra_FileNameGeneric( pFileName ); + p->pDesign = Abc_LibCreate( pDesignName ); + free( pDesignName ); + // free the HOP manager + Hop_ManStop( p->pDesign->pManFunc ); + p->pDesign->pManFunc = NULL; + // prepare the file for parsing + Io_MvReadPreparse( p ); + // parse interfaces of each network + Io_MvReadInterfaces( p ); + // construct the network + pDesign = Io_MvParse( p ); + if ( p->sError[0] ) + fprintf( stdout, "%s\n", p->sError ); + if ( pDesign == NULL ) + return NULL; + Io_MvFree( p ); +// pDesign should be linked to all models of the design + + // make sure that everything is okay with the network structure + if ( fCheck ) + { + Vec_PtrForEachEntry( pDesign->vModules, pNtk, i ) + { + if ( !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBlifMv: The network check has failed for network %s.\n", pNtk->pName ); + Abc_LibFree( pDesign, NULL ); + return NULL; + } + } + } + +//Abc_LibPrint( pDesign ); + + // detect top-level model + RetValue = Abc_LibFindTopLevelModels( pDesign ); + pNtk = Vec_PtrEntry( pDesign->vTops, 0 ); + if ( RetValue > 1 ) + printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", + Vec_PtrSize(pDesign->vTops), pNtk->pName ); + + // extract the master network + pNtk->pDesign = pDesign; + pDesign->pManFunc = NULL; + + // verify the design for cyclic dependence + assert( Vec_PtrSize(pDesign->vModules) > 0 ); + if ( Vec_PtrSize(pDesign->vModules) == 1 ) + { +// printf( "Warning: The design is not hierarchical.\n" ); + Abc_LibFree( pDesign, pNtk ); + pNtk->pDesign = NULL; + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + } + else + Abc_NtkIsAcyclicHierarchy( pNtk ); + +//Io_WriteBlifMv( pNtk, "_temp_.mv" ); + if ( pNtk->pSpec == NULL ) + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_MvMan_t * Io_MvAlloc() +{ + Io_MvMan_t * p; + p = ALLOC( Io_MvMan_t, 1 ); + memset( p, 0, sizeof(Io_MvMan_t) ); + p->vLines = Vec_PtrAlloc( 512 ); + p->vModels = Vec_PtrAlloc( 512 ); + p->vTokens = Vec_PtrAlloc( 512 ); + p->vTokens2 = Vec_PtrAlloc( 512 ); + p->vFunc = Vec_StrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvFree( Io_MvMan_t * p ) +{ + Io_MvMod_t * pMod; + int i; + if ( p->pDesign ) + Abc_LibFree( p->pDesign, NULL ); + if ( p->pBuffer ) + free( p->pBuffer ); + if ( p->vLines ) + Vec_PtrFree( p->vLines ); + if ( p->vModels ) + { + Vec_PtrForEachEntry( p->vModels, pMod, i ) + Io_MvModFree( pMod ); + Vec_PtrFree( p->vModels ); + } + Vec_PtrFree( p->vTokens ); + Vec_PtrFree( p->vTokens2 ); + Vec_StrFree( p->vFunc ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure for one model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_MvMod_t * Io_MvModAlloc() +{ + Io_MvMod_t * p; + p = ALLOC( Io_MvMod_t, 1 ); + memset( p, 0, sizeof(Io_MvMod_t) ); + p->vInputs = Vec_PtrAlloc( 512 ); + p->vOutputs = Vec_PtrAlloc( 512 ); + p->vLatches = Vec_PtrAlloc( 512 ); + p->vResets = Vec_PtrAlloc( 512 ); + p->vNames = Vec_PtrAlloc( 512 ); + p->vSubckts = Vec_PtrAlloc( 512 ); + p->vMvs = Vec_PtrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure for one model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvModFree( Io_MvMod_t * p ) +{ +// if ( p->pNtk ) +// Abc_NtkDelete( p->pNtk ); + Vec_PtrFree( p->vInputs ); + Vec_PtrFree( p->vOutputs ); + Vec_PtrFree( p->vLatches ); + Vec_PtrFree( p->vResets ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vSubckts ); + Vec_PtrFree( p->vMvs ); + free( p ); +} + + + +/**Function************************************************************* + + Synopsis [Counts the number of given chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvCountChars( char * pLine, char Char ) +{ + char * pCur; + int Counter = 0; + for ( pCur = pLine; *pCur; pCur++ ) + if ( *pCur == Char ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the place where the arrow is hiding.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvFindArrow( char * pLine ) +{ + char * pCur; + for ( pCur = pLine; *(pCur+1); pCur++ ) + if ( *pCur == '-' && *(pCur+1) == '>' ) + { + *pCur = ' '; + *(pCur+1) = ' '; + return pCur; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Collects the already split tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) +{ + char * pCur; + Vec_PtrClear( vTokens ); + for ( pCur = pInput; pCur < pOutput; pCur++ ) + { + if ( *pCur == 0 ) + continue; + Vec_PtrPush( vTokens, pCur ); + while ( *++pCur ); + } +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens when .default may be present.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) || *pCur == Char ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Returns the 1-based number of the line in which the token occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvGetLine( Io_MvMan_t * p, char * pToken ) +{ + char * pLine; + int i; + Vec_PtrForEachEntry( p->vLines, pLine, i ) + if ( pToken < pLine ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Reads the file into a character buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvLoadFile( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + char * pContents; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize == 0 ) + { + printf( "Io_MvLoadFile(): The file is empty.\n" ); + return NULL; + } + pContents = ALLOC( char, nFileSize + 10 ); + rewind( pFile ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + // finish off the file with the spare .end line + // some benchmarks suddenly break off without this line + strcpy( pContents + nFileSize, "\n.end\n" ); + return pContents; +} + +/**Function************************************************************* + + Synopsis [Prepares the parsing.] + + Description [Performs several preliminary operations: + - Cuts the file buffer into separate lines. + - Removes comments and line extenders. + - Sorts lines by directives. + - Estimates the number of objects. + - Allocates room for the objects. + - Allocates room for the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvReadPreparse( Io_MvMan_t * p ) +{ + char * pCur, * pPrev; + int i, fComment = 0; + // parse the buffer into lines and remove comments + Vec_PtrPush( p->vLines, p->pBuffer ); + for ( pCur = p->pBuffer; *pCur; pCur++ ) + { + if ( *pCur == '\n' ) + { + *pCur = 0; +// if ( *(pCur-1) == '\r' ) +// *(pCur-1) = 0; + fComment = 0; + Vec_PtrPush( p->vLines, pCur + 1 ); + } + else if ( *pCur == '#' ) + fComment = 1; + // remove comments + if ( fComment ) + *pCur = 0; + } + + // unfold the line extensions and sort lines by directive + Vec_PtrForEachEntry( p->vLines, pCur, i ) + { + if ( *pCur == 0 ) + continue; + // find previous non-space character + for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) + if ( !Io_MvCharIsSpace(*pPrev) ) + break; + // if it is the line extender, overwrite it with spaces + if ( *pPrev == '\\' ) + { + for ( ; *pPrev; pPrev++ ) + *pPrev = ' '; + *pPrev = ' '; + continue; + } + // skip spaces at the beginning of the line + while ( Io_MvCharIsSpace(*pCur++) ); + // parse directives + if ( *(pCur-1) != '.' ) + continue; + if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) ) + Vec_PtrPush( p->pLatest->vNames, pCur ); + else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) ) + continue; + else if ( !strncmp(pCur, "latch", 5) ) + Vec_PtrPush( p->pLatest->vLatches, pCur ); + else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) ) + Vec_PtrPush( p->pLatest->vResets, pCur ); + else if ( !strncmp(pCur, "inputs", 6) ) + Vec_PtrPush( p->pLatest->vInputs, pCur ); + else if ( !strncmp(pCur, "outputs", 7) ) + Vec_PtrPush( p->pLatest->vOutputs, pCur ); + else if ( !strncmp(pCur, "subckt", 6) ) + Vec_PtrPush( p->pLatest->vSubckts, pCur ); + else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) ) + Vec_PtrPush( p->pLatest->vMvs, pCur ); + else if ( !strncmp(pCur, "blackbox", 8) ) + p->pLatest->fBlackBox = 1; + else if ( !strncmp(pCur, "model", 5) ) + { + p->pLatest = Io_MvModAlloc(); + p->pLatest->pName = pCur; + p->pLatest->pMan = p; + } + else if ( !strncmp(pCur, "end", 3) ) + { + if ( p->pLatest ) + Vec_PtrPush( p->vModels, p->pLatest ); + p->pLatest = NULL; + } + else if ( !strncmp(pCur, "exdc", 4) ) + { + fprintf( stdout, "Line %d: Skipping EXDC network.\n", Io_MvGetLine(p, pCur) ); + break; + } + else + { + pCur--; + if ( pCur[strlen(pCur)-1] == '\r' ) + pCur[strlen(pCur)-1] = 0; + fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur ); + } + } +} + +/**Function************************************************************* + + Synopsis [Parses interfaces of the models.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvReadInterfaces( Io_MvMan_t * p ) +{ + Io_MvMod_t * pMod; + char * pLine; + int i, k; + // iterate through the models + Vec_PtrForEachEntry( p->vModels, pMod, i ) + { + // parse the model + if ( !Io_MvParseLineModel( pMod, pMod->pName ) ) + return; + // add model to the design + if ( !Abc_LibAddModel( p->pDesign, pMod->pNtk ) ) + { + sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName ); + return; + } + // parse the inputs + Vec_PtrForEachEntry( pMod->vInputs, pLine, k ) + if ( !Io_MvParseLineInputs( pMod, pLine ) ) + return; + // parse the outputs + Vec_PtrForEachEntry( pMod->vOutputs, pLine, k ) + if ( !Io_MvParseLineOutputs( pMod, pLine ) ) + return; + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p ) +{ + Abc_Lib_t * pDesign; + Io_MvMod_t * pMod; + char * pLine; + int i, k; + // iterate through the models + Vec_PtrForEachEntry( p->vModels, pMod, i ) + { + // check if there any MV lines + if ( Vec_PtrSize(pMod->vMvs) > 0 ) + Abc_NtkStartMvVars( pMod->pNtk ); + // parse the mv lines + Vec_PtrForEachEntry( pMod->vMvs, pLine, k ) + if ( !Io_MvParseLineMv( pMod, pLine ) ) + return NULL; + // if reset lines are used there should be the same number of them as latches + if ( Vec_PtrSize(pMod->vResets) > 0 ) + { + if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) ) + { + sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).", + Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) ); + return NULL; + } + // create binary latch with 1-data and 0-init + if ( p->fUseReset ) + pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv ); + } + // parse the latches + Vec_PtrForEachEntry( pMod->vLatches, pLine, k ) + if ( !Io_MvParseLineLatch( pMod, pLine ) ) + return NULL; + // parse the reset lines + if ( p->fUseReset ) + Vec_PtrForEachEntry( pMod->vResets, pLine, k ) + if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) ) + return NULL; + // parse the nodes + if ( p->fBlifMv ) + { + Vec_PtrForEachEntry( pMod->vNames, pLine, k ) + if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) ) + return NULL; + } + else + { + Vec_PtrForEachEntry( pMod->vNames, pLine, k ) + if ( !Io_MvParseLineNamesBlif( pMod, pLine ) ) + return NULL; + } + // parse the subcircuits + Vec_PtrForEachEntry( pMod->vSubckts, pLine, k ) + if ( !Io_MvParseLineSubckt( pMod, pLine ) ) + return NULL; + // finalize the network + Abc_NtkFinalizeRead( pMod->pNtk ); + } + if ( p->nNDnodes ) +// printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes ); + printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes ); + // return the network + pDesign = p->pDesign; + p->pDesign = NULL; + return pDesign; +} + +/**Function************************************************************* + + Synopsis [Parses the model line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry( vTokens, 0 ); + assert( !strcmp(pToken, "model") ); + if ( Vec_PtrSize(vTokens) != 2 ) + { + sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); + return 0; + } + if ( p->fBlackBox ) + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 ); + else if ( p->pMan->fBlifMv ) + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 ); + else + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + p->pNtk->pName = Extra_UtilStrsav( Vec_PtrEntry(vTokens, 1) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the inputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens, 0); + assert( !strcmp(pToken, "inputs") ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + Io_ReadCreatePi( p->pNtk, pToken ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the outputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens, 0); + assert( !strcmp(pToken, "outputs") ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + Io_ReadCreatePo( p->pNtk, pToken ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the latches line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pObj, * pNet; + char * pToken; + int Init; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pToken, "latch") ); + if ( Vec_PtrSize(vTokens) < 3 ) + { + sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) ); + return 0; + } + // create latch + if ( p->pResetLatch == NULL ) + { + pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Vec_PtrEntry(vTokens,2) ); + // get initial value + if ( p->pMan->fBlifMv ) + Abc_LatchSetInit0( pObj ); + else + { + if ( Vec_PtrSize(vTokens) > 3 ) + Init = atoi( Vec_PtrEntry(vTokens,3) ); + else + Init = 2; + if ( Init < 0 || Init > 2 ) + { + sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) ); + return 0; + } + if ( Init == 0 ) + Abc_LatchSetInit0( pObj ); + else if ( Init == 1 ) + Abc_LatchSetInit1( pObj ); + else // if ( Init == 2 ) + Abc_LatchSetInitDc( pObj ); + } + } + else + { + // get the net corresponding to the output of the latch + pNet = Abc_NtkFindOrCreateNet( p->pNtk, Vec_PtrEntry(vTokens,2) ); + // get the net corresponding to the latch output (feeding into reset MUX) + pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") ); + // create latch + pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) ); + Abc_LatchSetInit0( pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the subckt line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Ntk_t * pModel; + Abc_Obj_t * pBox, * pNet, * pTerm; + char * pToken, * pName, ** ppNames; + int nEquals, i, k; + + // split the line into tokens + nEquals = Io_MvCountChars( pLine, '=' ); + Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); + pToken = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pToken, "subckt") ); + + // get the model for this box + pName = Vec_PtrEntry(vTokens,1); + pModel = Abc_LibFindModelByName( p->pMan->pDesign, pName ); + if ( pModel == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName ); + return 0; + } + + // check if the number of tokens is correct + if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ) + { + sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).", + Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ); + return 0; + } + + // get the names + ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv; + + // create the box with these terminals + if ( Abc_NtkHasBlackbox(pModel) ) + pBox = Abc_NtkCreateBlackbox( p->pNtk ); + else + pBox = Abc_NtkCreateWhitebox( p->pNtk ); + pBox->pData = pModel; + if ( p->pMan->fBlifMv ) + Abc_ObjAssignName( pBox, Vec_PtrEntry(vTokens,2), NULL ); + Abc_NtkForEachPi( pModel, pTerm, i ) + { + // find this terminal among the formal inputs of the subcircuit + pName = Abc_ObjName(Abc_ObjFanout0(pTerm)); + for ( k = 0; k < nEquals; k++ ) + if ( !strcmp( ppNames[2*k], pName ) ) + break; + if ( k == nEquals ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.", + Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); + return 0; + } + // create the BI with the actual name + pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); + pTerm = Abc_NtkCreateBi( p->pNtk ); + Abc_ObjAddFanin( pBox, pTerm ); + Abc_ObjAddFanin( pTerm, pNet ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + // find this terminal among the formal outputs of the subcircuit + pName = Abc_ObjName(Abc_ObjFanin0(pTerm)); + for ( k = 0; k < nEquals; k++ ) + if ( !strcmp( ppNames[2*k], pName ) ) + break; + if ( k == nEquals ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.", + Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); + return 0; + } + // create the BI with the actual name + pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); + pTerm = Abc_NtkCreateBo( p->pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + Abc_ObjAddFanin( pTerm, pBox ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Parses the mv line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pObj; + Io_MvVar_t * pVar; + Extra_MmFlex_t * pFlex; + char * pName; + int nCommas, nValues, i, k; + // count commas and get the tokens + nCommas = Io_MvCountChars( pLine, ',' ); + Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' ); + pName = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pName, "mv") ); + // get the number of values + if ( Vec_PtrSize(vTokens) <= nCommas + 2 ) + { + sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + nValues = atoi( Vec_PtrEntry(vTokens,nCommas+2) ); + if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES ) + { + sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).", + Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES ); + return 0; + } + // if there is no symbolic values, quit + if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 ) + return 1; + if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues ) + { + sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).", + Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues ); + return 0; + } + // go through variables + pFlex = Abc_NtkMvVarMan( p->pNtk ); + for ( i = 0; i <= nCommas; i++ ) + { + pName = Vec_PtrEntry( vTokens, i+1 ); + pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + // allocate variable + pVar = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); + pVar->nValues = nValues; + pVar->pNames = NULL; + // create names + if ( Vec_PtrSize(vTokens) > nCommas + 3 ) + { + pVar->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * nValues ); + Vec_PtrForEachEntryStart( vTokens, pName, k, nCommas + 3 ) + { + pVar->pNames[k-(nCommas + 3)] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pName) + 1 ); + strcpy( pVar->pNames[k-(nCommas + 3)], pName ); + } + } + // save the variable + Abc_ObjSetMvVar( pObj, pVar ); + } + // make sure the names are unique + if ( pVar->pNames ) + { + for ( i = 0; i < nValues; i++ ) + for ( k = i+1; k < nValues; k++ ) + if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) ) + { + pName = Vec_PtrEntry(vTokens,0); + sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.", + Io_MvGetLine(p->pMan, pName), pVar->pNames[i] ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the values into the BLIF-MV representation for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc ) +{ + char Buffer[10]; + Abc_Obj_t * pFanin; + int i; + // add the fanin number of values + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, ' ' ); + } + // add the node number of values + sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, '\n' ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Translated one literal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit ) +{ + char Buffer[10]; + Io_MvVar_t * pVar; + Abc_Obj_t * pFanin, * pNet; + char * pCur, * pNext; + int i; + // consider the equality literal + if ( pToken[0] == '=' ) + { + // find the fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) ) + break; + if ( i == Abc_ObjFaninNum(pNode) ) + { + sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.", + Io_MvGetLine(p->pMan, pToken), pToken + 1 ); + return 0; + } + Vec_StrPush( vFunc, '=' ); + sprintf( Buffer, "%d", i ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; + } + // consider regular literal + assert( iLit < Abc_ObjFaninNum(pNode) ); + pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode); + pVar = Abc_ObjMvVar( pNet ); + // if the var is absent or has no symbolic values quit + if ( pVar == NULL || pVar->pNames == NULL ) + { + Vec_StrAppend( vFunc, pToken ); + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; + } + // parse the literal using symbolic values + for ( pCur = pToken; *pCur; pCur++ ) + { + if ( Io_MvCharIsMvSymb(*pCur) ) + { + Vec_StrPush( vFunc, *pCur ); + continue; + } + // find the next MvSymb char + for ( pNext = pCur+1; *pNext; pNext++ ) + if ( Io_MvCharIsMvSymb(*pNext) ) + break; + // look for the value name + for ( i = 0; i < pVar->nValues; i++ ) + if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) ) + break; + if ( i == pVar->nValues ) + { + *pNext = 0; + sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".", + Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) ); + return 0; + } + // value name is found + sprintf( Buffer, "%d", i ); + Vec_StrAppend( vFunc, Buffer ); + // update the pointer + pCur = pNext - 1; + } + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Constructs the MV-SOP cover from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut ) +{ + Vec_Str_t * vFunc = p->pMan->vFunc; + char * pFirst, * pToken; + int iStart, i; + // prepare the place for the cover + Vec_StrClear( vFunc ); + // write the number of values +// Io_MvWriteValues( pNode, vFunc ); + // get the first token + pFirst = Vec_PtrEntry( vTokens2, 0 ); + if ( pFirst[0] == '.' ) + { + // write the default literal + Vec_StrPush( vFunc, 'd' ); + pToken = Vec_PtrEntry(vTokens2, 1 + iOut); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) + return NULL; + iStart = 1 + nOutputs; + } + else + iStart = 0; + // write the remaining literals + while ( iStart < Vec_PtrSize(vTokens2) ) + { + // input literals + for ( i = 0; i < nInputs; i++ ) + { + pToken = Vec_PtrEntry( vTokens2, iStart + i ); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) ) + return NULL; + } + // output literal + pToken = Vec_PtrEntry( vTokens2, iStart + nInputs + iOut ); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) + return NULL; + // update the counter + iStart += nInputs + nOutputs; + } + Vec_StrPush( vFunc, '\0' ); + return Vec_StrArray( vFunc ); +} + +/**Function************************************************************* + + Synopsis [Adds reset circuitry corresponding to latch with pName.] + + Description [Returns the reset node's net.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName ) +{ + char Buffer[50]; + Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet; + Io_MvVar_t * pVar; + // make sure the reset latch exists + assert( p->pResetLatch != NULL ); + // get the reset net + pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch)); + // get the output net + pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + // get the data nets + pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") ); + pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") ); + // duplicate MV variables + if ( Abc_NtkMvVar(p->pNtk) ) + { + pVar = Abc_ObjMvVar( pOutNet ); + Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); + Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); + } + // create the node + pNode = Abc_NtkCreateNode( p->pNtk ); + // create the output net + Abc_ObjAddFanin( pOutNet, pNode ); + // create the function + if ( p->pMan->fBlifMv ) + { +// Vec_Att_t * p = Abc_NtkMvVar( pNtk ); + int nValues = Abc_ObjMvVarNum(pOutNet); +// sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues ); + sprintf( Buffer, "1 - - =1\n0 - - =2\n" ); + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, Buffer ); + } + else + pNode->pData = Abc_SopCreateMux( p->pNtk->pManFunc ); + // add nets + Abc_ObjAddFanin( pNode, pResetLONet ); + Abc_ObjAddFanin( pNode, pData1Net ); + Abc_ObjAddFanin( pNode, pData0Net ); + return pData0Net; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset ) +{ + Abc_Obj_t * pNet, * pNode; + char * pName; + // get the output name + pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut ); + // create the node + if ( fReset ) + { + pNet = Abc_NtkFindNet( p->pNtk, pName ); + if ( pNet == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } +/* + if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) ) + { + sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } +*/ + // construct the reset circuit and get the reset net feeding into it + pNet = Io_MvParseAddResetCircuit( p, pName ); + // create fanins + pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs ); + assert( nInputs == Vec_PtrSize(vTokens) - 2 ); + } + else + { + pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + if ( Abc_ObjFaninNum(pNet) > 0 ) + { + sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs ); + } + // create the cover + pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut ); + if ( pNode->pData == NULL ) + return 0; + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData ); +//printf( "Finished parsing node \"%s\" with table:\n%s\n", pName, pNode->pData ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Vec_Ptr_t * vTokens2 = p->pMan->vTokens2; + Abc_Obj_t * pNet; + char * pName, * pFirst, * pArrow; + int nInputs, nOutputs, nLiterals, nLines, i; + assert( p->pMan->fBlifMv ); + // get the arrow if it is present + pArrow = Io_MvFindArrow( pLine ); + if ( !p->pMan->fBlifMv && pArrow ) + { + sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) ); + return 0; + } + // split names line into tokens + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + if ( fReset ) + assert( !strcmp(Vec_PtrEntry(vTokens,0), "r") || !strcmp(Vec_PtrEntry(vTokens,0), "reset") ); + else + assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") || !strcmp(Vec_PtrEntry(vTokens,0), "table") ); + // find the number of inputs and outputs + nInputs = Vec_PtrSize(vTokens) - 2; + nOutputs = 1; + if ( pArrow != NULL ) + { + for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- ) + if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) ) + { + nInputs--; + nOutputs++; + } + } + // split table into tokens + pName = Vec_PtrEntryLast( vTokens ); + Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) ); + pFirst = Vec_PtrEntry( vTokens2, 0 ); + if ( pFirst[0] == '.' ) + { + assert( pFirst[1] == 'd' ); + nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs; + } + else + nLiterals = Vec_PtrSize(vTokens2); + // check the number of lines + if ( nLiterals % (nInputs + nOutputs) != 0 ) + { + sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName ); + return 0; + } + // check for the ND table + nLines = nLiterals / (nInputs + nOutputs); + if ( nInputs == 0 && nLines > 1 ) + { + // add the outputs to the PIs + for ( i = 0; i < nOutputs; i++ ) + { + pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i ); + // get the net corresponding to this node + pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName); + if ( fReset ) + { + assert( p->pResetLatch != NULL ); + // construct the reset circuit and get the reset net feeding into it + pNet = Io_MvParseAddResetCircuit( p, pName ); + } + // add the new PI node +// Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) ); +// fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName ); + p->pMan->nNDnodes++; + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) ); + } + return 1; + } + // iterate through the outputs + for ( i = 0; i < nOutputs; i++ ) + { + if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) ) + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Constructs the SOP cover from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Vec_Str_t * vFunc = p->pMan->vFunc; + char * pProduct, * pOutput; + int i, Polarity = -1; + + p->pMan->nTablesRead++; + // get the tokens + Io_MvSplitIntoTokens( vTokens, pTable, '.' ); + if ( Vec_PtrSize(vTokens) == 0 ) + return Abc_SopCreateConst0( p->pNtk->pManFunc ); + if ( Vec_PtrSize(vTokens) == 1 ) + { + pOutput = Vec_PtrEntry( vTokens, 0 ); + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput ); + return NULL; + } + return pOutput[0] == '0' ? Abc_SopCreateConst0(p->pNtk->pManFunc) : Abc_SopCreateConst1(p->pNtk->pManFunc); + } + pProduct = Vec_PtrEntry( vTokens, 0 ); + if ( Vec_PtrSize(vTokens) % 2 == 1 ) + { + sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) ); + return NULL; + } + // parse the table + Vec_StrClear( vFunc ); + for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ ) + { + pProduct = Vec_PtrEntry( vTokens, 2*i + 0 ); + pOutput = Vec_PtrEntry( vTokens, 2*i + 1 ); + if ( strlen(pProduct) != (unsigned)nFanins ) + { + sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins ); + return NULL; + } + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput ); + return NULL; + } + if ( Polarity == -1 ) + Polarity = pOutput[0] - '0'; + else if ( Polarity != pOutput[0] - '0' ) + { + sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity ); + return NULL; + } + // parse one product + Vec_StrAppend( vFunc, pProduct ); + Vec_StrPush( vFunc, ' ' ); + Vec_StrPush( vFunc, pOutput[0] ); + Vec_StrPush( vFunc, '\n' ); + } + Vec_StrPush( vFunc, '\0' ); + return Vec_StrArray( vFunc ); +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pNet, * pNode; + char * pName; + assert( !p->pMan->fBlifMv ); + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + // parse the mapped node + if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") ) + return Io_MvParseLineGateBlif( p, vTokens ); + // parse the regular name line + assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") ); + pName = Vec_PtrEntryLast( vTokens ); + pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + if ( Abc_ObjFaninNum(pNet) > 0 ) + { + sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + // create fanins + pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 ); + // parse the table of this node + pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) ); + if ( pNode->pData == NULL ) + return 0; + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Duplicate the MV variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ) +{ + Extra_MmFlex_t * pFlex; + Io_MvVar_t * pVarDup; + int i; + if ( pVar == NULL ) + return NULL; + pFlex = Abc_NtkMvVarMan( pNtk ); + assert( pFlex != NULL ); + pVarDup = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); + pVarDup->nValues = pVar->nValues; + pVarDup->pNames = NULL; + if ( pVar->pNames == NULL ) + return pVarDup; + pVarDup->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues ); + for ( i = 0; i < pVar->nValues; i++ ) + { + pVarDup->pNames[i] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 ); + strcpy( pVarDup->pNames[i], pVar->pNames[i] ); + } + return pVarDup; +} + + +#include "mio.h" +#include "main.h" + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_ReadBlifCleanName( char * pName ) +{ + int i, Length; + Length = strlen(pName); + for ( i = 0; i < Length; i++ ) + if ( pName[i] == '=' ) + return pName + i + 1; + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ) +{ + Mio_Library_t * pGenlib; + Mio_Gate_t * pGate; + Abc_Obj_t * pNode; + char ** ppNames, * pName; + int i, nNames; + + pName = vTokens->pArray[0]; + + // check that the library is available + pGenlib = Abc_FrameReadLibGen(); + if ( pGenlib == NULL ) + { + sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + + // get the gate + pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] ); + if ( pGate == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), vTokens->pArray[1] ); + return 0; + } + + // if this is the first line with gate, update the network type + if ( Abc_NtkNodeNum(p->pNtk) == 0 ) + { + assert( p->pNtk->ntkFunc == ABC_FUNC_SOP ); + p->pNtk->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( p->pNtk->pManFunc ); + p->pNtk->pManFunc = pGenlib; + } + + // remove the formal parameter names + for ( i = 2; i < vTokens->nSize; i++ ) + { + vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] ); + if ( vTokens->pArray[i] == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + } + + // create the node + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 3; + pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, pGate ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadDsd.c b/abc70930/src/base/io/ioReadDsd.c new file mode 100644 index 00000000..1ab726e5 --- /dev/null +++ b/abc70930/src/base/io/ioReadDsd.c @@ -0,0 +1,308 @@ +/**CFile**************************************************************** + + FileName [ioReadDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds the end of the part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_ReadDsdFindEnd( char * pCur ) +{ + char * pEnd; + int nParts = 0; + assert( *pCur == '(' ); + for ( pEnd = pCur; *pEnd; pEnd++ ) + { + if ( *pEnd == '(' ) + nParts++; + else if ( *pEnd == ')' ) + nParts--; + if ( nParts == 0 ) + return pEnd; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Splits the formula into parts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadDsdStrSplit( char * pCur, char * pParts[], int * pTypeXor ) +{ + int fAnd = 0, fXor = 0, fPri = 0, nParts = 0; + assert( *pCur ); + // process the parts + while ( 1 ) + { + // save the current part + pParts[nParts++] = pCur; + // skip the complement + if ( *pCur == '!' ) + pCur++; + // skip var + if ( *pCur >= 'a' && *pCur <= 'z' ) + pCur++; + else + { + // skip hex truth table + while ( (*pCur >= '0' && *pCur <= '9') || (*pCur >= 'A' && *pCur <= 'F') ) + pCur++; + // process parantheses + if ( *pCur != '(' ) + { + printf( "Cannot find the opening paranthesis.\n" ); + break; + } + // find the corresponding closing paranthesis + pCur = Io_ReadDsdFindEnd( pCur ); + if ( pCur == NULL ) + { + printf( "Cannot find the closing paranthesis.\n" ); + break; + } + pCur++; + } + // check the end + if ( *pCur == 0 ) + break; + // check symbol + if ( *pCur != '*' && *pCur != '+' && *pCur != ',' ) + { + printf( "Wrong separating symbol.\n" ); + break; + } + // remember the symbol + fAnd |= (*pCur == '*'); + fXor |= (*pCur == '+'); + fPri |= (*pCur == ','); + *pCur++ = 0; + } + // check separating symbols + if ( fAnd + fXor + fPri > 1 ) + { + printf( "Different types of separating symbol ennPartsed.\n" ); + return 0; + } + *pTypeXor = fXor; + return nParts; +} + +/**Function************************************************************* + + Synopsis [Recursively parses the formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadDsd_rec( Abc_Ntk_t * pNtk, char * pCur, char * pSop ) +{ + Abc_Obj_t * pObj, * pFanin; + char * pEnd, * pParts[32]; + int i, nParts, TypeExor; + + // consider complemented formula + if ( *pCur == '!' ) + { + pObj = Io_ReadDsd_rec( pNtk, pCur + 1, NULL ); + return Abc_NtkCreateNodeInv( pNtk, pObj ); + } + if ( *pCur == '(' ) + { + assert( pCur[strlen(pCur)-1] == ')' ); + pCur[strlen(pCur)-1] = 0; + nParts = Io_ReadDsdStrSplit( pCur+1, pParts, &TypeExor ); + if ( nParts == 0 ) + { + Abc_NtkDelete( pNtk ); + return NULL; + } + pObj = Abc_NtkCreateNode( pNtk ); + if ( pSop ) + { +// for ( i = nParts - 1; i >= 0; i-- ) + for ( i = 0; i < nParts; i++ ) + { + pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); + if ( pFanin == NULL ) + return NULL; + Abc_ObjAddFanin( pObj, pFanin ); + } + } + else + { + for ( i = 0; i < nParts; i++ ) + { + pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); + if ( pFanin == NULL ) + return NULL; + Abc_ObjAddFanin( pObj, pFanin ); + } + } + if ( pSop ) + pObj->pData = Abc_SopRegister( pNtk->pManFunc, pSop ); + else if ( TypeExor ) + pObj->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, nParts ); + else + pObj->pData = Abc_SopCreateAnd( pNtk->pManFunc, nParts, NULL ); + return pObj; + } + if ( *pCur >= 'a' && *pCur <= 'z' ) + { + assert( *(pCur+1) == 0 ); + return Abc_NtkPi( pNtk, *pCur - 'a' ); + } + + // skip hex truth table + pEnd = pCur; + while ( (*pEnd >= '0' && *pEnd <= '9') || (*pEnd >= 'A' && *pEnd <= 'F') ) + pEnd++; + if ( *pEnd != '(' ) + { + printf( "Cannot find the end of hexidecimal truth table.\n" ); + return NULL; + } + + // parse the truth table + *pEnd = 0; + pSop = Abc_SopFromTruthHex( pCur ); + *pEnd = '('; + pObj = Io_ReadDsd_rec( pNtk, pEnd, pSop ); + free( pSop ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Derives the DSD network of the formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadDsd( char * pForm ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pTop; + Vec_Ptr_t * vNames; + char * pCur, * pFormCopy; + int i, nInputs; + + // count the number of elementary variables + nInputs = 0; + for ( pCur = pForm; *pCur; pCur++ ) + if ( *pCur >= 'a' && *pCur <= 'z' ) + nInputs = ABC_MAX( nInputs, *pCur - 'a' ); + nInputs++; + + // create the network + pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtk->pName = Extra_UtilStrsav( "dsd" ); + + // create PIs + vNames = Abc_NodeGetFakeNames( nInputs ); + for ( i = 0; i < nInputs; i++ ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), Vec_PtrEntry(vNames, i), NULL ); + Abc_NodeFreeNames( vNames ); + + // transform the formula by inserting parantheses + // this transforms strings like PRIME(a,b,cd) into (PRIME((a),(b),(cd))) + pCur = pFormCopy = ALLOC( char, 3 * strlen(pForm) + 10 ); + *pCur++ = '('; + for ( ; *pForm; pForm++ ) + if ( *pForm == '(' ) + { + *pCur++ = '('; + *pCur++ = '('; + } + else if ( *pForm == ')' ) + { + *pCur++ = ')'; + *pCur++ = ')'; + } + else if ( *pForm == ',' ) + { + *pCur++ = ')'; + *pCur++ = ','; + *pCur++ = '('; + } + else + *pCur++ = *pForm; + *pCur++ = ')'; + *pCur = 0; + + // parse the formula + pObj = Io_ReadDsd_rec( pNtk, pFormCopy, NULL ); + free( pFormCopy ); + if ( pObj == NULL ) + return NULL; + + // create output + pTop = Abc_NtkCreatePo(pNtk); + Abc_ObjAssignName( pTop, "F", NULL ); + Abc_ObjAddFanin( pTop, pObj ); + + // create the only PO + if ( !Abc_NtkCheck( pNtk ) ) + { + fprintf( stdout, "Io_ReadDsd(): Network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadEdif.c b/abc70930/src/base/io/ioReadEdif.c new file mode 100644 index 00000000..188e5b8c --- /dev/null +++ b/abc70930/src/base/io/ioReadEdif.c @@ -0,0 +1,235 @@ +/**CFile**************************************************************** + + FileName [ioReadEdif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read ISCAS benchmarks in EDIF.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadEdif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from an EDIF file.] + + Description [Works only for the ISCAS benchmarks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + printf( "Currently this parser does not work!\n" ); + return NULL; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t()" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadEdifNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadEdif: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNet, * pObj, * pFanout; + char * pGateName, * pNetName; + int fTokensReady, iLine, i; + + // read the first line + vTokens = Extra_FileReaderGetTokens(p); + if ( strcmp( vTokens->pArray[0], "edif" ) != 0 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + return NULL; + } + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + fTokensReady = 0; + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 1; fTokensReady || (vTokens = Extra_FileReaderGetTokens(p)); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // get the type of the line + fTokensReady = 0; + if ( strcmp( vTokens->pArray[0], "instance" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetName ); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + pGateName = vTokens->pArray[1]; + if ( strncmp( pGateName, "Flip", 4 ) == 0 ) + { + pObj = Abc_NtkCreateLatch( pNtk ); + Abc_LatchSetInit0( pObj ); + } + else + { + pObj = Abc_NtkCreateNode( pNtk ); +// pObj->pData = Abc_NtkRegisterName( pNtk, pGateName ); + pObj->pData = Extra_UtilStrsav( pGateName ); // memory leak!!! + } + Abc_ObjAddFanin( pNet, pObj ); + } + else if ( strcmp( vTokens->pArray[0], "net" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) + continue; + if ( strcmp( pNetName + strlen(pNetName) - 4, "_out" ) == 0 ) + pNetName[strlen(pNetName) - 4] = 0; + pNet = Abc_NtkFindNet( pNtk, pNetName ); + assert( pNet ); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + while ( strcmp( vTokens->pArray[0], "portRef" ) == 0 ) + { + if ( strcmp( pNetName, vTokens->pArray[3] ) != 0 ) + { + pFanout = Abc_NtkFindNet( pNtk, vTokens->pArray[3] ); + Abc_ObjAddFanin( Abc_ObjFanin0(pFanout), pNet ); + } + vTokens = Extra_FileReaderGetTokens(p); + } + fTokensReady = 1; + } + else if ( strcmp( vTokens->pArray[0], "library" ) == 0 ) + { + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + while ( strcmp( vTokens->pArray[0], "port" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) + { + vTokens = Extra_FileReaderGetTokens(p); + continue; + } + if ( strcmp( pNetName + strlen(pNetName) - 3, "_PO" ) == 0 ) + pNetName[strlen(pNetName) - 3] = 0; + if ( strcmp( vTokens->pArray[3], "INPUT" ) == 0 ) + Io_ReadCreatePi( pNtk, vTokens->pArray[1] ); + else if ( strcmp( vTokens->pArray[3], "OUTPUT" ) == 0 ) + Io_ReadCreatePo( pNtk, vTokens->pArray[1] ); + else + { + printf( "%s (line %d): Wrong interface specification.\n", Extra_FileReaderGetFileName(p), iLine ); + Abc_NtkDelete( pNtk ); + return NULL; + } + vTokens = Extra_FileReaderGetTokens(p); + } + } + else if ( strcmp( vTokens->pArray[0], "design" ) == 0 ) + { + free( pNtk->pName ); + pNtk->pName = Extra_UtilStrsav( vTokens->pArray[3] ); + break; + } + } + Extra_ProgressBarStop( pProgress ); + + // assign logic functions + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( strncmp( pObj->pData, "And", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateAnd(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); + else if ( strncmp( pObj->pData, "Or", 2 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateOr(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); + else if ( strncmp( pObj->pData, "Nand", 4 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNand(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Nor", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Exor", 4 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateXor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Exnor", 5 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNxor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Inv", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateInv(pNtk->pManFunc) ); + else if ( strncmp( pObj->pData, "Buf", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateBuf(pNtk->pManFunc) ); + else + { + printf( "%s: Unknown gate type \"%s\".\n", Extra_FileReaderGetFileName(p), pObj->pData ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + // check if constants have been added +// if ( pNet = Abc_NtkFindNet( pNtk, "VDD" ) ) +// Io_ReadCreateConst( pNtk, "VDD", 1 ); +// if ( pNet = Abc_NtkFindNet( pNtk, "GND" ) ) +// Io_ReadCreateConst( pNtk, "GND", 0 ); + + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadEqn.c b/abc70930/src/base/io/ioReadEqn.c new file mode 100644 index 00000000..e04f2b1a --- /dev/null +++ b/abc70930/src/base/io/ioReadEqn.c @@ -0,0 +1,239 @@ +/**CFile**************************************************************** + + FileName [ioReadEqn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read equation format files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ); +static void Io_ReadEqnStrCompact( char * pStr ); +static int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ); +static void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a BENCH file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", ";", "=" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadEqnNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadEqn: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Vec_Ptr_t * vVars; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + char * pNodeName, * pFormula, * pFormulaCopy, * pVarName; + int iLine, i; + + // allocate the empty network + pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_AIG, 1 ); + // set the specs + pNtk->pName = Extra_FileNameGeneric(Extra_FileReaderGetFileName(p)); + pNtk->pSpec = Extra_UtilStrsav(Extra_FileReaderGetFileName(p)); + + // go through the lines of the file + vVars = Vec_PtrAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // check if the first token contains anything + Io_ReadEqnStrCompact( vTokens->pArray[0] ); + if ( strlen(vTokens->pArray[0]) == 0 ) + break; + + // if the number of tokens is different from two, error + if ( vTokens->nSize != 2 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + // get the type of the line + if ( strncmp( vTokens->pArray[0], "INORDER", 7 ) == 0 ) + { + Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); + Vec_PtrForEachEntry( vVars, pVarName, i ) + Io_ReadCreatePi( pNtk, pVarName ); + } + else if ( strncmp( vTokens->pArray[0], "OUTORDER", 8 ) == 0 ) + { + Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); + Vec_PtrForEachEntry( vVars, pVarName, i ) + Io_ReadCreatePo( pNtk, pVarName ); + } + else + { + extern Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ); + + // get hold of the node name and its formula + pNodeName = vTokens->pArray[0]; + pFormula = vTokens->pArray[1]; + // compact the formula + Io_ReadEqnStrCompact( pFormula ); + + // consider the case of the constant node + if ( pFormula[1] == 0 && (pFormula[0] == '0' || pFormula[0] == '1') ) + { + pFormulaCopy = NULL; + Vec_PtrClear( vVars ); + } + else + { + // make a copy of formula for names + pFormulaCopy = Extra_UtilStrsav( pFormula ); + // find the names of the fanins of this node + Io_ReadEqnStrCutAt( pFormulaCopy, "!*+()", 1, vVars ); + } + // create the node + pNode = Io_ReadCreateNode( pNtk, pNodeName, (char **)Vec_PtrArray(vVars), Vec_PtrSize(vVars) ); + // derive the function + pNode->pData = Parse_FormulaParserEqn( stdout, pFormula, vVars, pNtk->pManFunc ); + // remove the cubes + FREE( pFormulaCopy ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vVars ); + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + + + +/**Function************************************************************* + + Synopsis [Compacts the string by throwing away space-like chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadEqnStrCompact( char * pStr ) +{ + char * pCur, * pNew; + for ( pNew = pCur = pStr; *pCur; pCur++ ) + if ( !(*pCur == ' ' || *pCur == '\n' || *pCur == '\r' || *pCur == '\t') ) + *pNew++ = *pCur; + *pNew = 0; +} + +/**Function************************************************************* + + Synopsis [Determines unique variables in the string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ) +{ + char * pToken; + int i; + Vec_PtrForEachEntry( vTokens, pToken, i ) + if ( strcmp( pToken, pName ) == 0 ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Cuts the string into pieces using stop chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ) +{ + char * pToken; + Vec_PtrClear( vTokens ); + for ( pToken = strtok( pStr, pStop ); pToken; pToken = strtok( NULL, pStop ) ) + if ( !fUniqueOnly || Io_ReadEqnStrFind( vTokens, pToken ) == -1 ) + Vec_PtrPush( vTokens, pToken ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadPla.c b/abc70930/src/base/io/ioReadPla.c new file mode 100644 index 00000000..fdfdb4f6 --- /dev/null +++ b/abc70930/src/base/io/ioReadPla.c @@ -0,0 +1,250 @@ +/**CFile**************************************************************** + + FileName [ioReadPla.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadPla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a PLA file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t|" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadPlaNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadPla: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pTermPi, * pTermPo, * pNode; + Vec_Str_t ** ppSops; + char Buffer[100]; + int nInputs = -1, nOutputs = -1, nProducts = -1; + char * pCubeIn, * pCubeOut; + int i, k, iLine, nDigits, nCubes; + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + nCubes = 0; + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // if it is the end of file, quit the loop + if ( strcmp( vTokens->pArray[0], ".e" ) == 0 ) + break; + + if ( vTokens->nSize == 1 ) + { + printf( "%s (line %d): Wrong number of token.\n", + Extra_FileReaderGetFileName(p), iLine+1 ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + if ( strcmp( vTokens->pArray[0], ".i" ) == 0 ) + nInputs = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".o" ) == 0 ) + nOutputs = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".p" ) == 0 ) + nProducts = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".ilb" ) == 0 ) + { + if ( vTokens->nSize - 1 != nInputs ) + printf( "Warning: Mismatch between the number of PIs on the .i line (%d) and the number of PIs on the .ilb line (%d).\n", nInputs, vTokens->nSize - 1 ); + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePi( pNtk, vTokens->pArray[i] ); + } + else if ( strcmp( vTokens->pArray[0], ".ob" ) == 0 ) + { + if ( vTokens->nSize - 1 != nOutputs ) + printf( "Warning: Mismatch between the number of POs on the .o line (%d) and the number of POs on the .ob line (%d).\n", nOutputs, vTokens->nSize - 1 ); + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePo( pNtk, vTokens->pArray[i] ); + } + else + { + // check if the input/output names are given + if ( Abc_NtkPiNum(pNtk) == 0 ) + { + if ( nInputs == -1 ) + { + printf( "%s: The number of inputs is not specified.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + nDigits = Extra_Base10Log( nInputs ); + for ( i = 0; i < nInputs; i++ ) + { + sprintf( Buffer, "x%0*d", nDigits, i ); + Io_ReadCreatePi( pNtk, Buffer ); + } + } + if ( Abc_NtkPoNum(pNtk) == 0 ) + { + if ( nOutputs == -1 ) + { + printf( "%s: The number of outputs is not specified.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + nDigits = Extra_Base10Log( nOutputs ); + for ( i = 0; i < nOutputs; i++ ) + { + sprintf( Buffer, "z%0*d", nDigits, i ); + Io_ReadCreatePo( pNtk, Buffer ); + } + } + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { // first time here + // create the PO drivers and add them + // start the SOP covers + ppSops = ALLOC( Vec_Str_t *, nOutputs ); + Abc_NtkForEachPo( pNtk, pTermPo, i ) + { + ppSops[i] = Vec_StrAlloc( 100 ); + // create the node + pNode = Abc_NtkCreateNode(pNtk); + // connect the node to the PO net + Abc_ObjAddFanin( Abc_ObjFanin0Ntk(pTermPo), pNode ); + // connect the node to the PI nets + Abc_NtkForEachPi( pNtk, pTermPi, k ) + Abc_ObjAddFanin( pNode, Abc_ObjFanout0Ntk(pTermPi) ); + } + } + // read the cubes + if ( vTokens->nSize != 2 ) + { + printf( "%s (line %d): Input and output cubes are not specified.\n", + Extra_FileReaderGetFileName(p), iLine+1 ); + Abc_NtkDelete( pNtk ); + return NULL; + } + pCubeIn = vTokens->pArray[0]; + pCubeOut = vTokens->pArray[1]; + if ( strlen(pCubeIn) != (unsigned)nInputs ) + { + printf( "%s (line %d): Input cube length (%d) differs from the number of inputs (%d).\n", + Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeIn), nInputs ); + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( strlen(pCubeOut) != (unsigned)nOutputs ) + { + printf( "%s (line %d): Output cube length (%d) differs from the number of outputs (%d).\n", + Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeOut), nOutputs ); + Abc_NtkDelete( pNtk ); + return NULL; + } + for ( i = 0; i < nOutputs; i++ ) + { + if ( pCubeOut[i] == '1' ) + { + Vec_StrAppend( ppSops[i], pCubeIn ); + Vec_StrAppend( ppSops[i], " 1\n" ); + } + } + nCubes++; + } + } + Extra_ProgressBarStop( pProgress ); + if ( nProducts != -1 && nCubes != nProducts ) + printf( "Warning: Mismatch between the number of cubes (%d) and the number on .p line (%d).\n", + nCubes, nProducts ); + + // add the SOP covers + Abc_NtkForEachPo( pNtk, pTermPo, i ) + { + pNode = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pTermPo) ); + if ( ppSops[i]->nSize == 0 ) + { + Abc_ObjRemoveFanins(pNode); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" ); + Vec_StrFree( ppSops[i] ); + continue; + } + Vec_StrPush( ppSops[i], 0 ); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, ppSops[i]->pArray ); + Vec_StrFree( ppSops[i] ); + } + free( ppSops ); + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadVerilog.c b/abc70930/src/base/io/ioReadVerilog.c new file mode 100644 index 00000000..c64e330c --- /dev/null +++ b/abc70930/src/base/io/ioReadVerilog.c @@ -0,0 +1,90 @@ +/**CFile**************************************************************** + + FileName [ioReadVerilog.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads hierarchical design from the Verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ) +{ + Abc_Ntk_t * pNtk; + Abc_Lib_t * pDesign; + int RetValue; + + // parse the verilog file + pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 ); + if ( pDesign == NULL ) + return NULL; + + // detect top-level model + RetValue = Abc_LibFindTopLevelModels( pDesign ); + pNtk = Vec_PtrEntry( pDesign->vTops, 0 ); + if ( RetValue > 1 ) + printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", + Vec_PtrSize(pDesign->vTops), pNtk->pName ); + + // extract the master network + pNtk->pDesign = pDesign; + pDesign->pManFunc = NULL; + + // verify the design for cyclic dependence + assert( Vec_PtrSize(pDesign->vModules) > 0 ); + if ( Vec_PtrSize(pDesign->vModules) == 1 ) + { +// printf( "Warning: The design is not hierarchical.\n" ); + Abc_LibFree( pDesign, pNtk ); + pNtk->pDesign = NULL; + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + } + else + { + // check that there is no cyclic dependency + Abc_NtkIsAcyclicHierarchy( pNtk ); + } + +//Io_WriteVerilog( pNtk, "_temp.v" ); + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioUtil.c b/abc70930/src/base/io/ioUtil.c new file mode 100644 index 00000000..94ec4316 --- /dev/null +++ b/abc70930/src/base/io/ioUtil.c @@ -0,0 +1,752 @@ +/**CFile**************************************************************** + + FileName [ioUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the file type.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_FileType_t Io_ReadFileType( char * pFileName ) +{ + char * pExt; + if ( pFileName == NULL ) + return IO_FILE_NONE; + pExt = Extra_FileNameExtension( pFileName ); + if ( pExt == NULL ) + return IO_FILE_NONE; + if ( !strcmp( pExt, "aig" ) ) + return IO_FILE_AIGER; + if ( !strcmp( pExt, "baf" ) ) + return IO_FILE_BAF; + if ( !strcmp( pExt, "blif" ) ) + return IO_FILE_BLIF; + if ( !strcmp( pExt, "bench" ) ) + return IO_FILE_BENCH; + if ( !strcmp( pExt, "cnf" ) ) + return IO_FILE_CNF; + if ( !strcmp( pExt, "dot" ) ) + return IO_FILE_DOT; + if ( !strcmp( pExt, "edif" ) ) + return IO_FILE_EDIF; + if ( !strcmp( pExt, "eqn" ) ) + return IO_FILE_EQN; + if ( !strcmp( pExt, "gml" ) ) + return IO_FILE_GML; + if ( !strcmp( pExt, "list" ) ) + return IO_FILE_LIST; + if ( !strcmp( pExt, "mv" ) ) + return IO_FILE_BLIFMV; + if ( !strcmp( pExt, "pla" ) ) + return IO_FILE_PLA; + if ( !strcmp( pExt, "v" ) ) + return IO_FILE_VERILOG; + return IO_FILE_UNKNOWN; +} + +/**Function************************************************************* + + Synopsis [Read the network from a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ) +{ + FILE * pFile; + Abc_Ntk_t * pNtk; + if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) + { + fprintf( stdout, "The generic file reader requires a known file extension.\n" ); + return NULL; + } + // check if the file exists + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( stdout, "Did you mean \"%s\"?", pFileName ); + fprintf( stdout, "\n" ); + return NULL; + } + fclose( pFile ); + // read the AIG + if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) + { + if ( FileType == IO_FILE_AIGER ) + pNtk = Io_ReadAiger( pFileName, fCheck ); + else // if ( FileType == IO_FILE_BAF ) + pNtk = Io_ReadBaf( pFileName, fCheck ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Reading AIG from file has failed.\n" ); + return NULL; + } + return pNtk; + } + // read the new netlist + if ( FileType == IO_FILE_BLIF ) +// pNtk = Io_ReadBlif( pFileName, fCheck ); + pNtk = Io_ReadBlifMv( pFileName, 0, fCheck ); + else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + pNtk = Io_ReadBlifMv( pFileName, 1, fCheck ); + else if ( FileType == IO_FILE_BENCH ) + pNtk = Io_ReadBench( pFileName, fCheck ); + else if ( FileType == IO_FILE_EDIF ) + pNtk = Io_ReadEdif( pFileName, fCheck ); + else if ( FileType == IO_FILE_EQN ) + pNtk = Io_ReadEqn( pFileName, fCheck ); + else if ( FileType == IO_FILE_PLA ) + pNtk = Io_ReadPla( pFileName, fCheck ); + else if ( FileType == IO_FILE_VERILOG ) + pNtk = Io_ReadVerilog( pFileName, fCheck ); + else + { + fprintf( stderr, "Unknown file format.\n" ); + return NULL; + } + if ( pNtk == NULL ) + { + fprintf( stdout, "Reading network from file has failed.\n" ); + return NULL; + } + if ( Abc_NtkBlackboxNum(pNtk) || Abc_NtkWhiteboxNum(pNtk) ) + fprintf( stdout, "Warning: The network contains hierarchy.\n" ); + return pNtk; +} + + +/**Function************************************************************* + + Synopsis [Read the network from a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck ) +{ + Abc_Ntk_t * pNtk, * pTemp; + // get the netlist + pNtk = Io_ReadNetlist( pFileName, FileType, fCheck ); + if ( pNtk == NULL ) + return NULL; + if ( !Abc_NtkIsNetlist(pNtk) ) + return pNtk; + // flatten logic hierarchy + assert( Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkWhiteboxNum(pNtk) > 0 ) + { + pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Flattening logic hierarchy has failed.\n" ); + return NULL; + } + } + // convert blackboxes + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) ); + pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting blackboxes has failed.\n" ); + return NULL; + } + } + // consider the case of BLIF-MV + if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + { +//Abc_NtkPrintStats( stdout, pNtk, 0 ); +// Io_WriteBlifMv( pNtk, "_temp_.mv" ); + pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" ); + return NULL; + } + return pNtk; + } + // convert the netlist into the logic network + pNtk = Abc_NtkToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Write the network into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ) +{ + Abc_Ntk_t * pNtkTemp, * pNtkCopy; + // check if the current network is available + if ( pNtk == NULL ) + { + fprintf( stdout, "Empty network.\n" ); + return; + } + // check if the file extension if given + if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) + { + fprintf( stdout, "The generic file writer requires a known file extension.\n" ); + return; + } + // write the AIG formats + if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) + { + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); + return; + } + if ( FileType == IO_FILE_AIGER ) + Io_WriteAiger( pNtk, pFileName, 1 ); + else // if ( FileType == IO_FILE_BAF ) + Io_WriteBaf( pNtk, pFileName ); + return; + } + // write non-netlist types + if ( FileType == IO_FILE_CNF ) + { + Io_WriteCnf( pNtk, pFileName, 0 ); + return; + } + if ( FileType == IO_FILE_DOT ) + { + Io_WriteDot( pNtk, pFileName ); + return; + } + if ( FileType == IO_FILE_GML ) + { + Io_WriteGml( pNtk, pFileName ); + return; + } +/* + if ( FileType == IO_FILE_BLIFMV ) + { + Io_WriteBlifMv( pNtk, pFileName ); + return; + } +*/ + // convert logic network into netlist + if ( FileType == IO_FILE_PLA ) + { + if ( Abc_NtkLevel(pNtk) > 1 ) + { + fprintf( stdout, "PLA writing is available for collapsed networks.\n" ); + return; + } + if ( Abc_NtkIsComb(pNtk) ) + pNtkTemp = Abc_NtkToNetlist( pNtk ); + else + { + fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" ); + pNtkCopy = Abc_NtkDup( pNtk ); + Abc_NtkMakeComb( pNtkCopy ); + pNtkTemp = Abc_NtkToNetlist( pNtk ); + Abc_NtkDelete( pNtkCopy ); + } + if ( !Abc_NtkToSop( pNtk, 1 ) ) + return; + } + else if ( FileType == IO_FILE_BENCH ) + { + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Writing traditional BENCH is available for AIGs only (use \"write_bench\").\n" ); + return; + } + pNtkTemp = Abc_NtkToNetlistBench( pNtk ); + } + else + pNtkTemp = Abc_NtkToNetlist( pNtk ); + + if ( pNtkTemp == NULL ) + { + fprintf( stdout, "Converting to netlist has failed.\n" ); + return; + } + + if ( FileType == IO_FILE_BLIF ) + { + if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) + Abc_NtkToSop( pNtkTemp, 0 ); + Io_WriteBlif( pNtkTemp, pFileName, 1 ); + } + else if ( FileType == IO_FILE_BLIFMV ) + { + if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) ) + return; + Io_WriteBlifMv( pNtkTemp, pFileName ); + } + else if ( FileType == IO_FILE_BENCH ) + Io_WriteBench( pNtkTemp, pFileName ); + else if ( FileType == IO_FILE_PLA ) + Io_WritePla( pNtkTemp, pFileName ); + else if ( FileType == IO_FILE_EQN ) + { + if ( !Abc_NtkHasAig(pNtkTemp) ) + Abc_NtkToAig( pNtkTemp ); + Io_WriteEqn( pNtkTemp, pFileName ); + } + else if ( FileType == IO_FILE_VERILOG ) + { + if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) + Abc_NtkToAig( pNtkTemp ); + Io_WriteVerilog( pNtkTemp, pFileName ); + } + else + fprintf( stderr, "Unknown file format.\n" ); + Abc_NtkDelete( pNtkTemp ); +} + +/**Function************************************************************* + + Synopsis [Write the network into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ) +{ + Abc_Ntk_t * pNtkTemp, * pNtkResult, * pNtkBase = NULL; + // check if the current network is available + if ( pNtk == NULL ) + { + fprintf( stdout, "Empty network.\n" ); + return; + } + + // read the base network + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF ) + pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 ); + else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) + pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 ); + else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG ) + pNtkBase = Io_ReadVerilog( pBaseName, 1 ); + else + fprintf( stderr, "Unknown input file format.\n" ); + if ( pNtkBase == NULL ) + return; + + // flatten logic hierarchy if present + if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 ) + { + pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase ); + if ( pNtkBase == NULL ) + return; + Abc_NtkDelete( pNtkTemp ); + } + + // reintroduce the boxes into the netlist + if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) + { + if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) + { + printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" ); + Abc_NtkDelete( pNtkBase ); + return; + } + // convert the current network to BLIF-MV + assert( !Abc_NtkIsNetlist(pNtk) ); + pNtkResult = Abc_NtkToNetlist( pNtk ); + if ( !Abc_NtkConvertToBlifMv( pNtkResult ) ) + return; + // reintroduce the network + pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult ); + Abc_NtkDelete( pNtkTemp ); + } + else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) + { + // derive the netlist + pNtkResult = Abc_NtkToNetlist( pNtk ); + pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult ); + Abc_NtkDelete( pNtkTemp ); + if ( pNtkResult ) + printf( "Hierarchy writer reintroduced %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtkBase) ); + } + else + { + printf( "Warning: The output network does not contain blackboxes.\n" ); + pNtkResult = Abc_NtkToNetlist( pNtk ); + } + Abc_NtkDelete( pNtkBase ); + if ( pNtkResult == NULL ) + return; + + // write the resulting network + if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF ) + { + if ( !Abc_NtkHasSop(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) + Abc_NtkToSop( pNtkResult, 0 ); + Io_WriteBlif( pNtkResult, pFileName, 1 ); + } + else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG ) + { + if ( !Abc_NtkHasAig(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) + Abc_NtkToAig( pNtkResult ); + Io_WriteVerilog( pNtkResult, pFileName ); + } + else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + { + Io_WriteBlifMv( pNtkResult, pFileName ); + } + else + fprintf( stderr, "Unknown output file format.\n" ); + + Abc_NtkDelete( pNtkResult ); +} + +/**Function************************************************************* + + Synopsis [Creates PI terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PI net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet ) + printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PI node + pTerm = Abc_NtkCreatePi( pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) + printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) + printf( "Warning: Assert \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreateAssert( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create a latch with the given input/output.] + + Description [By default, the latch value is unknown (ABC_INIT_NONE).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) +{ + Abc_Obj_t * pLatch, * pTerm, * pNet; + // get the LI net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI ); + // add the BO terminal + pTerm = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + // add the latch box + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_ObjAddFanin( pLatch, pTerm ); + // add the BI terminal + pTerm = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTerm, pLatch ); + // get the LO net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); + Abc_ObjAddFanin( pNet, pTerm ); + // set latch name + Abc_ObjAssignName( pLatch, pNetLO, "L" ); + return pLatch; +} + +/**Function************************************************************* + + Synopsis [Create the reset latch with data=1 and init=0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ) +{ + Abc_Obj_t * pLatch, * pNode; + Abc_Obj_t * pNetLI, * pNetLO; + // create latch with 0 init value +// pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" ); + pNetLI = Abc_NtkCreateNet( pNtk ); + pNetLO = Abc_NtkCreateNet( pNtk ); + Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL ); + Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL ); + pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) ); + // set the initial value + Abc_LatchSetInit0( pLatch ); + // feed the latch with constant1- node +// pNode = Abc_NtkCreateNode( pNtk ); +// pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" ); + pNode = Abc_NtkCreateNodeConst1( pNtk ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode ); + return pLatch; +} + +/**Function************************************************************* + + Synopsis [Create node and the net driven by it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ) +{ + Abc_Obj_t * pNet, * pNode; + int i; + // create a new node + pNode = Abc_NtkCreateNode( pNtk ); + // add the fanin nets + for ( i = 0; i < nInputs; i++ ) + { + pNet = Abc_NtkFindOrCreateNet( pNtk, pNamesIn[i] ); + Abc_ObjAddFanin( pNode, pNet ); + } + // add the fanout net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNameOut ); + Abc_ObjAddFanin( pNet, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Create a constant 0 node driving the net with this name.] + + Description [Assumes that the net already exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 ) +{ + Abc_Obj_t * pNet, * pTerm; + pTerm = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); + pNet = Abc_NtkFindNet(pNtk, pName); assert( pNet ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create an inverter or buffer for the given net.] + + Description [Assumes that the nets already exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) +{ + Abc_Obj_t * pNet, * pNode; + pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); + pNode = Abc_NtkCreateNodeInv(pNtk, pNet); + pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); + Abc_ObjAddFanin( pNet, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Create an inverter or buffer for the given net.] + + Description [Assumes that the nets already exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) +{ + Abc_Obj_t * pNet, * pNode; + pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); + pNode = Abc_NtkCreateNodeBuf(pNtk, pNet); + pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); + Abc_ObjAddFanin( pNet, pNode ); + return pNet; +} + + +/**Function************************************************************* + + Synopsis [Provide an fopen replacement with path lookup] + + Description [Provide an fopen replacement where the path stored + in pathvar MVSIS variable is used to look up the path + for name. Returns NULL if file cannot be opened.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ) +{ + char * t = 0, * c = 0, * i; + extern char * Abc_FrameReadFlag( char * pFlag ); + + if ( PathVar == 0 ) + { + return fopen( FileName, Mode ); + } + else + { + if ( c = Abc_FrameReadFlag( (char*)PathVar ) ) + { + char ActualFileName[4096]; + FILE * fp = 0; + t = Extra_UtilStrsav( c ); + for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") ) + { +#ifdef WIN32 + _snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); +#else + snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); +#endif + if ( ( fp = fopen ( ActualFileName, Mode ) ) ) + { + if ( fVerbose ) + fprintf ( stdout, "Using file %s\n", ActualFileName ); + free( t ); + return fp; + } + } + free( t ); + return 0; + } + else + { + return fopen( FileName, Mode ); + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteAiger.c b/abc70930/src/base/io/ioWriteAiger.c new file mode 100644 index 00000000..ff34b177 --- /dev/null +++ b/abc70930/src/base/io/ioWriteAiger.c @@ -0,0 +1,291 @@ +/**CFile**************************************************************** + + FileName [ioWriteAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + The following is taken from the AIGER format description, + which can be found at http://fmv.jku.at/aiger +*/ + + +/* + The AIGER And-Inverter Graph (AIG) Format Version 20061129 + ---------------------------------------------------------- + Armin Biere, Johannes Kepler University, 2006 + + This report describes the AIG file format as used by the AIGER library. + The purpose of this report is not only to motivate and document the + format, but also to allow independent implementations of writers and + readers by giving precise and unambiguous definitions. + + ... + +Introduction + + The name AIGER contains as one part the acronym AIG of And-Inverter + Graphs and also if pronounced in German sounds like the name of the + 'Eiger', a mountain in the Swiss alps. This choice should emphasize the + origin of this format. It was first openly discussed at the Alpine + Verification Meeting 2006 in Ascona as a way to provide a simple, compact + file format for a model checking competition affiliated to CAV 2007. + + ... + +Binary Format Definition + + The binary format is semantically a subset of the ASCII format with a + slightly different syntax. The binary format may need to reencode + literals, but translating a file in binary format into ASCII format and + then back in to binary format will result in the same file. + + The main differences of the binary format to the ASCII format are as + follows. After the header the list of input literals and all the + current state literals of a latch can be omitted. Furthermore the + definitions of the AND gates are binary encoded. However, the symbol + table and the comment section are as in the ASCII format. + + The header of an AIGER file in binary format has 'aig' as format + identifier, but otherwise is identical to the ASCII header. The standard + file extension for the binary format is therefore '.aig'. + + A header for the binary format is still in ASCII encoding: + + aig M I L O A + + Constants, variables and literals are handled in the same way as in the + ASCII format. The first simplifying restriction is on the variable + indices of inputs and latches. The variable indices of inputs come first, + followed by the pseudo-primary inputs of the latches and then the variable + indices of all LHS of AND gates: + + input variable indices 1, 2, ... , I + latch variable indices I+1, I+2, ... , (I+L) + AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M + + The corresponding unsigned literals are + + input literals 2, 4, ... , 2*I + latch literals 2*I+2, 2*I+4, ... , 2*(I+L) + AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M + + All literals have to be defined, and therefore 'M = I + L + A'. With this + restriction it becomes possible that the inputs and the current state + literals of the latches do not have to be listed explicitly. Therefore, + after the header only the list of 'L' next state literals follows, one per + latch on a single line, and then the 'O' outputs, again one per line. + + In the binary format we assume that the AND gates are ordered and respect + the child parent relation. AND gates with smaller literals on the LHS + come first. Therefore we can assume that the literals on the right-hand + side of a definition of an AND gate are smaller than the LHS literal. + Furthermore we can sort the literals on the RHS, such that the larger + literal comes first. A definition thus consists of three literals + + lhs rhs0 rhs1 + + with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are + pairwise different to avoid combinational self loops. Since the LHS + indices of the definitions are all consecutive (as even integers), + the binary format does not have to keep 'lhs'. In addition, we can use + the order restriction and only write the differences 'delta0' and 'delta1' + instead of 'rhs0' and 'rhs1', with + + delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 + + The differences will all be strictly positive, and in practice often very + small. We can take advantage of this fact by the simple little-endian + encoding of unsigned integers of the next section. After the binary delta + encoding of the RHSs of all AND gates, the optional symbol table and + optional comment section start in the same format as in the ASCII case. + + ... + +*/ + +static unsigned Io_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } +static unsigned Io_ObjAigerNum( Abc_Obj_t * pObj ) { return (unsigned)pObj->pCopy; } +static void Io_ObjSetAigerNum( Abc_Obj_t * pObj, unsigned Num ) { pObj->pCopy = (void *)Num; } + +int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ) +{ + ProgressBar * pProgress; + FILE * pFile; + Abc_Obj_t * pObj, * pDriver; + int i, nNodes, Pos, nBufferSize; + unsigned char * pBuffer; + unsigned uLit0, uLit1, uLit; + + assert( Abc_NtkIsStrash(pNtk) ); + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( !Abc_LatchIsInit0(pObj) ) + { + fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); + return; + } + + // set the node numbers to be used in the output file + nNodes = 0; + Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Io_ObjSetAigerNum( pObj, nNodes++ ); + Abc_AigForEachAnd( pNtk, pObj, i ) + Io_ObjSetAigerNum( pObj, nNodes++ ); + + // write the header "M I L O A" where M = I + L + A + fprintf( pFile, "aig %u %u %u %u %u\n", + Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), + Abc_NtkPiNum(pNtk), + Abc_NtkLatchNum(pNtk), + Abc_NtkPoNum(pNtk), + Abc_NtkNodeNum(pNtk) ); + + // if the driver node is a constant, we need to complement the literal below + // because, in the AIGER format, literal 0/1 is represented as number 0/1 + // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 + + // write latch drivers + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); + } + + // write PO drivers + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); + } + + // write the nodes into the buffer + Pos = 0; + nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge + pBuffer = ALLOC( char, nBufferSize ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + uLit = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 ); + uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) ); + uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) ); + assert( uLit0 < uLit1 ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); + if ( Pos > nBufferSize - 10 ) + { + printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); + fclose( pFile ); + return; + } + } + assert( Pos < nBufferSize ); + Extra_ProgressBarStop( pProgress ); + + // write the buffer + fwrite( pBuffer, 1, Pos, pFile ); + free( pBuffer ); + + // write the symbol table + if ( fWriteSymbols ) + { + // write PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) ); + // write latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + fprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) ); + // write POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) ); + } + + // write the comment + fprintf( pFile, "c\n" ); + if ( pNtk->pName && strlen(pNtk->pName) > 0 ) + fprintf( pFile, ".model %s\n", pNtk->pName ); + fprintf( pFile, "This file was produced by ABC on %s\n", Extra_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Adds one unsigned AIG edge to the output buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "void encode (FILE * file, unsigned x)" ] + + SideEffects [Returns the current writing position.] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; +// putc (ch, file); + pBuffer[Pos++] = ch; + x >>= 7; + } + ch = x; +// putc (ch, file); + pBuffer[Pos++] = ch; + return Pos; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBaf.c b/abc70930/src/base/io/ioWriteBaf.c new file mode 100644 index 00000000..fc0229a4 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBaf.c @@ -0,0 +1,168 @@ +/**CFile**************************************************************** + + FileName [ioWriteBaf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write AIG in the binary format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + Binary Aig Format + + The motivation for this format is to have + - compact binary representation of large AIGs (~10x more compact than BLIF) + - consequently, fast reading/writing of large AIGs (~10x faster than BLIF) + - representation for all tech-ind info related to an AIG + - human-readable file header + + The header: + (1) May contain several lines of human-readable comments. + Each comment line begins with symbol '#' and ends with symbol '\n'. + (2) Always contains the following data. + - benchmark name + - number of primary inputs + - number of primary outputs + - number of latches + - number of AIG nodes (excluding the constant 1 node) + Each entry is followed by 0-byte (character '\0'): + (3) Next follow the names of the PIs, POs, and latches in this order. + Each name is followed by 0-byte (character '\0'). + Inside each set of names (PIs, POs, latches) there should be no + identical names but the PO names may coincide with PI/latch names. + + The body: + (1) First part of the body contains binary information about the internal AIG nodes. + Each internal AIG node is represented using two edges (each edge is a 4-byte integer). + Each integer is the fanin ID followed by 1-bit representation of the complemented attribute. + (For example, complemented edge to node 10 will be represented as 2*10 + 1 = 21.) + The IDs of the nodes are created as follows: Constant 1 node has ID=0. + CIs (PIs and latch outputs) have 1-based IDs assigned in that order. + Each node in the array of the internal AIG nodes has the ID assigned in that order. + The constant 1 node is not written into the file. + (2) Second part of the body contains binary information about the edges connecting + the COs (POs and latch inputs) to the internal AIG nodes. + Each edge is a 4-byte integer the same way as a node fanin. + The latch initial value (2 bits) is stored in this integer. +*/ + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ) +{ + ProgressBar * pProgress; + FILE * pFile; + Abc_Obj_t * pObj; + int i, nNodes, nAnds, nBufferSize; + unsigned * pBufferNode; + assert( Abc_NtkIsStrash(pNtk) ); + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBaf(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // write the comment + fprintf( pFile, "# BAF (Binary Aig Format) for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // write the network name + fprintf( pFile, "%s%c", pNtk->pName, 0 ); + // write the number of PIs + fprintf( pFile, "%d%c", Abc_NtkPiNum(pNtk), 0 ); + // write the number of POs + fprintf( pFile, "%d%c", Abc_NtkPoNum(pNtk), 0 ); + // write the number of latches + fprintf( pFile, "%d%c", Abc_NtkLatchNum(pNtk), 0 ); + // write the number of internal nodes + fprintf( pFile, "%d%c", Abc_NtkNodeNum(pNtk), 0 ); + + // write PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + // write POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + // write latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanin0(pObj)), 0 ); + fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanout0(pObj)), 0 ); + } + + // set the node numbers to be used in the output file + Abc_NtkCleanCopy( pNtk ); + nNodes = 1; + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (void *)nNodes++; + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->pCopy = (void *)nNodes++; + + // write the nodes into the buffer + nAnds = 0; + nBufferSize = Abc_NtkNodeNum(pNtk) * 2 + Abc_NtkCoNum(pNtk); + pBufferNode = ALLOC( int, nBufferSize ); + pProgress = Extra_ProgressBarStart( stdout, nBufferSize ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); + pBufferNode[nAnds++] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); + pBufferNode[nAnds++] = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj); + } + + // write the COs into the buffer + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); + pBufferNode[nAnds] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); + if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + pBufferNode[nAnds] = (pBufferNode[nAnds] << 2) | ((unsigned)Abc_ObjData(Abc_ObjFanout0(pObj)) & 3); + nAnds++; + } + Extra_ProgressBarStop( pProgress ); + assert( nBufferSize == nAnds ); + + // write the buffer + fwrite( pBufferNode, 1, sizeof(int) * nBufferSize, pFile ); + fclose( pFile ); + free( pBufferNode ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBench.c b/abc70930/src/base/io/ioWriteBench.c new file mode 100644 index 00000000..4b766a47 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBench.c @@ -0,0 +1,335 @@ +/**CFile**************************************************************** + + FileName [ioWriteBench.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ); + +static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ); + +static int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBench( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + assert( Abc_NtkIsSopNetlist(pNtk) ); + if ( !Io_WriteBenchCheckNames(pNtk) ) + { + fprintf( stdout, "Io_WriteBench(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); + return 0; + } + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WriteBenchOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WriteBench: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode; + int i; + + // write the PIs/POs/latches + Abc_NtkForEachPi( pNtk, pNode, i ) + fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Abc_NtkForEachPo( pNtk, pNode, i ) + fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + fprintf( pFile, "%-11s = DFF(%s)\n", + Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); + + // write internal nodes + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_WriteBenchOneNode( pFile, pNode ); + } + Extra_ProgressBarStop( pProgress ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ) +{ + int nFanins; + + assert( Abc_ObjIsNode(pNode) ); + nFanins = Abc_ObjFaninNum(pNode); + if ( nFanins == 0 ) + { // write the constant 1 node + assert( Abc_NodeIsConst1(pNode) ); + fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, " = vdd\n" ); + } + else if ( nFanins == 1 ) + { // write the interver/buffer + if ( Abc_NodeIsBuf(pNode) ) + { + fprintf( pFile, "%-11s = BUFF(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + } + else + { + fprintf( pFile, "%-11s = NOT(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + } + } + else + { // write the AND gate + fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, " = AND(%s, ", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin1(pNode)) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format with LUTs and DFFRSE.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + assert( Abc_NtkIsAigNetlist(pNtk) ); + if ( !Io_WriteBenchCheckNames(pNtk) ) + { + fprintf( stdout, "Io_WriteBenchLut(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); + return 0; + } + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WriteBenchLutOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WriteBench: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode; + Vec_Int_t * vMemory; + int i; + + // write the PIs/POs/latches + Abc_NtkForEachPi( pNtk, pNode, i ) + fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Abc_NtkForEachPo( pNtk, pNode, i ) + fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + fprintf( pFile, "%-11s = DFFRSE( %s, gnd, gnd, gnd, gnd )\n", + Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); +//Abc_NtkLevel(pNtk); + // write internal nodes + vMemory = Vec_IntAlloc( 10000 ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_WriteBenchLutOneNode( pFile, pNode, vMemory ); + } + Extra_ProgressBarStop( pProgress ); + Vec_IntFree( vMemory ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ) +{ + Abc_Obj_t * pFanin; + unsigned * pTruth; + int i, nFanins; + assert( Abc_ObjIsNode(pNode) ); + nFanins = Abc_ObjFaninNum(pNode); + assert( nFanins <= 8 ); + // compute the truth table + pTruth = Abc_ConvertAigToTruth( pNode->pNtk->pManFunc, Hop_Regular(pNode->pData), nFanins, vTruth, 0 ); + if ( Hop_IsComplement(pNode->pData) ) + Extra_TruthNot( pTruth, pTruth, nFanins ); + // consider simple cases + if ( Extra_TruthIsConst0(pTruth, nFanins) ) + { + fprintf( pFile, "%-11s = gnd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return 1; + } + if ( Extra_TruthIsConst1(pTruth, nFanins) ) + { + fprintf( pFile, "%-11s = vdd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return 1; + } + if ( nFanins == 1 ) + { + fprintf( pFile, "%-11s = LUT 0x%d ( %s )\n", + Abc_ObjName(Abc_ObjFanout0(pNode)), + Abc_NodeIsBuf(pNode)? 2 : 1, + Abc_ObjName(Abc_ObjFanin0(pNode)) ); + return 1; + } + // write it in the hexadecimal form + fprintf( pFile, "%-11s = LUT 0x", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Extra_PrintHexadecimal( pFile, pTruth, nFanins ); +/* + { +extern void Kit_DsdTest( unsigned * pTruth, int nVars ); +Abc_ObjForEachFanin( pNode, pFanin, i ) +printf( "%c%d ", 'a'+i, Abc_ObjFanin0(pFanin)->Level ); +printf( "\n" ); +Kit_DsdTest( pTruth, nFanins ); + } + if ( pNode->Id % 1000 == 0 ) + { + int x = 0; + } +*/ + // write the fanins + fprintf( pFile, " (" ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + fprintf( pFile, " %s%s", Abc_ObjName(pFanin), ((i==nFanins-1)? "" : ",") ); + fprintf( pFile, " )\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the names cannot be written into the bench file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + char * pName; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ ) + if ( *pName == '(' || *pName == ')' ) + return 0; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBlif.c b/abc70930/src/base/io/ioWriteBlif.c new file mode 100644 index 00000000..c0c29d65 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBlif.c @@ -0,0 +1,591 @@ +/**CFile**************************************************************** + + FileName [ioWriteBlif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write BLIF files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ); +static void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ); +static void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) +{ + Abc_Ntk_t * pNtkTemp; + // derive the netlist + pNtkTemp = Abc_NtkToNetlist(pNtk); + if ( pNtkTemp == NULL ) + { + fprintf( stdout, "Writing BLIF has failed.\n" ); + return; + } + Io_WriteBlif( pNtkTemp, FileName, fWriteLatches ); + Abc_NtkDelete( pNtkTemp ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) +{ + FILE * pFile; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + // start writing the file + pFile = fopen( FileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBlif(): Cannot open the output file.\n" ); + return; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the master network + Io_NtkWrite( pFile, pNtk, fWriteLatches ); + // make sure there is no logic hierarchy + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + // write the hierarchy if present + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) + { + if ( pNtkTemp == pNtk ) + continue; + fprintf( pFile, "\n\n" ); + Io_NtkWrite( pFile, pNtkTemp, fWriteLatches ); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Ntk_t * pExdc; + assert( Abc_NtkIsNetlist(pNtk) ); + // write the model name + fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); + // write the network + Io_NtkWriteOne( pFile, pNtk, fWriteLatches ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + { + fprintf( pFile, "\n" ); + fprintf( pFile, ".exdc\n" ); + Io_NtkWriteOne( pFile, pExdc, fWriteLatches ); + } + // finalize the file + fprintf( pFile, ".end\n" ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pLatch; + int i, Length; + + // write the PIs + fprintf( pFile, ".inputs" ); + Io_NtkWritePis( pFile, pNtk, fWriteLatches ); + fprintf( pFile, "\n" ); + + // write the POs + fprintf( pFile, ".outputs" ); + Io_NtkWritePos( pFile, pNtk, fWriteLatches ); + fprintf( pFile, "\n" ); + + // write the assertions + if ( Abc_NtkAssertNum(pNtk) ) + { + fprintf( pFile, ".asserts" ); + Io_NtkWriteAsserts( pFile, pNtk ); + fprintf( pFile, "\n" ); + } + + // write the blackbox + if ( Abc_NtkHasBlackbox( pNtk ) ) + { + fprintf( pFile, ".blackbox\n" ); + return; + } + + // write the timing info + Io_WriteTimingInfo( pFile, pNtk ); + + // write the latches + if ( fWriteLatches && !Abc_NtkIsComb(pNtk) ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Io_NtkWriteLatch( pFile, pLatch ); + fprintf( pFile, "\n" ); + } + + // write the subcircuits + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBlackbox( pNtk, pNode, i ) + Io_NtkWriteSubckt( pFile, pNode ); + fprintf( pFile, "\n" ); + } + + // write each internal node + Length = Abc_NtkHasMapping(pNtk)? Mio_LibraryReadGateNameMax(pNtk->pManFunc) : 0; + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_NtkWriteNode( pFile, pNode, Length ); + } + Extra_ProgressBarStop( pProgress ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 7; + NameCounter = 0; + + if ( fWriteLatches ) + { + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } + else + { + Abc_NtkForEachCi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + if ( fWriteLatches ) + { + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } + else + { + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + if ( Abc_ObjIsAssert(pTerm) ) + continue; + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } +} + +/**Function************************************************************* + + Synopsis [Writes the assertion list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachAssert( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pModel = pNode->pData; + Abc_Obj_t * pTerm; + int i; + // write the subcircuit +// fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); + fprintf( pFile, ".subckt %s", Abc_NtkName(pModel) ); + // write pairs of the formal=actual names + Abc_NtkForEachPi( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + pTerm = Abc_ObjFanin( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + pTerm = Abc_ObjFanout( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + } + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pNetLi, * pNetLo; + int Reset; + pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); + pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); + Reset = (int)Abc_ObjData( pLatch ); + // write the latch line + fprintf( pFile, ".latch" ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); + fprintf( pFile, " %d\n", Reset-1 ); +} + + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ) +{ + if ( Abc_NtkHasMapping(pNode->pNtk) ) + { + // write the .gate line + fprintf( pFile, ".gate" ); + Io_NtkWriteNodeGate( pFile, pNode, Length ); + fprintf( pFile, "\n" ); + } + else + { + // write the .names line + fprintf( pFile, ".names" ); + Io_NtkWriteNodeFanins( pFile, pNode ); + fprintf( pFile, "\n" ); + // write the cubes + fprintf( pFile, "%s", Abc_ObjData(pNode) ); + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) +{ + Mio_Gate_t * pGate = pNode->pData; + Mio_Pin_t * pGatePin; + int i; + // write the node + fprintf( pFile, " %-*s ", Length, Mio_GateReadName(pGate) ); + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + fprintf( pFile, "%s=%s ", Mio_PinReadName(pGatePin), Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); + assert ( i == Abc_ObjFaninNum(pNode) ); + fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName( Abc_ObjFanout0(pNode) ) ); +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + Abc_ObjForEachFanin( pNode, pNet, i ) + { + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); + LineLength += AddedLength; + NameCounter++; + } + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); +} + +/**Function************************************************************* + + Synopsis [Writes the timing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Abc_Time_t * pTime, * pTimeDef; + int i; + + if ( pNtk->pManTime == NULL ) + return; + + pTimeDef = Abc_NtkReadDefaultArrival( pNtk ); + fprintf( pFile, ".default_input_arrival %g %g\n", pTimeDef->Rise, pTimeDef->Fall ); + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pTime = Abc_NodeReadArrival(pNode); + if ( pTime->Rise == pTimeDef->Rise && pTime->Fall == pTimeDef->Fall ) + continue; + fprintf( pFile, ".input_arrival %s %g %g\n", Abc_ObjName(pNode), pTime->Rise, pTime->Fall ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBlifMv.c b/abc70930/src/base/io/ioWriteBlifMv.c new file mode 100644 index 00000000..775a2e07 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBlifMv.c @@ -0,0 +1,519 @@ +/**CFile**************************************************************** + + FileName [ioWriteBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write BLIF-MV files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ); +static void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ) +{ + FILE * pFile; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + // start writing the file + pFile = fopen( FileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" ); + return; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the master network + Io_NtkWriteBlifMv( pFile, pNtk ); + // write the remaining networks + if ( pNtk->pDesign ) + { + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) + { + if ( pNtkTemp == pNtk ) + continue; + fprintf( pFile, "\n\n" ); + Io_NtkWriteBlifMv( pFile, pNtkTemp ); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + assert( Abc_NtkIsNetlist(pNtk) ); + // write the model name + fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); + // write the network + Io_NtkWriteBlifMvOne( pFile, pNtk ); + // write EXDC network if it exists + if ( Abc_NtkExdc(pNtk) ) + printf( "Io_NtkWriteBlifMv(): EXDC is not written.\n" ); + // finalize the file + fprintf( pFile, ".end\n\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pTerm, * pLatch; + int i; + + // write the PIs + fprintf( pFile, ".inputs" ); + Io_NtkWriteBlifMvPis( pFile, pNtk ); + fprintf( pFile, "\n" ); + + // write the POs + fprintf( pFile, ".outputs" ); + Io_NtkWriteBlifMvPos( pFile, pNtk ); + fprintf( pFile, "\n" ); + + // write the assertions + if ( Abc_NtkAssertNum(pNtk) ) + { + fprintf( pFile, ".asserts" ); + Io_NtkWriteBlifMvAsserts( pFile, pNtk ); + fprintf( pFile, "\n" ); + } + + // write the MV directives + fprintf( pFile, "\n" ); + Abc_NtkForEachCi( pNtk, pTerm, i ) + if ( Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + if ( Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanin0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) ); + + // write the blackbox + if ( Abc_NtkHasBlackbox( pNtk ) ) + { + fprintf( pFile, ".blackbox\n" ); + return; + } + + // write the timing info +// Io_WriteTimingInfo( pFile, pNtk ); + + // write the latches + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Io_NtkWriteBlifMvLatch( pFile, pLatch ); + fprintf( pFile, "\n" ); + } +/* + // write the subcircuits + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBlackbox( pNtk, pNode, i ) + Io_NtkWriteBlifMvSubckt( pFile, pNode ); + fprintf( pFile, "\n" ); + } +*/ + if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBox( pNtk, pNode, i ) + { + if ( Abc_ObjIsLatch(pNode) ) + continue; + Io_NtkWriteBlifMvSubckt( pFile, pNode ); + } + fprintf( pFile, "\n" ); + } + + // write each internal node + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_NtkWriteBlifMvNode( pFile, pNode ); + } + Extra_ProgressBarStop( pProgress ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 7; + NameCounter = 0; + + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the assertion list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachAssert( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pNetLi, * pNetLo; + int Reset; + pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); + pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); + Reset = (int)Abc_ObjData( pLatch ); + // write the latch line + fprintf( pFile, ".latch" ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); + fprintf( pFile, "\n" ); + // write the reset node + fprintf( pFile, ".reset %s\n", Abc_ObjName(pNetLo) ); + fprintf( pFile, "%d\n", Reset-1 ); +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pModel = pNode->pData; + Abc_Obj_t * pTerm; + int i; + // write the MV directives + fprintf( pFile, "\n" ); + Abc_ObjForEachFanin( pNode, pTerm, i ) + if ( Abc_ObjMvVarNum(pTerm) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); + Abc_ObjForEachFanout( pNode, pTerm, i ) + if ( Abc_ObjMvVarNum(pTerm) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); + // write the subcircuit + fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); + // write pairs of the formal=actual names + Abc_NtkForEachPi( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + pTerm = Abc_ObjFanin( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + pTerm = Abc_ObjFanout( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + } + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + char * pCur; + int nValues, iFanin, i; + + // write .mv directives for the fanins + fprintf( pFile, "\n" ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { +// nValues = atoi(pCur); + nValues = Abc_ObjMvVarNum( pFanin ); + if ( nValues > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues ); +// while ( *pCur++ != ' ' ); + } + + // write .mv directives for the node +// nValues = atoi(pCur); + nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) ); + if ( nValues > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues ); +// while ( *pCur++ != '\n' ); + + // write the .names line + fprintf( pFile, ".table" ); + Io_NtkWriteBlifMvNodeFanins( pFile, pNode ); + fprintf( pFile, "\n" ); + + // write the cubes + pCur = Abc_ObjData(pNode); + if ( *pCur == 'd' ) + { + fprintf( pFile, ".default " ); + pCur++; + } + // write the literals + for ( ; *pCur; pCur++ ) + { + fprintf( pFile, "%c", *pCur ); + if ( *pCur != '=' ) + continue; + // get the number + iFanin = atoi( pCur+1 ); + fprintf( pFile, "%s", Abc_ObjName(Abc_ObjFanin(pNode,iFanin)) ); + // scroll on to the next symbol + while ( *pCur != ' ' && *pCur != '\n' ) + pCur++; + pCur--; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + Abc_ObjForEachFanin( pNode, pNet, i ) + { + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); + LineLength += AddedLength; + NameCounter++; + } + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteCnf.c b/abc70930/src/base/io/ioWriteCnf.c new file mode 100644 index 00000000..e1b2d956 --- /dev/null +++ b/abc70930/src/base/io/ioWriteCnf.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [ioWriteCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to output CNF of the miter cone.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "satSolver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * s_pNtk = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the miter cone into a CNF file for the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName, int fAllPrimes ) +{ + sat_solver * pSat; + if ( Abc_NtkIsStrash(pNtk) ) + printf( "Io_WriteCnf() warning: Generating CNF by applying heuristic AIG to CNF conversion.\n" ); + else + printf( "Io_WriteCnf() warning: Generating CNF by convering logic nodes into CNF clauses.\n" ); + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" ); + return 0; + } + if ( Abc_NtkLatchNum(pNtk) != 0 ) + { + fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { + fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" ); + return 0; + } + // convert to logic BDD network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToBdd( pNtk ); + // create solver with clauses + pSat = Abc_NtkMiterSatCreate( pNtk, fAllPrimes ); + if ( pSat == NULL ) + { + fprintf( stdout, "The problem is trivially UNSAT. No CNF file is generated.\n" ); + return 1; + } + // write the clauses + s_pNtk = pNtk; + Sat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 ); + s_pNtk = NULL; + // free the solver + sat_solver_delete( pSat ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Output the mapping of PIs into variable numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars ) +{ + extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); + Abc_Ntk_t * pNtk = s_pNtk; + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); + fprintf( pFile, "c PI variable numbers: <PI_name> <SAT_var_number>\n" ); + Abc_NtkForEachCi( pNtk, pObj, i ) + fprintf( pFile, "c %s %d\n", Abc_ObjName(pObj), Vec_IntEntry(vCiIds, i) + (int)(incrementVars > 0) ); + Vec_IntFree( vCiIds ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteDot.c b/abc70930/src/base/io/ioWriteDot.c new file mode 100644 index 00000000..8ae3cc42 --- /dev/null +++ b/abc70930/src/base/io/ioWriteDot.c @@ -0,0 +1,809 @@ +/**CFile**************************************************************** + + FileName [ioWriteDot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of AIG in DOT.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteDot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static char * Abc_NtkPrintSop( char * pSop ); +static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ) +{ + Vec_Ptr_t * vNodes; + vNodes = Abc_NtkCollectObjects( pNtk ); + Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0 ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) +{ + FILE * pFile; + Abc_Obj_t * pNode, * pFanin; + char * pSopString; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; + int Limit = 300; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + if ( vNodes->nSize < 1 ) + { + printf( "The set has no nodes. DOT file is not written.\n" ); + return; + } + + if ( vNodes->nSize > Limit ) + { + printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); + return; + } + + // start the stream + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); + return; + } + } + + // mark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 1; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 1; + + // get the levels of nodes + LevelMax = Abc_NtkLevel( pNtk ); + if ( fUseReverse ) + { + LevelMin = Abc_NtkLevelReverse( pNtk ); + assert( LevelMax == LevelMin ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_ObjIsNode(pNode) ) + pNode->Level = LevelMax - pNode->Level + 1; + } + + // find the largest and the smallest levels + LevelMin = 10000; + LevelMax = -1; + fHasCos = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + { + fHasCos = 1; + continue; + } + if ( LevelMin > (int)pNode->Level ) + LevelMin = pNode->Level; + if ( LevelMax < (int)pNode->Level ) + LevelMax = pNode->Level; + } + + // set the level of the CO nodes + if ( fHasCos ) + { + LevelMax++; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + pNode->Level = LevelMax; + } + } + + // write the DOT header + fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph network {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "size = \"10,8.5\";\n" ); +// fprintf( pFile, "size = \"14,11\";\n" ); +// fprintf( pFile, "page = \"8,11\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != LevelMin ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "Network structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) + fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); + else + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the POs + if ( fHasCos ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCo(pNode) ) + continue; + fprintf( pFile, " Node%d [label = \"%s%s\"", + pNode->Id, + (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), + (Abc_ObjIsBi(pNode)? "_in":"") ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate nodes of each rank + for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; +// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + if ( Abc_NtkIsStrash(pNtk) ) + pSopString = ""; + else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) + pSopString = Mio_GateReadName(pNode->pData); + else if ( Abc_NtkHasMapping(pNtk) ) + pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); + else + pSopString = Abc_NtkPrintSop(pNode->pData); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the PI nodes if any + if ( LevelMin == 0 ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMin ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCi(pNode) ) + { + // check if the costant node is present + if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) + { + fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) ); + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + continue; + } + fprintf( pFile, " Node%d [label = \"%s\"", + pNode->Id, + (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != LevelMax ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + } + + // generate edges + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsLatch(pNode) ) + continue; + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + if ( Abc_ObjIsLatch(pFanin) ) + continue; + fCompl = 0; + if ( Abc_NtkIsStrash(pNtk) ) + fCompl = Abc_ObjFaninC(pNode, k); + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pFanin->Id ); + fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); +// fprintf( pFile, ", label = \"%c\"", 'a' + k ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 0; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 0; + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); +} + + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) +{ + FILE * pFile; + Abc_Obj_t * pNode, * pFanin; + char * pSopString; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; + int Limit = 300; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + if ( vNodes->nSize < 1 ) + { + printf( "The set has no nodes. DOT file is not written.\n" ); + return; + } + + if ( vNodes->nSize > Limit ) + { + printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); + return; + } + + // start the stream + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); + return; + } + } + + // mark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 1; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 1; + + // get the levels of nodes + LevelMax = Abc_NtkLevel( pNtk ); + if ( fUseReverse ) + { + LevelMin = Abc_NtkLevelReverse( pNtk ); + assert( LevelMax == LevelMin ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_ObjIsNode(pNode) ) + pNode->Level = LevelMax - pNode->Level + 1; + } + + // find the largest and the smallest levels + LevelMin = 10000; + LevelMax = -1; + fHasCos = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + { + fHasCos = 1; + continue; + } + if ( LevelMin > (int)pNode->Level ) + LevelMin = pNode->Level; + if ( LevelMax < (int)pNode->Level ) + LevelMax = pNode->Level; + } + + // set the level of the CO nodes + if ( fHasCos ) + { + LevelMax++; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + pNode->Level = LevelMax; + } + } + + // write the DOT header + fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph network {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "size = \"10,8.5\";\n" ); +// fprintf( pFile, "size = \"14,11\";\n" ); +// fprintf( pFile, "page = \"8,11\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != LevelMin ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "Network structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) + fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); + else + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the POs + if ( fHasCos ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsPo(pNode) ) + continue; + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = %s", "invtriangle" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate nodes of each rank + for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; +// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + if ( Abc_NtkIsStrash(pNtk) ) + pSopString = ""; + else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) + pSopString = Mio_GateReadName(pNode->pData); + else if ( Abc_NtkHasMapping(pNtk) ) + pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); + else + pSopString = Abc_NtkPrintSop(pNode->pData); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the PI nodes if any + if ( LevelMin == 0 ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMin ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( pNode->Level > 0 ) + continue; + if ( !Abc_ObjIsPi(pNode) ) + { + // check if the costant node is present + if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) + { + fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + continue; + } + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = %s", "triangle" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + +// fprintf( pFile, "{\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsLatch(pNode) ) + continue; + fprintf( pFile, "Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = box" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } +// fprintf( pFile, "}" ); +// fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != LevelMax ) + continue; + if ( !Abc_ObjIsPo(pNode) ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + } + + // generate edges + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsBi(pNode) || Abc_ObjIsBo(pNode) ) + continue; + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + fCompl = 0; + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( Abc_ObjIsBi(pFanin) ) + fCompl = Abc_ObjFaninC(pFanin, k); + else + fCompl = Abc_ObjFaninC(pNode, k); + } + if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + if ( !pFanin->fMarkC ) + continue; + + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pFanin->Id ); + fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); +// fprintf( pFile, ", label = \"%c\"", 'a' + k ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 0; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 0; + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); +} + + +/**Function************************************************************* + + Synopsis [Computes the printable SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NtkPrintSop( char * pSop ) +{ + static char Buffer[1000]; + char * pGet, * pSet; + pSet = Buffer; + for ( pGet = pSop; *pGet; pGet++ ) + { + if ( *pGet == '\n' ) + { + *pSet++ = '\\'; + *pSet++ = 'n'; + } + else + *pSet++ = *pGet; + } + *(pSet-2) = 0; + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Computes the printable SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( !Abc_ObjIsNode(pObj) ) + continue; + if ( Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) + continue; + Counter ++; + } + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteEqn.c b/abc70930/src/base/io/ioWriteEqn.c new file mode 100644 index 00000000..95c54577 --- /dev/null +++ b/abc70930/src/base/io/ioWriteEqn.c @@ -0,0 +1,252 @@ +/**CFile**************************************************************** + + FileName [ioWriteEqn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write equation representation of the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the logic network in the equation format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + + assert( Abc_NtkIsAigNetlist(pNtk) ); + if ( Abc_NtkLatchNum(pNtk) > 0 ) + printf( "Warning: only combinational portion is being written.\n" ); + + // check that the names are fine for the EQN format + if ( !Io_NtkWriteEqnCheck(pNtk) ) + return; + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteEqn(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# Equations for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // write the equations for the network + Io_NtkWriteEqnOne( pFile, pNtk ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Vec_Vec_t * vLevels; + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pFanin; + int i, k; + + // write the PIs + fprintf( pFile, "INORDER =" ); + Io_NtkWriteEqnCis( pFile, pNtk ); + fprintf( pFile, ";\n" ); + + // write the POs + fprintf( pFile, "OUTORDER =" ); + Io_NtkWriteEqnCos( pFile, pNtk ); + fprintf( pFile, ";\n" ); + + // write each internal node + vLevels = Vec_VecAlloc( 10 ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + fprintf( pFile, "%s = ", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + // set the input names + Abc_ObjForEachFanin( pNode, pFanin, k ) + Hop_IthVar(pNtk->pManFunc, k)->pData = Abc_ObjName(pFanin); + // write the formula + Hop_ObjPrintEqn( pFile, pNode->pData, vLevels, 0 ); + fprintf( pFile, ";\n" ); + } + Extra_ProgressBarStop( pProgress ); + Vec_VecFree( vLevels ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 9; + NameCounter = 0; + + Abc_NtkForEachCi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 10; + NameCounter = 0; + + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Make sure the network does not have offending names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + char * pName; + int i, k, Length; + int RetValue = 1; + + // make sure the network does not have proper names, such as "0" or "1" or containing parantheses + Abc_NtkForEachObj( pNtk, pObj, i ) + { + pName = Nm_ManFindNameById(pNtk->pManName, i); + if ( pName == NULL ) + continue; + Length = strlen(pName); + if ( pName[0] == '0' || pName[0] == '1' ) + { + RetValue = 0; + break; + } + for ( k = 0; k < Length; k++ ) + if ( pName[k] == '(' || pName[k] == ')' || pName[k] == '!' || pName[k] == '*' || pName[k] == '+' ) + { + RetValue = 0; + break; + } + if ( k < Length ) + break; + } + if ( RetValue == 0 ) + { + printf( "The network cannot be written in the EQN format because object %d has name \"%s\".\n", i, pName ); + printf( "Consider renaming the objects using command \"short_names\" and trying again.\n" ); + } + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteGml.c b/abc70930/src/base/io/ioWriteGml.c new file mode 100644 index 00000000..dc897300 --- /dev/null +++ b/abc70930/src/base/io/ioWriteGml.c @@ -0,0 +1,116 @@ +/**CFile**************************************************************** + + FileName [ioWriteGml.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of AIG in GML.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteGml.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG in GML.] + + Description [Useful for graph visualization using tools such as yEd: + http://www.yworks.com/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + Abc_Obj_t * pObj, * pFanin; + int i, k; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteGml(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# GML for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "graph [\n" ); + + // output the POs + fprintf( pFile, "\n" ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FFFF\" ]\n" ); // blue + fprintf( pFile, " ]\n" ); + } + // output the PIs + fprintf( pFile, "\n" ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FF00\" ]\n" ); // green + fprintf( pFile, " ]\n" ); + } + // output the latches + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"rectangle\" fill \"#FF0000\" ]\n" ); // red + fprintf( pFile, " ]\n" ); + } + // output the nodes + fprintf( pFile, "\n" ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"ellipse\" fill \"#CCCCFF\" ]\n" ); // grey + fprintf( pFile, " ]\n" ); + } + + // output the edges + fprintf( pFile, "\n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + fprintf( pFile, " edge [ source %5d target %5d\n", pObj->Id, pFanin->Id ); + fprintf( pFile, " graphics [ type \"line\" arrow \"first\" ]\n" ); + fprintf( pFile, " ]\n" ); + } + } + + fprintf( pFile, "]\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteList.c b/abc70930/src/base/io/ioWriteList.c new file mode 100644 index 00000000..71af7c53 --- /dev/null +++ b/abc70930/src/base/io/ioWriteList.c @@ -0,0 +1,288 @@ +/**CFile**************************************************************** + + FileName [ioWriteList.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of sequential AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteList.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +/* +-------- Original Message -------- +Subject: Re: abc release and retiming +Date: Sun, 13 Nov 2005 20:31:18 -0500 (EST) +From: Luca Carloni <luca@cs.columbia.edu> +To: Alan Mishchenko <alanmi@eecs.berkeley.edu> + +Alan, + +My graph-representation file format is based on an adjacency list +representation and is indeed quite simple, in fact maybe too simple... I +used it in order to reason on relatively small weighed direct graphs. I +simply list all vertices, one per line and for each vertex "V_source" I +list all vertices that are "sinks" with respect to it, i.e. such that +there is a distinct arc between "V_source" and each of them (in +paranthesis I list the name of the edge and its weight (number of latency +on that path). For instance, if you look at the following graph, you have +that vertex "v_5" is connected to vertex "v_6" through a directed arc +called "v_5_to_v_6" whose latency is equal to 3, i.e. there are three +flip-flops on this arc. Still, notice that I sometime interpret the graph +also as the representation of a LIS where each node corresponds to a +shell encapsulating a sequential core module (i.e. a module which does not +contain any combinational path between its inputs and its outputs). With +this representation an arc of latency 3 is interpreted as a wire where two +relay stations have been inserted in addition to the flip-flop terminating +the output of the core module. + +Finally, notice that the name of the arc does not necessarily have to be +"v_5_to_v_6", but it could have been something like "arc_222" or "xyz" as +long as it is a unique name in the graph. + +Thanks, +Luca + +Example of graph representation +----------------------------------------------------------------------------- +v_5 > v_6 ([v_5_to_v_6] = 3), v_12 ([v_5_to_v_12] = 2). +v_2 > v_4 ([v_2_to_v_4] = 1), v_10_s0 ([v_2_to_v_10_s0] = 6), v_12 ([v_2_to_v_12] = 3). +v_9 > v_10_s0 ([v_9_to_v_10_s0] = 5), v_12 ([v_9_to_v_12] = 2). +v_12 > v_13 ([v_12_to_v_13] = 5). +v_13 > v_14 ([v_13_to_v_14] = 1). +v_6 > v_7 ([v_6_to_v_7] = 2). +v_4 > v_5 ([v_4_to_v_5] = 2). +v_1 > v_2 ([v_1_to_v_2] = 1). +v_7 > v_8 ([v_7_to_v_8] = 2). +t > . +v_14 > t ([v_14_to_t] = 1), v_5 ([v_14_to_v_5] = 1). +v_8 > v_9 ([v_8_to_v_9] = 2). +s > v_1 ([s_to_v_1] = 1). +v_10_s0 > v_10_s1 ([v_10_s0_to_v_10_s1] = 1). +v_10_s1 > v_4 ([v_10_s1__v_4] = 1), v_8 ([v_10_s1__v_8] = 1). +----------------------------------------------------------------------------- +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ); +static void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ) +{ + FILE * pFile; + Abc_Obj_t * pObj; + int i; + +// assert( Abc_NtkIsSeq(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteList(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + fprintf( pFile, "# Adjacency list for sequential AIG \"%s\"\n", pNtk->pName ); + fprintf( pFile, "# written by ABC on %s\n", Extra_TimeStamp() ); + + // write the constant node + if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk) ) > 0 ) + Io_WriteListEdge( pFile, Abc_AigConst1(pNtk) ); + + // write the PI edges + Abc_NtkForEachPi( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + // write the internal nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + // write the host node + if ( fUseHost ) + Io_WriteListHost( pFile, pNtk ); + else + Abc_NtkForEachPo( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for one edge in a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i; + fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + fprintf( pFile, " %s", Abc_ObjName(pFanout) ); + fprintf( pFile, " ([%s_to_", Abc_ObjName(pObj) ); +// fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) ); + fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), 0 ); + if ( i != Abc_ObjFanoutNum(pObj) - 1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for one edge in a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + Abc_NtkForEachPo( pNtk, pObj, i ) + { + fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); + fprintf( pFile, " %s ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), "HOST", 0 ); + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); + } + + fprintf( pFile, "%-10s > ", "HOST" ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, " %s", Abc_ObjName(pObj) ); + fprintf( pFile, " ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), 0 ); + if ( i != Abc_NtkPiNum(pNtk) - 1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + Abc_Obj_t * pObj, * pFanout; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteCellNet(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + fprintf( pFile, "# CellNet file for network \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // the only tricky part with writing is handling latches: + // each latch comes with (a) single-input latch-input node, (b) latch proper, (c) single-input latch-output node + // we arbitrarily decide to use the interger ID of the latch-input node to represent the latch in the file + // (this ID is used for both the cell and the net driven by that cell) + + // write the PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 0\n", pObj->Id ); + // write the POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 1\n", pObj->Id ); + // write the latches (use the ID of latch input) + Abc_NtkForEachLatch( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 2\n", Abc_ObjFanin0(pObj)->Id ); + // write the logic nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + fprintf( pFile, "cell %d is %d\n", pObj->Id, 3+Abc_ObjFaninNum(pObj) ); + + // write the nets driven by PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + // write the nets driven by latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", Abc_ObjFanin0(pObj)->Id, Abc_ObjFanin0(pObj)->Id ); + pObj = Abc_ObjFanout0(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + // write the nets driven by nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWritePla.c b/abc70930/src/base/io/ioWritePla.c new file mode 100644 index 00000000..b119751c --- /dev/null +++ b/abc70930/src/base/io/ioWritePla.c @@ -0,0 +1,197 @@ +/**CFile**************************************************************** + + FileName [ioWritePla.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWritePla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the network in PLA format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + + assert( Abc_NtkIsSopNetlist(pNtk) ); + assert( Abc_NtkLevel(pNtk) == 1 ); + + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WritePlaOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WritePla: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in PLA format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pFanin, * pDriver; + char * pCubeIn, * pCubeOut, * pCube; + int i, k, nProducts, nInputs, nOutputs, nFanins; + + nProducts = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + if ( !Abc_ObjIsNode(pDriver) ) + { + nProducts++; + continue; + } + if ( Abc_NodeIsConst(pDriver) ) + { + if ( Abc_NodeIsConst1(pDriver) ) + nProducts++; + continue; + } + nProducts += Abc_SopGetCubeNum(pDriver->pData); + } + + // collect the parameters + nInputs = Abc_NtkCiNum(pNtk); + nOutputs = Abc_NtkCoNum(pNtk); + pCubeIn = ALLOC( char, nInputs + 1 ); + pCubeOut = ALLOC( char, nOutputs + 1 ); + memset( pCubeIn, '-', nInputs ); pCubeIn[nInputs] = 0; + memset( pCubeOut, '0', nOutputs ); pCubeOut[nOutputs] = 0; + + // write the header + fprintf( pFile, ".i %d\n", nInputs ); + fprintf( pFile, ".o %d\n", nOutputs ); + fprintf( pFile, ".ilb" ); + Abc_NtkForEachCi( pNtk, pNode, i ) + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".ob" ); + Abc_NtkForEachCo( pNtk, pNode, i ) + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".p %d\n", nProducts ); + + // mark the CI nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)i; + + // write the cubes + pProgress = Extra_ProgressBarStart( stdout, nOutputs ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // prepare the output cube + if ( i - 1 >= 0 ) + pCubeOut[i-1] = '0'; + pCubeOut[i] = '1'; + + // consider special cases of nodes + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + if ( !Abc_ObjIsNode(pDriver) ) + { + assert( Abc_ObjIsCi(pDriver) ); + pCubeIn[(int)pDriver->pCopy] = '1' - Abc_ObjFaninC0(pNode); + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + pCubeIn[(int)pDriver->pCopy] = '-'; + continue; + } + if ( Abc_NodeIsConst(pDriver) ) + { + if ( Abc_NodeIsConst1(pDriver) ) + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + continue; + } + + // make sure the cover is not complemented + assert( !Abc_SopIsComplement( pDriver->pData ) ); + + // write the cubes + nFanins = Abc_ObjFaninNum(pDriver); + Abc_SopForEachCube( pDriver->pData, nFanins, pCube ) + { + Abc_ObjForEachFanin( pDriver, pFanin, k ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + assert( (int)pFanin->pCopy < nInputs ); + pCubeIn[(int)pFanin->pCopy] = pCube[k]; + } + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + } + // clean the cube for future writing + Abc_ObjForEachFanin( pDriver, pFanin, k ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + assert( Abc_ObjIsCi(pFanin) ); + pCubeIn[(int)pFanin->pCopy] = '-'; + } + Extra_ProgressBarUpdate( pProgress, i, NULL ); + } + Extra_ProgressBarStop( pProgress ); + fprintf( pFile, ".e\n" ); + + // clean the CI nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = NULL; + free( pCubeIn ); + free( pCubeOut ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteVerilog.c b/abc70930/src/base/io/ioWriteVerilog.c new file mode 100644 index 00000000..9e71e3e4 --- /dev/null +++ b/abc70930/src/base/io/ioWriteVerilog.c @@ -0,0 +1,639 @@ +/**CFile**************************************************************** + + FileName [ioWriteVerilog.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to output a special subset of Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ); +static char * Io_WriteVerilogGetName( char * pName ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write verilog.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pNetlist; + FILE * pFile; + int i; + // can only write nodes represented using local AIGs + if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) ) + { + printf( "Io_WriteVerilog(): Can produce Verilog for mapped or AIG netlists only.\n" ); + return; + } + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // write the equations for the network + fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "\n" ); + + // write modules + if ( pNtk->pDesign ) + { + // write the network first + Io_WriteVerilogInt( pFile, pNtk ); + // write other things + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNetlist, i ) + { + assert( Abc_NtkIsNetlist(pNetlist) ); + if ( pNetlist == pNtk ) + continue; + fprintf( pFile, "\n" ); + Io_WriteVerilogInt( pFile, pNetlist ); + } + } + else + { + Io_WriteVerilogInt( pFile, pNtk ); + } + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes verilog.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + // write inputs and outputs +// fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); + fprintf( pFile, "module %s ( ", Abc_NtkName(pNtk) ); + // add the clock signal if it does not exist + if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) + fprintf( pFile, "clock, " ); + // write other primary inputs + fprintf( pFile, "\n " ); + if ( Abc_NtkPiNum(pNtk) > 0 ) + { + Io_WriteVerilogPis( pFile, pNtk, 3 ); + fprintf( pFile, ",\n " ); + } + if ( Abc_NtkPoNum(pNtk) > 0 ) + Io_WriteVerilogPos( pFile, pNtk, 3 ); + fprintf( pFile, " );\n" ); + // add the clock signal if it does not exist + if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) + fprintf( pFile, " input clock;\n" ); + // write inputs, outputs, registers, and wires + if ( Abc_NtkPiNum(pNtk) > 0 ) + { +// fprintf( pFile, " input gclk," ); + fprintf( pFile, " input " ); + Io_WriteVerilogPis( pFile, pNtk, 10 ); + fprintf( pFile, ";\n" ); + } + if ( Abc_NtkPoNum(pNtk) > 0 ) + { + fprintf( pFile, " output" ); + Io_WriteVerilogPos( pFile, pNtk, 5 ); + fprintf( pFile, ";\n" ); + } + // if this is not a blackbox, write internal signals + if ( !Abc_NtkHasBlackbox(pNtk) ) + { + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( pFile, " reg" ); + Io_WriteVerilogRegs( pFile, pNtk, 4 ); + fprintf( pFile, ";\n" ); + } + if ( Io_WriteVerilogWiresCount(pNtk) > 0 ) + { + fprintf( pFile, " wire" ); + Io_WriteVerilogWires( pFile, pNtk, 4 ); + fprintf( pFile, ";\n" ); + } + // write nodes + Io_WriteVerilogObjects( pFile, pNtk ); + // write registers + if ( Abc_NtkLatchNum(pNtk) > 0 ) + Io_WriteVerilogLatches( pFile, pNtk ); + } + // finalize the file + fprintf( pFile, "endmodule\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet, * pSkip; + int LineLength; + int AddedLength; + int NameCounter; + int i; + int nskip; + + pSkip = 0; + nskip = 0; + + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + + if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) ) + { + // Skip this output since it is a feedthrough -- the same + // name will appear as an input and an output which other + // tools reading verilog do not like. + + nskip++; + pSkip = pNet; // save an example of skipped net + continue; + } + + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + + if (nskip != 0) + { + assert (pSkip); + printf( "Io_WriteVerilogPos(): Omitted %d feedthrough nets from output list of module (e.g. %s).\n", nskip, Abc_ObjName(pSkip) ); + return; + } + +} + +/**Function************************************************************* + + Synopsis [Writes the wires.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pObj, * pNet, * pBox, * pTerm; + int LineLength; + int AddedLength; + int NameCounter; + int i, k, Counter, nNodes; + + // count the number of wires + nNodes = Io_WriteVerilogWiresCount( pNtk ); + + // write the wires + Counter = 0; + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) + continue; + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_NtkForEachBox( pNtk, pBox, i ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + Abc_ObjForEachFanin( pBox, pTerm, k ) + { + pNet = Abc_ObjFanin0(pTerm); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_ObjForEachFanout( pBox, pTerm, k ) + { + pNet = Abc_ObjFanout0(pTerm); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + } + assert( Counter == nNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the regs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pLatch, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i, Counter, nNodes; + + // count the number of latches + nNodes = Abc_NtkLatchNum(pNtk); + + // write the wires + Counter = 0; + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pNet = Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch; + int i; + if ( Abc_NtkLatchNum(pNtk) == 0 ) + return; + // write the latches +// fprintf( pFile, " always @(posedge %s) begin\n", Io_WriteVerilogGetName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0))) ); +// fprintf( pFile, " always begin\n" ); + fprintf( pFile, " always @ (posedge clock) begin\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + fprintf( pFile, " %s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + fprintf( pFile, " <= %s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pLatch)))) ); + } + fprintf( pFile, " end\n" ); + // check if there are initial values + Abc_NtkForEachLatch( pNtk, pLatch, i ) + if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO || Abc_LatchInit(pLatch) == ABC_INIT_ONE ) + break; + if ( i == Abc_NtkLatchNum(pNtk) ) + return; + // write the initial values + fprintf( pFile, " initial begin\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0)))) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO ) + fprintf( pFile, " %s <= 1\'b0;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE ) + fprintf( pFile, " %s <= 1\'b1;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + } + fprintf( pFile, " end\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the nodes and boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Vec_Vec_t * vLevels; + Abc_Ntk_t * pNtkBox; + Abc_Obj_t * pObj, * pTerm, * pFanin; + Hop_Obj_t * pFunc; + int i, k, Counter, nDigits, Length; + + // write boxes + nDigits = Extra_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); + Counter = 0; + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkBox = pObj->pData; + fprintf( pFile, " %s box%0*d", pNtkBox->pName, nDigits, Counter++ ); + fprintf( pFile, "(" ); + Abc_NtkForEachPi( pNtkBox, pTerm, k ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) ); + fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) ); + } + Abc_NtkForEachPo( pNtkBox, pTerm, k ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) ); + fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " ); + } + fprintf( pFile, ");\n" ); + } + // write nodes + if ( Abc_NtkHasMapping(pNtk) ) + { + Length = Mio_LibraryReadGateNameMax(pNtk->pManFunc); + nDigits = Extra_Base10Log( Abc_NtkNodeNum(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, k ) + { + Mio_Gate_t * pGate = pObj->pData; + Mio_Pin_t * pGatePin; + // write the node + fprintf( pFile, " %-*s g%0*d", Length, Mio_GateReadName(pGate), nDigits, Counter++ ); + fprintf( pFile, "(" ); + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_PinReadName(pGatePin)) ); + fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) ); + } + assert ( i == Abc_ObjFaninNum(pObj) ); + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) ); + fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) ); + fprintf( pFile, ");\n" ); + } + } + else + { + vLevels = Vec_VecAlloc( 10 ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pFunc = pObj->pData; + fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + // set the input names + Abc_ObjForEachFanin( pObj, pFanin, k ) + Hop_IthVar(pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin))); + // write the formula + Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 ); + fprintf( pFile, ";\n" ); + // clear the input names + Abc_ObjForEachFanin( pObj, pFanin, k ) + free( Hop_IthVar(pNtk->pManFunc, k)->pData ); + } + Vec_VecFree( vLevels ); + } +} + +/**Function************************************************************* + + Synopsis [Counts the number of wires.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pNet, * pBox; + int i, k, nWires; + nWires = Abc_NtkLatchNum(pNtk); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) + continue; + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + nWires++; + } + Abc_NtkForEachBox( pNtk, pBox, i ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + nWires += Abc_ObjFaninNum(pBox); + Abc_ObjForEachFanout( pBox, pObj, k ) + { + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + nWires++; + } + } + return nWires; +} + +/**Function************************************************************* + + Synopsis [Prepares the name for writing the Verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_WriteVerilogGetName( char * pName ) +{ + static char Buffer[500]; + int Length, i; + Length = strlen(pName); + // consider the case of a signal having name "0" or "1" + if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) ) + { + for ( i = 0; i < Length; i++ ) + if ( !((pName[i] >= 'a' && pName[i] <= 'z') || + (pName[i] >= 'A' && pName[i] <= 'Z') || + (pName[i] >= '0' && pName[i] <= '9') || pName[i] == '_') ) + break; + if ( i == Length ) + return pName; + } + // create Verilog style name + Buffer[0] = '\\'; + for ( i = 0; i < Length; i++ ) + Buffer[i+1] = pName[i]; + Buffer[Length+1] = ' '; + Buffer[Length+2] = 0; + return Buffer; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/io_.c b/abc70930/src/base/io/io_.c new file mode 100644 index 00000000..62dd60e5 --- /dev/null +++ b/abc70930/src/base/io/io_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [io_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/module.make b/abc70930/src/base/io/module.make new file mode 100644 index 00000000..bb35a7fc --- /dev/null +++ b/abc70930/src/base/io/module.make @@ -0,0 +1,25 @@ +SRC += src/base/io/io.c \ + src/base/io/ioReadAiger.c \ + src/base/io/ioReadBaf.c \ + src/base/io/ioReadBench.c \ + src/base/io/ioReadBlif.c \ + src/base/io/ioReadBlifAig.c \ + src/base/io/ioReadBlifMv.c \ + src/base/io/ioReadDsd.c \ + src/base/io/ioReadEdif.c \ + src/base/io/ioReadEqn.c \ + src/base/io/ioReadPla.c \ + src/base/io/ioReadVerilog.c \ + src/base/io/ioUtil.c \ + src/base/io/ioWriteAiger.c \ + src/base/io/ioWriteBaf.c \ + src/base/io/ioWriteBench.c \ + src/base/io/ioWriteBlif.c \ + src/base/io/ioWriteBlifMv.c \ + src/base/io/ioWriteCnf.c \ + src/base/io/ioWriteDot.c \ + src/base/io/ioWriteEqn.c \ + src/base/io/ioWriteGml.c \ + src/base/io/ioWriteList.c \ + src/base/io/ioWritePla.c \ + src/base/io/ioWriteVerilog.c |