mirror of https://github.com/YosysHQ/abc.git
Adding an option to write Verilog with LUT instances.
This commit is contained in:
parent
73f8b598ac
commit
f9af41ba1b
|
|
@ -2982,14 +2982,27 @@ usage:
|
|||
***********************************************************************/
|
||||
int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv )
|
||||
{
|
||||
extern void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize );
|
||||
char * pFileName;
|
||||
int c, fOnlyAnds = 0;
|
||||
int nLutSize = -1;
|
||||
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Kah" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'K':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nLutSize = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nLutSize < 2 || nLutSize > 6 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'a':
|
||||
fOnlyAnds ^= 1;
|
||||
break;
|
||||
|
|
@ -3017,13 +3030,16 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv )
|
|||
Io_WriteVerilog( pNtkTemp, pFileName, 1 );
|
||||
Abc_NtkDelete( pNtkTemp );
|
||||
}
|
||||
else if ( nLutSize >= 2 && nLutSize <= 6 )
|
||||
Io_WriteVerilogLut( pAbc->pNtkCur, pFileName, nLutSize );
|
||||
else
|
||||
Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG );
|
||||
Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pAbc->Err, "usage: write_verilog [-ah] <file>\n" );
|
||||
fprintf( pAbc->Err, "usage: write_verilog [-K num] [-ah] <file>\n" );
|
||||
fprintf( pAbc->Err, "\t writes the current network in Verilog format\n" );
|
||||
fprintf( pAbc->Err, "\t-K num : write the network using instances of K-LUTs (2 <= K <= %d) [default = not used]\n", 6, nLutSize );
|
||||
fprintf( pAbc->Err, "\t-a : toggle writing expressions with only ANDs (without XORs and MUXes) [default = %s]\n", fOnlyAnds? "yes":"no" );
|
||||
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
|
||||
fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
|
||||
|
|
|
|||
|
|
@ -653,6 +653,183 @@ char * Io_WriteVerilogGetName( char * pName )
|
|||
return Buffer;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Write the network of K-input LUTs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Io_WriteLutModule( FILE * pFile, int nLutSize )
|
||||
{
|
||||
fprintf( pFile, "module lut%d #( parameter TT = %d\'h0 ) ( input [%d:0] in, output out );\n", nLutSize, 1<<nLutSize, nLutSize-1 );
|
||||
fprintf( pFile, " assign out = TT[in];\n" );
|
||||
fprintf( pFile, "endmodule\n\n" );
|
||||
}
|
||||
void Io_WriteVerilogObjectsLut( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize )
|
||||
{
|
||||
Abc_Ntk_t * pNtkBox;
|
||||
Abc_Obj_t * pObj, * pTerm;
|
||||
int i, k, Counter, nDigits, Length = 0;
|
||||
|
||||
// write boxes
|
||||
nDigits = Abc_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) );
|
||||
Counter = 0;
|
||||
Abc_NtkForEachBox( pNtk, pObj, i )
|
||||
{
|
||||
if ( Abc_ObjIsLatch(pObj) )
|
||||
continue;
|
||||
pNtkBox = (Abc_Ntk_t *)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" );
|
||||
}
|
||||
|
||||
// find the longest signal name
|
||||
Abc_NtkForEachNode( pNtk, pObj, i )
|
||||
{
|
||||
Length = Abc_MaxInt( Length, strlen(Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj)))) );
|
||||
Abc_ObjForEachFanin( pObj, pTerm, k )
|
||||
Length = Abc_MaxInt( Length, strlen(Io_WriteVerilogGetName(Abc_ObjName(pTerm))) );
|
||||
}
|
||||
|
||||
// write LUT instances
|
||||
nDigits = Abc_Base10Log( Abc_NtkNodeNum(pNtk) );
|
||||
Counter = 0;
|
||||
Abc_NtkForEachNode( pNtk, pObj, i )
|
||||
{
|
||||
word Truth = Abc_SopToTruth( (char *)pObj->pData, Abc_ObjFaninNum(pObj) );
|
||||
fprintf( pFile, " lut%d #(%d\'h", nLutSize, 1<<nLutSize );
|
||||
if ( nLutSize == 6 )
|
||||
fprintf( pFile, "%08x%08x", (unsigned)(Truth >> 32), (unsigned)Truth );
|
||||
else
|
||||
fprintf( pFile, "%0*x", 1<<(nLutSize-2), Abc_InfoMask(1 << nLutSize) & Truth );
|
||||
fprintf( pFile, ") lut_%0*d ( {", nDigits, Counter++ );
|
||||
for ( k = nLutSize - 1; k >= Abc_ObjFaninNum(pObj); k-- )
|
||||
fprintf( pFile, "%*s, ", Length, "1\'b0" );
|
||||
for ( k = Abc_ObjFaninNum(pObj) - 1; k >= 0; k-- )
|
||||
fprintf( pFile, "%*s%s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin(pObj, k))), k==0 ? "":", " );
|
||||
fprintf( pFile, "}, %*s );\n", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) );
|
||||
}
|
||||
}
|
||||
void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize )
|
||||
{
|
||||
// write inputs and outputs
|
||||
// fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) );
|
||||
fprintf( pFile, "module %s ( ", Io_WriteVerilogGetName(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\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\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\n" );
|
||||
}
|
||||
if ( Io_WriteVerilogWiresCount(pNtk) > 0 )
|
||||
{
|
||||
fprintf( pFile, " wire" );
|
||||
Io_WriteVerilogWires( pFile, pNtk, 4 );
|
||||
fprintf( pFile, ";\n\n" );
|
||||
}
|
||||
// write nodes
|
||||
Io_WriteVerilogObjectsLut( pFile, pNtk, nLutSize );
|
||||
// write registers
|
||||
if ( Abc_NtkLatchNum(pNtk) > 0 )
|
||||
{
|
||||
fprintf( pFile, "\n" );
|
||||
Io_WriteVerilogLatches( pFile, pNtk );
|
||||
}
|
||||
}
|
||||
// finalize the file
|
||||
fprintf( pFile, "\nendmodule\n\n" );
|
||||
}
|
||||
void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize )
|
||||
{
|
||||
FILE * pFile;
|
||||
Abc_Ntk_t * pNtkTemp;
|
||||
Abc_Obj_t * pObj;
|
||||
int i, Counter = 0;
|
||||
Abc_NtkForEachNode( pNtk, pObj, i )
|
||||
if ( Abc_ObjFaninNum(pObj) > nLutSize )
|
||||
{
|
||||
if ( Counter < 3 )
|
||||
printf( "Node \"%s\" has the fanin count (%d) larger than the LUT size (%d).\n", Abc_ObjName(pObj), Abc_ObjFaninNum(pObj), nLutSize );
|
||||
Counter++;
|
||||
}
|
||||
if ( Counter )
|
||||
{
|
||||
printf( "In total, %d internal logic nodes exceeded the fanout count limit.\n", Counter );
|
||||
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" );
|
||||
Io_WriteLutModule( pFile, nLutSize );
|
||||
|
||||
pNtkTemp = Abc_NtkToNetlist( pNtk );
|
||||
Abc_NtkToSop( pNtkTemp, -1, ABC_INFINITY );
|
||||
Io_WriteVerilogLutInt( pFile, pNtkTemp, nLutSize );
|
||||
Abc_NtkDelete( pNtkTemp );
|
||||
|
||||
fprintf( pFile, "\n" );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Reference in New Issue