From a16a0f102785468bf1b0bf4c48fbd84b179d7b5c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Wed, 6 Mar 2024 01:40:48 -0800 Subject: [PATCH] Writing Verilog for AIG using NAND gates. --- src/aig/gia/gia.h | 1 + src/aig/gia/giaMan.c | 99 +++++++++++++++++++++++++++++++++++++++++--- src/base/abci/abc.c | 76 ++++++++++++++++++++++++++++++++-- 3 files changed, 167 insertions(+), 9 deletions(-) diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index f12ab35df..704cd728b 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1532,6 +1532,7 @@ extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign, int fReverse ); +extern void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 5d8c86b31..288c06536 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -1414,12 +1414,12 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int if ( fInterComb ) { if ( fAssign ) { - extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ); - Gia_ManDumpInterfaceAssign( p, pFileName, fReverse ); + extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterfaceAssign( p, pFileName ); } else { - extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ); - Gia_ManDumpInterface( p, pFileName, fReverse ); + extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterface( p, pFileName ); } } else @@ -1899,7 +1899,7 @@ void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) SeeAlso [] ***********************************************************************/ -void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ) +void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -2010,7 +2010,7 @@ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName, int fReverse ) Vec_BitFree( vInvs ); Vec_BitFree( vUsed ); } -void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ) +void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -2123,6 +2123,93 @@ void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName, int fReverse ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpNandLit( FILE * pFile, int nIns, int Lit, int nDigits ) +{ + if ( Lit == 0 ) + fprintf( pFile, "1\'b0" ); + else if ( Lit == 1 ) + fprintf( pFile, "1\'b1" ); + else if ( Abc_Lit2Var(Lit) <= nIns ) + fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? '~':' '), nDigits, Abc_Lit2Var(Lit) ); + else + fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? ' ':'~'), nDigits, Abc_Lit2Var(Lit) ); +} +void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; int i, nPis = Gia_ManPiNum(p); + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + assert( Gia_ManRegNum(p) == 0 ); + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( " ); + if ( p->vNamesIn ) { + Gia_ManDumpIoList( p, pFile, 0, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + } + else { + fprintf( pFile, "\n " ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, "%s, ", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI) ); + fprintf( pFile, "\n " ); + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, "%s%s ", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); + fprintf( pFile, "\n);\n\n" ); + fprintf( pFile, " input" ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI), i < Gia_ManPiNum(p)-1 ? ",":"" ); + fprintf( pFile, ";\n" ); + fprintf( pFile, " output" ); + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\n" ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, " wire n%0*d = %s;\n", nDigits, i+1, p->vNamesIn ? (char *)Vec_PtrEntry(p->vNamesIn, i) : Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " wire n%0*d = ~(", nDigits, i ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0(pObj, i), nDigits ); + fprintf( pFile, " & " ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit1(pObj, i), nDigits ); + fprintf( pFile, ");\n" ); + } + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", p->vNamesOut ? (char *)Vec_PtrEntry(p->vNamesOut, i) : Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0p(p, pObj), nDigits ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); +} + /**Function************************************************************* Synopsis [Generate hierarchical design.] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index d6363a0cc..9547c4a79 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -219,6 +219,7 @@ static int Abc_CommandInter ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandBb2Wb ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOutdec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNodeDup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandWrap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestColor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -998,6 +999,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "bb2wb", Abc_CommandBb2Wb, 0 ); Cmd_CommandAdd( pAbc, "Various", "outdec", Abc_CommandOutdec, 1 ); Cmd_CommandAdd( pAbc, "Various", "nodedup", Abc_CommandNodeDup, 1 ); + Cmd_CommandAdd( pAbc, "Various", "wrap", Abc_CommandWrap, 0 ); Cmd_CommandAdd( pAbc, "Various", "testcolor", Abc_CommandTestColor, 0 ); Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); // Cmd_CommandAdd( pAbc, "Various", "qbf_solve", Abc_CommandTest, 0 ); @@ -14463,6 +14465,67 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandWrap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char * pFileName = NULL, * pFileName2 = NULL; + FILE * pFile = NULL, * pFile2 = NULL; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( 1,"Two file names are expected on the command line.\n" ); + return 0; + } + pFileName = argv[globalUtilOptind]; + pFileName2 = argv[globalUtilOptind+1]; + pFile = fopen( pFileName, "rb" ); + pFile2 = fopen( pFileName2, "wb" ); + if ( pFile && pFile2 ) + { + char Buffer[1000]; + while ( fgets( Buffer, 1000, pFile ) != NULL ) + { + if ( Buffer[strlen(Buffer)-1] == '\n' ) + Buffer[strlen(Buffer)-1] = 0; + if ( Buffer[strlen(Buffer)-1] == '\r' ) + Buffer[strlen(Buffer)-1] = 0; + fprintf( pFile2, " printf(\"%s\\n\");\n", Buffer ); + } + } + if ( pFile ) fclose(pFile); + if ( pFile2 ) fclose(pFile2); + return 0; + +usage: + Abc_Print( -2, "usage: wrap [-h] \n" ); + Abc_Print( -2, "\t wrapping lines\n" ); + Abc_Print( -2, "\t : input text file\n"); + Abc_Print( -2, "\t : output text file\n"); + return 1; + +} + /**Function************************************************************* Synopsis [] @@ -32065,8 +32128,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) char * pFileName; char ** pArgvNew; int c, nArgcNew; - int fUnique = 0; + int fUnique = 0; int fVerilog = 0; + int fVerNand = 0; int fInter = 0; int fInterComb = 0; int fAssign = 0; @@ -32078,7 +32142,7 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int fSkipComment = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upicabmlnrsvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upqicabmlnrsvh" ) ) != EOF ) { switch ( c ) { @@ -32088,6 +32152,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fVerilog ^= 1; break; + case 'q': + fVerNand ^= 1; + break; case 'i': fInter ^= 1; break; @@ -32143,6 +32210,8 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_AigerWriteSimple( pGia, pFileName ); Gia_ManStop( pGia ); } + else if ( fVerNand ) + Gia_ManDumpVerilogNand( pAbc->pGia, pFileName ); else if ( fVerilog ) Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter, fInterComb, fAssign, fReverse ); else if ( fMiniAig ) @@ -32154,10 +32223,11 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &w [-upicabmlnsvh] \n" ); + Abc_Print( -2, "usage: &w [-upqicabmlnsvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); + Abc_Print( -2, "\t-q : toggle writing Verilog with NAND-gates [default = %s]\n", fVerNand? "yes" : "no" ); Abc_Print( -2, "\t-i : toggle writing the interface module in Verilog [default = %s]\n", fInter? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle writing the interface module in Verilog [default = %s]\n", fInterComb? "yes" : "no" ); Abc_Print( -2, "\t-a : toggle writing the interface module with assign-statements [default = %s]\n", fAssign? "yes" : "no" );