blob: 45c8ed99a53f5acbfc83426638e92b0818e43c8b [file] [log] [blame]
/**CFile****************************************************************
FileName [cbaWriteVer.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Verilog writer.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: cbaWriteVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cba.h"
#include "cbaPrs.h"
#include "map/mio/mio.h"
#include "base/main/main.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cba_ManCreatePrimMap( char ** pMap )
{
memset( pMap, 0, sizeof(char *) * CBA_BOX_LAST );
pMap[ CBA_BOX_SLICE ] = "sli";
pMap[ CBA_BOX_CONCAT ] = "icc";
pMap[ CBA_BOX_BUF ] = "";
pMap[ CBA_BOX_INV ] = "~";
pMap[ CBA_BOX_AND ] = "&";
pMap[ CBA_BOX_NAND ] = "&";
pMap[ CBA_BOX_OR ] = "|";
pMap[ CBA_BOX_NOR ] = "|";
pMap[ CBA_BOX_XOR ] = "^";
pMap[ CBA_BOX_XNOR ] = "^";
pMap[ CBA_BOX_SHARP ] = "&";
pMap[ CBA_BOX_SHARPL ] = "&";
pMap[ CBA_BOX_MUX ] = "?";
pMap[ CBA_BOX_MAJ ] = "maj";
pMap[ CBA_BOX_RAND ] = "&";
pMap[ CBA_BOX_RNAND ] = "~&";
pMap[ CBA_BOX_ROR ] = "|";
pMap[ CBA_BOX_RNOR ] = "~|";
pMap[ CBA_BOX_RXOR ] = "^";
pMap[ CBA_BOX_RXNOR ] = "~^";
pMap[ CBA_BOX_LNOT ] = "!";
pMap[ CBA_BOX_LAND ] = "&&";
pMap[ CBA_BOX_LNAND ] = "logic nand";
pMap[ CBA_BOX_LOR ] = "||";
pMap[ CBA_BOX_LNOR ] = "logic nor";
pMap[ CBA_BOX_LXOR ] = "^^";
pMap[ CBA_BOX_LXNOR ] = "logic xnor";
pMap[ CBA_BOX_NMUX ] = "nmux";
pMap[ CBA_BOX_SEL ] = "sel";
pMap[ CBA_BOX_PSEL ] = "prio-select";
pMap[ CBA_BOX_ENC ] = "enc";
pMap[ CBA_BOX_PENC ] = "prio-enc";
pMap[ CBA_BOX_DEC ] = "dec";
pMap[ CBA_BOX_EDEC ] = "enable-dec";
pMap[ CBA_BOX_ADD ] = "+";
pMap[ CBA_BOX_SUB ] = "-";
pMap[ CBA_BOX_MUL ] = "*";
pMap[ CBA_BOX_DIV ] = "/";
pMap[ CBA_BOX_MOD ] = "%";
pMap[ CBA_BOX_REM ] = "%";
pMap[ CBA_BOX_POW ] = "**";
pMap[ CBA_BOX_MIN ] = "-";
pMap[ CBA_BOX_SQRT ] = "@";
pMap[ CBA_BOX_ABS ] = "abs";
pMap[ CBA_BOX_LTHAN ] = "<";
pMap[ CBA_BOX_LETHAN ] = "<=";
pMap[ CBA_BOX_METHAN ] = ">=";
pMap[ CBA_BOX_MTHAN ] = ">";
pMap[ CBA_BOX_EQU ] = "==";
pMap[ CBA_BOX_NEQU ] = "!=";
pMap[ CBA_BOX_SHIL ] = "<<";
pMap[ CBA_BOX_SHIR ] = ">>";
pMap[ CBA_BOX_SHILA ] = "<<<";
pMap[ CBA_BOX_SHIRA ] = ">>>";
pMap[ CBA_BOX_ROTL ] = "rotL";
pMap[ CBA_BOX_ROTR ] = "rotR";
pMap[ CBA_BOX_TRI ] = "tri";
pMap[ CBA_BOX_RAM ] = "ram";
pMap[ CBA_BOX_RAMR ] = "ramR";
pMap[ CBA_BOX_RAMW ] = "ramW";
pMap[ CBA_BOX_RAMWC ] = "ramWC";
pMap[ CBA_BOX_RAMBOX ] = "ramBox";
pMap[ CBA_BOX_LATCH ] = "lat";
pMap[ CBA_BOX_LATCHRS] = "latrs";
pMap[ CBA_BOX_DFF ] = "dff";
pMap[ CBA_BOX_DFFRS ] = "dffrs";
}
/**Function*************************************************************
Synopsis [Writing parser state into a file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Prs_NameIsLegalInVerilog( char * pName, int NameId )
{
// identifier ::= simple_identifier | escaped_identifier
// simple_identifier ::= [a-zA-Z_][a-zA-Z0-9_$]
// escaped_identifier ::= \ {Any_ASCII_character_except_white_space} white_space
// white_space ::= space | tab | newline
assert( pName != NULL && *pName != '\0' );
if ( *pName == '\\' )
return 1;
if ( NameId < 13 ) // see PRS_VER_UNKNOWN in cbaReadVer.c
return 0;
if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && *pName != '_' )
return 0;
while ( *(++pName) )
if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && (*pName < '0' || *pName > '9') && *pName != '_' && *pName != '$' )
return 0;
return 1;
}
char * Prs_ObjGetName( Prs_Ntk_t * p, int NameId )
{
char * pName = Prs_NtkStr(p, NameId);
if ( pName == NULL )
return pName;
if ( Prs_NameIsLegalInVerilog(pName, NameId) )
return pName;
return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "\\%s ", pName );
}
static inline char * Prs_ManWriteRange( Prs_Ntk_t * p, int RangeId, int fSlice )
{
int Left = RangeId ? Hash_IntObjData0( p->vHash, RangeId ) : 0;
int Right = RangeId ? Hash_IntObjData1( p->vHash, RangeId ) : 0;
if ( Left == Right && fSlice )
return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "[%d]", Right );
else
return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "[%d:%d]", Left, Right );
}
static void Prs_ManWriteVerilogConcat( FILE * pFile, Prs_Ntk_t * p, int Con )
{
extern void Prs_ManWriteVerilogArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs, int fOdd );
Vec_Int_t * vSigs = Prs_CatSignals(p, Con);
fprintf( pFile, "{" );
Prs_ManWriteVerilogArray( pFile, p, vSigs, 0 );
fprintf( pFile, "}" );
}
static void Prs_ManWriteVerilogSignal( FILE * pFile, Prs_Ntk_t * p, int Sig )
{
int Value = Abc_Lit2Var2( Sig );
Prs_ManType_t Type = (Prs_ManType_t)Abc_Lit2Att2( Sig );
if ( Type == CBA_PRS_NAME )
fprintf( pFile, "%s", Prs_ObjGetName(p, Value) );
else if ( Type == CBA_PRS_CONST )
fprintf( pFile, "%s", Prs_NtkConst(p, Value) );
else if ( Type == CBA_PRS_SLICE )
fprintf( pFile, "%s%s", Prs_ObjGetName(p, Prs_SliceName(p, Value)), Prs_ManWriteRange(p, Prs_SliceRange(p, Value), 1) );
else if ( Type == CBA_PRS_CONCAT )
Prs_ManWriteVerilogConcat( pFile, p, Value );
else assert( 0 );
}
void Prs_ManWriteVerilogArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs, int fOdd )
{
int i, Sig, fFirst = 1;
assert( Vec_IntSize(vSigs) > 0 );
Vec_IntForEachEntry( vSigs, Sig, i )
{
if ( fOdd && !(i & 1) )
continue;
fprintf( pFile, "%s", fFirst ? "" : ", " );
Prs_ManWriteVerilogSignal( pFile, p, Sig );
fFirst = 0;
}
}
static void Prs_ManWriteVerilogArray2( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs )
{
int i, FormId, ActSig;
assert( Vec_IntSize(vSigs) % 2 == 0 );
Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i )
{
fprintf( pFile, "." );
fprintf( pFile, "%s", Prs_ObjGetName(p, FormId) );
fprintf( pFile, "(" );
Prs_ManWriteVerilogSignal( pFile, p, ActSig );
fprintf( pFile, ")%s", (i == Vec_IntSize(vSigs) - 2) ? "" : ", " );
}
}
static void Prs_ManWriteVerilogMux( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs )
{
int i, FormId, ActSig;
char * pStrs[4] = { " = ", " ? ", " : ", ";\n" };
assert( Vec_IntSize(vSigs) == 8 );
fprintf( pFile, " assign " );
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vSigs, 1) );
fprintf( pFile, "%s", pStrs[0] );
Vec_IntForEachEntryDoubleStart( vSigs, FormId, ActSig, i, 2 )
{
Prs_ManWriteVerilogSignal( pFile, p, ActSig );
fprintf( pFile, "%s", pStrs[i/2] );
}
}
static void Prs_ManWriteVerilogBoxes( FILE * pFile, Prs_Ntk_t * p, char ** pTypeNames )
{
Vec_Int_t * vBox; int i, k;
Prs_NtkForEachBox( p, vBox, i )
{
Cba_ObjType_t NtkId = (Cba_ObjType_t)Prs_BoxNtk(p, i);
//char * pNtkName = Prs_ObjGetName(p, Prs_BoxName(p, i));
if ( NtkId == CBA_BOX_MUX && Prs_BoxIsNode(p, i) )
Prs_ManWriteVerilogMux( pFile, p, vBox );
else if ( Prs_BoxIsNode(p, i) ) // node
{
fprintf( pFile, " assign " );
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 1) );
fprintf( pFile, " = " );
if ( Cba_TypeIsUnary(NtkId) )
{
fprintf( pFile, "%s", pTypeNames[NtkId] );
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) );
}
else if ( NtkId == CBA_BOX_NMUX )
{
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) );
fprintf( pFile, " ? " );
for ( k = 5; k < Vec_IntSize(vBox); k += 2 )
{
if ( k > 5 ) fprintf( pFile, " : " );
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, k) );
}
}
else if ( NtkId == CBA_BOX_ADD )
{
if ( Vec_IntEntry(vBox, 3) )
{
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) );
fprintf( pFile, " %s ", pTypeNames[NtkId] );
}
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 5) );
fprintf( pFile, " %s ", pTypeNames[NtkId] );
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 7) );
}
else
{
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) );
fprintf( pFile, " %s ", pTypeNames[NtkId] );
Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 5) );
}
fprintf( pFile, ";\n" );
}
else // box
{
fprintf( pFile, " %s %s ( ", Prs_ObjGetName(p, NtkId), Prs_BoxName(p, i) ? Prs_ObjGetName(p, Prs_BoxName(p, i)) : "" );
Prs_ManWriteVerilogArray2( pFile, p, vBox );
fprintf( pFile, " );\n" );
}
}
}
static void Prs_ManWriteVerilogIos( FILE * pFile, Prs_Ntk_t * p, int SigType )
{
int NameId, RangeId, i;
char * pSigNames[4] = { "inout", "input", "output", "wire" };
Vec_Int_t * vSigs[4] = { &p->vInouts, &p->vInputs, &p->vOutputs, &p->vWires };
Vec_Int_t * vSigsR[4] = { &p->vInoutsR, &p->vInputsR, &p->vOutputsR, &p->vWiresR };
if ( SigType == 3 )
fprintf( pFile, "\n" );
Vec_IntForEachEntryTwo( vSigs[SigType], vSigsR[SigType], NameId, RangeId, i )
{
fprintf( pFile, " %s %s%s", pSigNames[SigType], Abc_LitIsCompl(RangeId) ? "signed " : "", RangeId ? Prs_ManWriteRange(p, Abc_Lit2Var(RangeId), 0) : "" );
fprintf( pFile, "%s;\n", Prs_ObjGetName(p, NameId) );
}
}
static void Prs_ManWriteVerilogIoOrder( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vOrder )
{
int i, NameId;
Vec_IntForEachEntry( vOrder, NameId, i )
fprintf( pFile, "%s%s", Prs_ObjGetName(p, Abc_Lit2Var2(NameId)), i == Vec_IntSize(vOrder) - 1 ? "" : ", " );
}
static void Prs_ManWriteVerilogNtk( FILE * pFile, Prs_Ntk_t * p, char ** pTypeNames )
{
int s;
// write header
fprintf( pFile, "module %s (\n ", Prs_ObjGetName(p, p->iModuleName) );
Prs_ManWriteVerilogIoOrder( pFile, p, &p->vOrder );
fprintf( pFile, "\n );\n" );
// write declarations
for ( s = 0; s < 4; s++ )
Prs_ManWriteVerilogIos( pFile, p, s );
fprintf( pFile, "\n" );
// write objects
Prs_ManWriteVerilogBoxes( pFile, p, pTypeNames );
fprintf( pFile, "endmodule\n\n" );
}
void Prs_ManWriteVerilog( char * pFileName, Vec_Ptr_t * vPrs )
{
char * pTypeNames[CBA_BOX_LAST];
Prs_Ntk_t * pNtk = Prs_ManRoot(vPrs); int i;
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open output file \"%s\".\n", pFileName );
return;
}
Cba_ManCreatePrimMap( pTypeNames );
fprintf( pFile, "// Design \"%s\" written by ABC on %s\n\n", Prs_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() );
Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i )
Prs_ManWriteVerilogNtk( pFile, pNtk, pTypeNames );
fclose( pFile );
}
static inline int Cba_NameIsLegalInVerilog( char * pName, int NameId )
{
// identifier ::= simple_identifier | escaped_identifier
// simple_identifier ::= [a-zA-Z_][a-zA-Z0-9_$]
// escaped_identifier ::= \ {Any_ASCII_character_except_white_space} white_space
// white_space ::= space | tab | newline
assert( pName != NULL && *pName != '\0' );
if ( *pName == '\\' )
return 1;
if ( NameId < 13 ) // see PRS_VER_UNKNOWN in cbaReadVer.c
return 0;
if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && *pName != '_' )
return 0;
while ( *(++pName) )
if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && (*pName < '0' || *pName > '9') && *pName != '_' && *pName != '$' )
return 0;
return 1;
}
char * Cba_ObjGetName( Cba_Ntk_t * p, int i )
{
char * pName = Cba_ObjNameStr(p, i);
if ( pName == NULL )
return pName;
if ( Cba_NameIsLegalInVerilog(pName, Cba_ObjName(p, i)) )
return pName;
return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s ", pName );
}
char * Cba_FonGetName( Cba_Ntk_t * p, int i )
{
char * pName = Cba_FonNameStr(p, i);
if ( pName == NULL )
return pName;
if ( Cba_ObjType(p, Cba_FonObj(p, i)) == CBA_BOX_SLICE )
return pName;
if ( Cba_NameIsLegalInVerilog(pName, Cba_FonName(p, i)) )
return pName;
return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s ", pName );
}
char * Cba_ManGetSliceName( Cba_Ntk_t * p, int iFon, int RangeId )
{
int Left = Cba_NtkRangeLeft(p, RangeId);
int Right = Cba_NtkRangeRight(p, RangeId);
char * pName = Cba_FonNameStr(p, iFon);
if ( Cba_NameIsLegalInVerilog(pName, Cba_FonName(p, iFon)) )
if ( Left == Right )
return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "%s[%d]", pName, Right );
else
return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "%s[%d:%d]", pName, Left, Right );
else
if ( Left == Right )
return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s [%d]", pName, Right );
else
return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s [%d:%d]", pName, Left, Right );
}
void Cba_ManWriteFonRange( Cba_Ntk_t * p, int iFon )
{
Vec_Str_t * vStr = &p->pDesign->vOut;
if ( !iFon || Cba_FonIsConst(iFon) || (Cba_FonRangeSize(p, iFon) == 1 && Cba_FonRight(p, iFon) == 0) )
return;
if ( Cba_FonSigned(p, iFon) )
Vec_StrPrintF( vStr, "signed " );
Vec_StrPrintF( vStr, "[%d:%d] ", Cba_FonLeft(p, iFon), Cba_FonRight(p, iFon) );
}
void Cba_ManWriteFonName( Cba_Ntk_t * p, int iFon, int fInlineConcat, int fInput )
{
extern void Cba_ManWriteConcat( Cba_Ntk_t * p, int iObj );
Vec_Str_t * vStr = &p->pDesign->vOut;
if ( !iFon || (!Cba_FonIsConst(iFon) && !Cba_FonName(p, iFon)) )
Vec_StrPrintF( vStr, "Open_%d", Cba_NtkMan(p)->nOpens++ );
// Vec_StrPrintF( vStr, "1\'b0" );
else if ( fInlineConcat && !Cba_FonIsConst(iFon) && Cba_ObjIsConcat(p, Cba_FonObj(p, iFon)) )
Cba_ManWriteConcat( p, Cba_FonObj(p, iFon) );
else
{
int Range = fInput ? Cba_FonRangeSize( p, iFon ) : 0;
if ( fInput && Range > 1 )
Vec_StrPush( vStr, '{' );
Vec_StrPrintStr( vStr, Cba_FonIsConst(iFon) ? Cba_NtkConst(p, Cba_FonConst(iFon)) : Cba_FonGetName(p, iFon) );
if ( fInput && Range > 1 )
Vec_StrPush( vStr, '}' );
}
}
void Cba_ManWriteConcat( Cba_Ntk_t * p, int iObj )
{
int i, iFin, iFon;
Vec_Str_t * vStr = &p->pDesign->vOut;
assert( Cba_ObjIsConcat(p, iObj) );
Vec_StrPush( vStr, '{' );
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
{
Vec_StrPrintStr( vStr, i ? ", " : "" );
Cba_ManWriteFonName( p, iFon, 1, 0 );
}
Vec_StrPush( vStr, '}' );
}
int Cba_ManWriteLineFile( Cba_Ntk_t * p, int iObj, int FileAttr, int LineAttr )
{
Vec_Str_t * vStr = &p->pDesign->vOut;
int FileId = 0, LineId = 0;
if ( FileAttr && (FileId = Cba_ObjAttrValue(p, iObj, FileAttr)) )
{
LineId = Cba_ObjAttrValue(p, iObj, LineAttr);
Vec_StrPrintF( vStr, " // %s(%d)", Cba_NtkStr(p, FileId), LineId );
return 1;
}
return 0;
}
void Cba_ManWriteVerilogNtk( Cba_Ntk_t * p, int fInlineConcat )
{
Vec_Str_t * vStr = &p->pDesign->vOut;
int i, k, iObj, iFin, iFon, StartPos, Status;
int FileAttr = Cba_NtkStrId( p, "file" );
int LineAttr = Cba_NtkStrId( p, "line" );
int fUseNewLine = (int)(Cba_NtkPioNum(p) > 5);
// mark PO fons
Vec_Bit_t * vPoFons = Vec_BitStart( Cba_NtkFonNum(p)+1 );
Cba_NtkForEachPoDriverFon( p, iObj, iFon, i )
if ( Cba_FonIsReal(iFon) && Cba_FonName(p, iFon) == Cba_ObjName(p, iObj) )
Vec_BitWriteEntry( vPoFons, iFon, 1 );
// write header
Vec_StrPrintStr( vStr, "module " );
Vec_StrPrintStr( vStr, Cba_NtkName(p) );
Vec_StrPrintStr( vStr, fUseNewLine ? " (\n " : " ( " );
StartPos = Vec_StrSize(vStr);
Cba_NtkForEachPioOrder( p, iObj, i )
{
Vec_StrPrintStr( vStr, i ? ", " : "" );
if ( Vec_StrSize(vStr) > StartPos + 70 )
{
StartPos = Vec_StrSize(vStr);
Vec_StrPrintStr( vStr, "\n " );
}
Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
}
Vec_StrPrintStr( vStr, fUseNewLine ? "\n );" : " );" );
Cba_ManWriteLineFile( p, 0, FileAttr, LineAttr );
Vec_StrPrintStr( vStr, fUseNewLine ? "\n" : "\n\n" );
// write inputs/outputs
Cba_NtkForEachPioOrder( p, iObj, i )
{
int Offset = Vec_StrSize(vStr);
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, Cba_ObjIsPi(p, iObj) ? "input " : "output " );
Cba_ManWriteFonRange( p, Cba_ObjIsPi(p, iObj) ? Cba_ObjFon0(p, iObj) : Cba_ObjFinFon(p, iObj, 0) );
Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
Vec_StrPrintF( vStr, ";%*s", Offset + 40 - Vec_StrSize(vStr), "" );
Cba_ManWriteLineFile( p, iObj, FileAttr, LineAttr );
Vec_StrPush( vStr, '\n' );
}
Vec_StrPrintStr( vStr, "\n" );
// write objects
Cba_NtkForEachBox( p, iObj )
{
// char * pNameNtk = Cba_NtkName(p);
// char * pNameInst = Cba_ObjGetName(p, iObj);
int Type = Cba_ObjType(p, iObj);
if ( Cba_ObjIsSlice(p, iObj) )
continue;
if ( fInlineConcat && Cba_ObjIsConcat(p, iObj) )
continue;
if ( Cba_ObjIsBoxUser(p, iObj) )
{
Cba_Ntk_t * pNtk = Cba_ObjNtk(p, iObj);
// write output wire declarations
Cba_ObjForEachFon( p, iObj, iFon, i )
{
if ( Vec_BitEntry(vPoFons, iFon) )
continue;
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFon );
Cba_ManWriteFonName( p, iFon, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
}
// write box
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, Cba_NtkName(pNtk) );
Vec_StrPush( vStr, ' ' );
if ( Cba_ObjName(p, iObj) )
Vec_StrPrintF( vStr, "%s ", Cba_ObjGetName(p, iObj) );
// write input binding
Vec_StrPrintStr( vStr, "( " );
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
{
Vec_StrPrintF( vStr, "%s.%s(", i ? ", " : "", Cba_ObjGetName(pNtk, Cba_NtkPi(pNtk, i)) );
Cba_ManWriteFonName( p, iFon, fInlineConcat, 1 );
Vec_StrPush( vStr, ')' );
}
// write output binding
Cba_ObjForEachFon( p, iObj, iFon, i )
{
Vec_StrPrintF( vStr, "%s.%s(", Cba_ObjFinNum(p, iObj) ? ", " : "", Cba_ObjGetName(pNtk, Cba_NtkPo(pNtk, i)) );
Cba_ManWriteFonName( p, iFon, 0, 1 );
Vec_StrPush( vStr, ')' );
}
Vec_StrPrintStr( vStr, ");" );
}
else if ( Type == CBA_BOX_RAMWC || Type == CBA_BOX_RAMBOX || Type == CBA_BOX_RAMR )
{
int Num = (Type == CBA_BOX_RAMWC) ? 0 : (Type == CBA_BOX_RAMR ? 1 : 2); // write / read / box
char * pBoxName[3] = { "RAM_WRITE", "RAM_READ", "RAM_BOX" };
char * pOutputs[3] = { "ram", "rdata", "out" };
char * pInputs[3][4] = { {"clk", "wen", "waddr", "wdata"}, {"ren", "raddr", "ram"}, {"in0", "in1", "in2", "in3"} };
// write declaration for the output
int iFonOut = Cba_ObjFon0(p, iObj);
if ( Vec_BitEntry(vPoFons, iFonOut) )
Vec_StrPrintStr( vStr, " assign " );
else
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFonOut );
}
Cba_ManWriteFonName( p, iFonOut, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
// write box
Vec_StrPrintF( vStr, " %s( ", pBoxName[Num] );
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
{
Vec_StrPrintF( vStr, "%s.%s(", i ? ", " : "", pInputs[Num][i] );
Cba_ManWriteFonName( p, iFon, fInlineConcat, 1 );
Vec_StrPush( vStr, ')' );
}
Vec_StrPrintF( vStr, "%s.%s(", Cba_ObjFinNum(p, iObj) ? ", " : "", pOutputs[Num] );
Cba_ManWriteFonName( p, iFonOut, 0, 1 );
Vec_StrPrintStr( vStr, ") );" );
}
else if ( Type == CBA_BOX_NMUX || Type == CBA_BOX_SEL )
{
int fUseSel = Type == CBA_BOX_SEL;
int nBits = fUseSel ? Cba_ObjFinNum(p, iObj) - 1 : Abc_Base2Log(Cba_ObjFinNum(p, iObj) - 1);
int iFonIn = Cba_ObjFinFon(p, iObj, 0);
int iFonOut = Cba_ObjFon0(p, iObj);
// function [15:0] res;
Vec_StrPrintStr( vStr, " function " );
Cba_ManWriteFonRange( p, iFonOut );
Vec_StrPrintStr( vStr, "_func_" );
Cba_ManWriteFonName( p, iFonOut, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
// input [1:0] s;
Vec_StrPrintStr( vStr, " input " );
Cba_ManWriteFonRange( p, iFonIn );
Vec_StrPrintStr( vStr, "s;\n" );
// input [15:0] d0, d1, d2, d3;
Vec_StrPrintStr( vStr, " input " );
Cba_ManWriteFonRange( p, iFonOut );
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
{
if ( i == 0 ) continue;
Vec_StrPrintF( vStr, "%sd%d", i > 1 ? ", " : "", i-1 );
}
Vec_StrPrintStr( vStr, ";\n" );
// casez (s)
Vec_StrPrintStr( vStr, " casez(s)" );
if ( fUseSel )
Vec_StrPrintStr( vStr, " // synopsys full_case parallel_case" );
Vec_StrPrintStr( vStr, "\n" );
// 2'b00: res = b[15:0];
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
{
if ( i == 0 ) continue;
Vec_StrPrintF( vStr, " %d\'b", nBits );
if ( fUseSel )
{
Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + nBits, '?' );
Vec_StrWriteEntry( vStr, Vec_StrSize(vStr) - i, '1' );
}
else
{
for ( k = nBits-1; k >= 0; k-- )
Vec_StrPrintNum( vStr, ((i-1) >> k) & 1 );
}
Vec_StrPrintStr( vStr, ": _func_" );
Cba_ManWriteFonName( p, iFonOut, 0, 0 );
Vec_StrPrintF( vStr, " = d%d;\n", i-1 );
}
Vec_StrPrintStr( vStr, " endcase\n" );
Vec_StrPrintStr( vStr, " endfunction\n" );
// assign z = res(a, b, s);
if ( Vec_BitEntry(vPoFons, iFonOut) )
Vec_StrPrintStr( vStr, " assign " );
else
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFonOut );
}
Cba_ManWriteFonName( p, iFonOut, fInlineConcat, 0 );
Vec_StrPrintStr( vStr, " = _func_" );
Cba_ManWriteFonName( p, iFonOut, 0, 0 );
Vec_StrPrintStr( vStr, " ( " );
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i )
{
Vec_StrPrintStr( vStr, i ? ", " : "" );
Cba_ManWriteFonName( p, iFon, fInlineConcat, 0 );
}
Vec_StrPrintStr( vStr, " );" );
}
else if ( Type == CBA_BOX_DEC )
{
int iFonIn = Cba_ObjFinFon(p, iObj, 0);
int iFonOut = Cba_ObjFon0(p, iObj);
int nBitsIn = Cba_FonRangeSize(p, iFonIn);
int nBitsOut = Cba_FonRangeSize(p, iFonOut);
assert( (1 << nBitsIn) == nBitsOut );
// function [15:0] res;
Vec_StrPrintStr( vStr, " function " );
Cba_ManWriteFonRange( p, iFonOut );
Vec_StrPrintStr( vStr, "_func_" );
Cba_ManWriteFonName( p, iFonOut, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
// input [1:0] i;
Vec_StrPrintStr( vStr, " input " );
Cba_ManWriteFonRange( p, iFonIn );
Vec_StrPrintStr( vStr, "i;\n" );
// casez (i)
Vec_StrPrintStr( vStr, " casez(i)\n" );
// 2'b00: res = 4'b0001;
for ( i = 0; i < (1 << nBitsIn); i++ )
{
Vec_StrPrintF( vStr, " %d\'b", nBitsIn );
for ( k = nBitsIn-1; k >= 0; k-- )
Vec_StrPrintNum( vStr, (i >> k) & 1 );
Vec_StrPrintStr( vStr, ": _func_" );
Cba_ManWriteFonName( p, iFonOut, 0, 0 );
Vec_StrPrintF( vStr, " = %d\'b%0*d;\n", nBitsOut, nBitsOut, 0 );
Vec_StrWriteEntry( vStr, Vec_StrSize(vStr) - i - 3, '1' );
}
Vec_StrPrintStr( vStr, " endcase\n" );
Vec_StrPrintStr( vStr, " endfunction\n" );
// assign z = res(i, o);
if ( Vec_BitEntry(vPoFons, iFonOut) )
Vec_StrPrintStr( vStr, " assign " );
else
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFonOut );
}
Cba_ManWriteFonName( p, iFonOut, fInlineConcat, 0 );
Vec_StrPrintStr( vStr, " = _func_" );
Cba_ManWriteFonName( p, iFonOut, 0, 0 );
Vec_StrPrintStr( vStr, " ( " );
Cba_ManWriteFonName( p, iFonIn, fInlineConcat, 0 );
Vec_StrPrintStr( vStr, " );" );
}
else if ( Type == CBA_BOX_DFFRS || Type == CBA_BOX_LATCHRS )
{
int fUseFlop = Type == CBA_BOX_DFFRS;
int iFonQ = Cba_ObjFon0(p, iObj);
int iFonD = Cba_ObjFinFon(p, iObj, 0);
int iFonSet = Cba_ObjFinFon(p, iObj, 1);
int iFonRst = Cba_ObjFinFon(p, iObj, 2);
int iFonC = Cba_ObjFinFon(p, iObj, 3);
int Range = Cba_FonRangeSize( p, iFonQ );
assert( Cba_FonRangeSize(p, iFonSet) == 1 && Cba_FonRangeSize(p, iFonRst) == 1 );
// reg [3:0] Q;
Vec_StrPrintStr( vStr, " reg " );
Cba_ManWriteFonRange( p, iFonQ );
Cba_ManWriteFonName( p, iFonQ, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
// always @(posedge C or posedge PRE)
Vec_StrPrintStr( vStr, " always @(" );
if ( fUseFlop )
Vec_StrPrintStr( vStr, "posedge " );
Cba_ManWriteFonName( p, iFonC, 0, 0 );
if ( !fUseFlop )
{
Vec_StrPrintStr( vStr, " or " );
Cba_ManWriteFonName( p, iFonD, 0, 0 );
}
if ( iFonSet > 0 )
{
Vec_StrPrintStr( vStr, " or " );
if ( fUseFlop )
Vec_StrPrintStr( vStr, "posedge " );
Cba_ManWriteFonName( p, iFonSet, 0, 0 );
}
if ( iFonRst > 0 )
{
Vec_StrPrintStr( vStr, " or " );
if ( fUseFlop )
Vec_StrPrintStr( vStr, "posedge " );
Cba_ManWriteFonName( p, iFonRst, 0, 0 );
}
Vec_StrPrintStr( vStr, ")\n" );
// if (Set) Q <= 4'b1111;
if ( iFonSet > 0 )
{
Vec_StrPrintStr( vStr, " if (" );
Cba_ManWriteFonName( p, iFonSet, 0, 0 );
Vec_StrPrintStr( vStr, ") " );
Cba_ManWriteFonName( p, iFonQ, 0, 0 );
Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " );
// value 1
Vec_StrPrintNum( vStr, Range );
Vec_StrPrintStr( vStr, "\'b" );
Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + Range, '1' );
Vec_StrPrintStr( vStr, ";\n" );
// Vec_StrPrintF( vStr, "\'b1" );
}
if ( iFonRst > 0 )
{
Vec_StrPrintStr( vStr, iFonSet > 0 ? " else if (" : " if (" );
Cba_ManWriteFonName( p, iFonRst, 0, 0 );
Vec_StrPrintStr( vStr, ") " );
Cba_ManWriteFonName( p, iFonQ, 0, 0 );
Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " );
// value 0
Vec_StrPrintNum( vStr, Range );
Vec_StrPrintStr( vStr, "\'b" );
Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + Range, '0' );
Vec_StrPrintStr( vStr, ";\n" );
// Vec_StrPrintF( vStr, "\'b0" );
}
Vec_StrPrintStr( vStr, (iFonSet > 0 || iFonRst > 0) ? " else " : " " );
if ( !fUseFlop )
{
Vec_StrPrintStr( vStr, " if (" );
Cba_ManWriteFonName( p, iFonC, 0, 0 );
Vec_StrPrintStr( vStr, ") " );
}
Cba_ManWriteFonName( p, iFonQ, 0, 0 );
Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " );
Cba_ManWriteFonName( p, iFonD, fInlineConcat, 0 );
Vec_StrPrintStr( vStr, ";" );
}
else if ( Type == CBA_BOX_DFFCPL )
{
// CPL_FF#32 inst_reg( .d(s1), .arstval(s2), .arst(s3), .clk(s4), .q(s5), .qbar(s6) );
int iFon0 = Cba_ObjFon0(p, iObj);
int iFon1 = Cba_ObjFon(p, iObj, 1);
int Range = Cba_FonRangeSize( p, iFon0 );
if ( !Vec_BitEntry(vPoFons, iFon0) )
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFon0 );
Cba_ManWriteFonName( p, iFon0, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
}
if ( !Vec_BitEntry(vPoFons, iFon1) && Cba_FonName(p, iFon1) )
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFon1 );
Cba_ManWriteFonName( p, iFon1, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
}
Vec_StrPrintStr( vStr, " CPL_FF" );
if ( Range > 1 )
Vec_StrPrintF( vStr, "#%d", Range );
Vec_StrPrintStr( vStr, " " );
if ( Cba_ObjName(p, iObj) )
Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
Vec_StrPrintStr( vStr, " ( .d(" );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, "), .arstval(" );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, "), .arst(" );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, "), .clk(" );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 3), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, "), .q(" );
Cba_ManWriteFonName( p, iFon0, fInlineConcat, 0 );
Vec_StrPrintStr( vStr, "), .qbar(" );
if ( Cba_FonName(p, iFon1) )
Cba_ManWriteFonName( p, iFon1, fInlineConcat, 0 );
Vec_StrPrintStr( vStr, ") );" );
}
else if ( Type == CBA_BOX_ADD )
{
int iFon0 = Cba_ObjFon0(p, iObj);
int iFon1 = Cba_ObjFon(p, iObj, 1);
// write outputs
if ( Cba_FonName(p, iFon1) )
{
if ( !Vec_BitEntry(vPoFons, iFon0) )
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFon0 );
Cba_ManWriteFonName( p, iFon0, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
}
if ( !Vec_BitEntry(vPoFons, iFon1) )
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFon1 );
Cba_ManWriteFonName( p, iFon1, 0, 0 );
Vec_StrPrintStr( vStr, ";\n" );
}
Vec_StrPrintStr( vStr, " assign {" );
Cba_ManWriteFonName( p, iFon1, 0, 0 );
Vec_StrPrintStr( vStr, ", " );
Cba_ManWriteFonName( p, iFon0, 0, 0 );
Vec_StrPrintStr( vStr, "} = " );
}
else
{
if ( Vec_BitEntry(vPoFons, iFon0) )
Vec_StrPrintStr( vStr, " assign " );
else
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, iFon0 );
}
Cba_ManWriteFonName( p, iFon0, 0, 0 );
Vec_StrPrintStr( vStr, " = " );
}
// write carry-in
if ( Cba_ObjFinFon(p, iObj, 0) && Cba_ObjFinFon(p, iObj, 0) != Cba_FonFromConst(1) )
{
Vec_StrPush( vStr, ' ' );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
Vec_StrPush( vStr, ' ' );
Vec_StrPrintStr( vStr, "+" );
}
Vec_StrPush( vStr, ' ' );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
Vec_StrPush( vStr, ' ' );
Vec_StrPrintStr( vStr, "+" );
Vec_StrPush( vStr, ' ' );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 );
Vec_StrPush( vStr, ';' );
}
else
{
if ( Vec_BitEntry(vPoFons, Cba_ObjFon0(p, iObj)) )
Vec_StrPrintStr( vStr, " assign " );
else
{
Vec_StrPrintStr( vStr, " wire " );
Cba_ManWriteFonRange( p, Cba_ObjFon0(p, iObj) );
}
Cba_ManWriteFonName( p, Cba_ObjFon0(p, iObj), 0, 0 );
Vec_StrPrintStr( vStr, " = " );
if ( Cba_ObjIsConcat(p, iObj) )
Cba_ManWriteConcat( p, iObj );
else if ( Type == CBA_BOX_MUX )
{
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, " ? " );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, " : " );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 );
}
else if ( Type == CBA_BOX_ROTL || Type == CBA_BOX_ROTR )
{
// wire [27:0] s4960 = (s57 >> 17) | (s57 << 11);
int Range = Cba_FonRangeSize( p, Cba_ObjFon0(p, iObj) );
int iFinFon1 = Cba_ObjFinFon(p, iObj, 1);
Vec_StrPush( vStr, '(' );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, Type == CBA_BOX_ROTL ? " << " : " >> " );
if ( Cba_FonIsConst(iFinFon1) )
Vec_StrPrintNum( vStr, Cba_FonConst(iFinFon1) );
else
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, ") | (" );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
Vec_StrPrintStr( vStr, Type == CBA_BOX_ROTL ? " >> " : " << " );
if ( Cba_FonIsConst(iFinFon1) )
Vec_StrPrintNum( vStr, Range - Cba_FonConst(iFinFon1) );
else
{
Vec_StrPush( vStr, '(' );
Vec_StrPrintNum( vStr, Range );
Vec_StrPrintStr( vStr, " - " );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
Vec_StrPush( vStr, ')' );
}
Vec_StrPush( vStr, ')' );
}
else if ( Type == CBA_BOX_LTHAN )
{
int fLessThan = (Cba_ObjFinFon(p, iObj, 0) == Cba_FonFromConst(1)); // const0
Vec_StrPush( vStr, ' ' );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
Vec_StrPush( vStr, ' ' );
Vec_StrPrintStr( vStr, fLessThan ? "<" : "<=" );
Vec_StrPush( vStr, ' ' );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 );
}
else if ( Cba_TypeIsUnary((Cba_ObjType_t)Type) )
{
Vec_StrPrintStr( vStr, Cba_NtkTypeName(p, Type) );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
}
else if ( Cba_NtkTypeName(p, Type) ) // binary operation
{
int fCompl = (Type == CBA_BOX_NAND || Type == CBA_BOX_NOR || Type == CBA_BOX_XNOR);
if ( fCompl )
Vec_StrPrintStr( vStr, "!(" );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 );
Vec_StrPush( vStr, ' ' );
Vec_StrPrintStr( vStr, Cba_NtkTypeName(p, Type) );
Vec_StrPush( vStr, ' ' );
Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 );
if ( fCompl )
Vec_StrPrintStr( vStr, ")" );
}
else // unknown
{
char * pName = Cba_FonGetName(p, Cba_ObjFon0(p, iObj));
Vec_StrPrintStr( vStr, "<unknown operator>" );
printf( "Cba_ManWriteVerilog(): In module \"%s\", cannot write object \"%s\" with output name \"%s\".\n", Cba_NtkName(p), Cba_ObjGetName(p, iObj), pName );
}
Vec_StrPush( vStr, ';' );
}
// write attributes
Status = Cba_ManWriteLineFile( p, iObj, FileAttr, LineAttr );
if ( !Cba_ObjIsBoxUser(p, iObj) && Cba_ObjName(p, iObj) )
{
if ( !Status )
Vec_StrPrintStr( vStr, " //" );
Vec_StrPrintStr( vStr, " name=" );
Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
}
Vec_StrPush( vStr, '\n' );
}
// write remaining outputs
Cba_NtkForEachPo( p, iObj, i )
{
iFon = Cba_ObjFinFon(p, iObj, 0);
if ( !iFon || (!Cba_FonIsConst(iFon) && Cba_FonName(p, iFon) == Cba_ObjName(p, iObj)) ) // already written
continue;
Vec_StrPrintStr( vStr, " assign " );
Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) );
Vec_StrPrintStr( vStr, " = " );
Cba_ManWriteFonName( p, iFon, fInlineConcat, 0 );
Vec_StrPush( vStr, ';' );
Vec_StrPush( vStr, '\n' );
}
Vec_StrPrintStr( vStr, "\n" );
Vec_StrPrintStr( vStr, "endmodule\n\n" );
Vec_BitFree( vPoFons );
}
void Cba_ManWriteVerilog( char * pFileName, Cba_Man_t * p, int fInlineConcat )
{
Cba_Ntk_t * pNtk; int i;
// check the library
if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() )
{
printf( "Genlib library used in the mapped design is not longer a current library.\n" );
return;
}
Cba_ManCreatePrimMap( p->pTypeNames );
// derive the stream
p->nOpens = 1;
Vec_StrClear( &p->vOut );
Vec_StrClear( &p->vOut2 );
Vec_StrPrintStr( &p->vOut, "// Design \"" );
Vec_StrPrintStr( &p->vOut, Cba_ManName(p) );
Vec_StrPrintStr( &p->vOut, "\" written via CBA package in ABC on " );
Vec_StrPrintStr( &p->vOut, Extra_TimeStamp() );
Vec_StrPrintStr( &p->vOut, "\n\n" );
Cba_ManForEachNtk( p, pNtk, i )
Cba_ManWriteVerilogNtk( pNtk, fInlineConcat );
// dump into file
if ( Vec_StrSize(&p->vOut) > 0 )
{
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
printf( "Cannot open file \"%s\" for writing.\n", pFileName );
else
{
fwrite( Vec_StrArray(&p->vOut), 1, Vec_StrSize(&p->vOut), pFile );
fclose( pFile );
}
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END