mirror of https://github.com/YosysHQ/abc.git
Dumping LUT-mapped networks in Vivado-readable Verilog.
This commit is contained in:
parent
8475386dfa
commit
3cdb1c4c3b
|
|
@ -1292,12 +1292,201 @@ static void GiaHie_DumpInterfaceAssigns( Gia_Man_t * p, char * pFileName )
|
|||
fclose( pFile );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Dumps mapped AIG as LUT6 instances in Verilog]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static void GiaHie_DumpMappedLuts( Gia_Man_t * p, char * pFileName )
|
||||
{
|
||||
int i, k, iFanin, nLutSize, nDigits;
|
||||
FILE * pFile;
|
||||
Vec_Int_t * vLeaves;
|
||||
word * pTruth;
|
||||
Gia_Obj_t * pObj;
|
||||
|
||||
// Check if AIG is mapped
|
||||
if ( !Gia_ManHasMapping(p) )
|
||||
{
|
||||
printf( "Cannot write LUT-based Verilog because AIG is not mapped.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
pFile = fopen( pFileName, "wb" );
|
||||
if ( pFile == NULL )
|
||||
{
|
||||
printf( "Cannot open output file \"%s\".\n", pFileName );
|
||||
return;
|
||||
}
|
||||
|
||||
nDigits = Abc_Base10Log( Gia_ManObjNum(p) );
|
||||
if ( nDigits < 3 )
|
||||
nDigits = 3;
|
||||
|
||||
// Write header
|
||||
fprintf( pFile, "`timescale 1ns/1ps\n\n" );
|
||||
|
||||
// Write LUT module definitions for Yosys compatibility (compact version)
|
||||
fprintf( pFile, "module LUT2 #( parameter INIT = 04\'h0 ) ( output O, input I0, I1 );\n" );
|
||||
fprintf( pFile, " assign O = INIT[ {I1, I0} ];\n" );
|
||||
fprintf( pFile, "endmodule\n" );
|
||||
|
||||
fprintf( pFile, "module LUT3 #( parameter INIT = 08\'h0 ) ( output O, input I0, I1, I2 );\n" );
|
||||
fprintf( pFile, " assign O = INIT[ {I2, I1, I0} ];\n" );
|
||||
fprintf( pFile, "endmodule\n" );
|
||||
|
||||
fprintf( pFile, "module LUT4 #( parameter INIT = 16\'h0 ) ( output O, input I0, I1, I2, I3 );\n" );
|
||||
fprintf( pFile, " assign O = INIT[ {I3, I2, I1, I0} ];\n" );
|
||||
fprintf( pFile, "endmodule\n" );
|
||||
|
||||
fprintf( pFile, "module LUT5 #( parameter INIT = 32\'h0 ) ( output O, input I0, I1, I2, I3, I4 );\n" );
|
||||
fprintf( pFile, " assign O = INIT[ {I4, I3, I2, I1, I0} ];\n" );
|
||||
fprintf( pFile, "endmodule\n" );
|
||||
|
||||
fprintf( pFile, "module LUT6 #( parameter INIT = 64\'h0 ) ( output O, input I0, I1, I2, I3, I4, I5 );\n" );
|
||||
fprintf( pFile, " assign O = INIT[ {I5, I4, I3, I2, I1, I0} ];\n" );
|
||||
fprintf( pFile, "endmodule\n\n" );
|
||||
|
||||
// Write main module
|
||||
fprintf( pFile, "module " );
|
||||
GiaHie_DumpModuleName( pFile, p->pName );
|
||||
fprintf( pFile, " (\n" );
|
||||
GiaHie_DumpPortDecls( p, pFile );
|
||||
fprintf( pFile, "\n);\n\n" );
|
||||
|
||||
// Declare wires for inputs (using object IDs like regular &write_ver)
|
||||
if ( Gia_ManCiNum(p) )
|
||||
{
|
||||
fprintf( pFile, " wire " );
|
||||
GiaHie_WriteObjRange( pFile, p, 0, Gia_ManCiNum(p), nDigits, 7, 4, 0, 1 );
|
||||
fprintf( pFile, ";\n\n" );
|
||||
GiaHie_DumpInputAssigns( p, pFile, nDigits );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
|
||||
// Declare wires for outputs (using object IDs like regular &write_ver)
|
||||
if ( Gia_ManCoNum(p) )
|
||||
{
|
||||
fprintf( pFile, " wire " );
|
||||
GiaHie_WriteObjRange( pFile, p, 0, Gia_ManCoNum(p), nDigits, 7, 4, 0, 0 );
|
||||
fprintf( pFile, ";\n\n" );
|
||||
GiaHie_DumpOutputAssigns( p, pFile, nDigits );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
|
||||
// Declare internal wires for LUT outputs (10 per line)
|
||||
{
|
||||
int nWiresPerLine = 10;
|
||||
int nWireCount = 0;
|
||||
int fFirst = 1;
|
||||
Gia_ManForEachLut( p, i )
|
||||
{
|
||||
if ( nWireCount == 0 )
|
||||
fprintf( pFile, " wire " );
|
||||
if ( !fFirst )
|
||||
fprintf( pFile, ", " );
|
||||
fprintf( pFile, "n%0*d", nDigits, i );
|
||||
fFirst = 0;
|
||||
nWireCount++;
|
||||
if ( nWireCount == nWiresPerLine )
|
||||
{
|
||||
fprintf( pFile, ";\n" );
|
||||
nWireCount = 0;
|
||||
fFirst = 1;
|
||||
}
|
||||
}
|
||||
if ( nWireCount > 0 )
|
||||
fprintf( pFile, ";\n" );
|
||||
}
|
||||
fprintf( pFile, "\n" );
|
||||
|
||||
// Initialize truth table computation
|
||||
vLeaves = Vec_IntAlloc( 6 );
|
||||
Gia_ObjComputeTruthTableStart( p, 6 );
|
||||
|
||||
// Write LUT6 instances
|
||||
Gia_ManForEachLut( p, i )
|
||||
{
|
||||
nLutSize = Gia_ObjLutSize( p, i );
|
||||
|
||||
// Collect LUT inputs
|
||||
Vec_IntClear( vLeaves );
|
||||
Gia_LutForEachFanin( p, i, iFanin, k )
|
||||
Vec_IntPush( vLeaves, iFanin );
|
||||
|
||||
// Compute truth table
|
||||
pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, i), vLeaves );
|
||||
|
||||
// Write LUT instance - use appropriate size LUT based on inputs
|
||||
if ( nLutSize <= 1 )
|
||||
nLutSize = 2; // minimum LUT size is 2
|
||||
|
||||
// Determine INIT width and padding
|
||||
int nInitBits = (1 << nLutSize);
|
||||
unsigned long long truthValue = (nLutSize <= 6) ? pTruth[0] : 0;
|
||||
|
||||
// Mask truth value to the appropriate number of bits
|
||||
if ( nLutSize < 6 )
|
||||
truthValue &= ((1ULL << nInitBits) - 1);
|
||||
|
||||
// Write LUT instance with padding for alignment
|
||||
fprintf( pFile, " (* DONT_TOUCH = \"yes\" *) LUT%d #(", nLutSize );
|
||||
|
||||
// Write INIT parameter with appropriate width and padding aligned to 64-bit width
|
||||
if ( nLutSize == 2 )
|
||||
fprintf( pFile, ".INIT(04'h%01llx )) u_lut%0*d (", truthValue, nDigits, i );
|
||||
else if ( nLutSize == 3 )
|
||||
fprintf( pFile, ".INIT(08'h%02llx )) u_lut%0*d (", truthValue, nDigits, i );
|
||||
else if ( nLutSize == 4 )
|
||||
fprintf( pFile, ".INIT(16'h%04llx )) u_lut%0*d (", truthValue, nDigits, i );
|
||||
else if ( nLutSize == 5 )
|
||||
fprintf( pFile, ".INIT(32'h%08llx )) u_lut%0*d (", truthValue, nDigits, i );
|
||||
else // nLutSize == 6
|
||||
fprintf( pFile, ".INIT(64'h%016llx)) u_lut%0*d (", truthValue, nDigits, i );
|
||||
|
||||
// Write LUT inputs - only the ones actually used by this LUT size
|
||||
for ( k = 0; k < nLutSize; k++ )
|
||||
{
|
||||
iFanin = Vec_IntEntry( vLeaves, k );
|
||||
if ( k > 0 )
|
||||
fprintf( pFile, ", " );
|
||||
fprintf( pFile, ".I%d(n%0*d)", k, nDigits, iFanin );
|
||||
}
|
||||
|
||||
// Write LUT output
|
||||
fprintf( pFile, ", .O(n%0*d));\n", nDigits, i );
|
||||
}
|
||||
|
||||
// Cleanup truth table computation
|
||||
Gia_ObjComputeTruthTableStop( p );
|
||||
Vec_IntFree( vLeaves );
|
||||
|
||||
fprintf( pFile, "\n" );
|
||||
|
||||
// Connect internal nodes to outputs (like regular &write_ver)
|
||||
Gia_ManForEachCo( p, pObj, i )
|
||||
{
|
||||
fprintf( pFile, " assign n%0*d = ", nDigits, Gia_ManCoIdToId(p, i) );
|
||||
GiaHie_PrintObjLit( pFile, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj), nDigits );
|
||||
fprintf( pFile, ";\n" );
|
||||
}
|
||||
|
||||
fprintf( pFile, "\nendmodule\n" );
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
|
@ -1314,6 +1503,30 @@ void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fV
|
|||
GiaHie_DumpInterfaceAssigns( pGia, pFileName );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Writes mapped AIG as LUT6-based Verilog]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Gia_WriteMappedVerilog( char * pFileName, Gia_Man_t * pGia, int fVerbose )
|
||||
{
|
||||
(void)fVerbose;
|
||||
if ( pFileName == NULL || pGia == NULL )
|
||||
return;
|
||||
if ( !Gia_ManHasMapping(pGia) )
|
||||
{
|
||||
printf( "Cannot write LUT-based Verilog because AIG is not mapped.\n" );
|
||||
return;
|
||||
}
|
||||
GiaHie_DumpMappedLuts( pGia, pFileName );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -35109,15 +35109,17 @@ usage:
|
|||
int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose );
|
||||
extern void Gia_WriteMappedVerilog( char * pFileName, Gia_Man_t * pGia, int fVerbose );
|
||||
char * pFileSpec = NULL;
|
||||
Abc_Ntk_t * pNtkSpec = NULL;
|
||||
char * pFileName;
|
||||
char ** pArgvNew;
|
||||
int c, nArgcNew;
|
||||
int fUseGates = 0;
|
||||
int fUseLuts = 0;
|
||||
int fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Sgvh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Sglvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -35133,6 +35135,9 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
case 'g':
|
||||
fUseGates ^= 1;
|
||||
break;
|
||||
case 'l':
|
||||
fUseLuts ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
|
|
@ -35157,7 +35162,21 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_Print( -1, "There is no AIG to write.\n" );
|
||||
return 1;
|
||||
}
|
||||
Gia_WriteVerilog( pFileName, pAbc->pGia, fUseGates, fVerbose );
|
||||
// Check if we should write LUT-based Verilog
|
||||
if ( fUseLuts || (Gia_ManHasMapping(pAbc->pGia) && !fUseGates) )
|
||||
{
|
||||
if ( !Gia_ManHasMapping(pAbc->pGia) )
|
||||
{
|
||||
Abc_Print( -1, "Cannot write LUT-based Verilog because AIG is not mapped.\n" );
|
||||
Abc_Print( -1, "Use \"&if\" to map the AIG first, or omit the -l flag.\n" );
|
||||
return 1;
|
||||
}
|
||||
Gia_WriteMappedVerilog( pFileName, pAbc->pGia, fVerbose );
|
||||
}
|
||||
else
|
||||
{
|
||||
Gia_WriteVerilog( pFileName, pAbc->pGia, fUseGates, fVerbose );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -35179,13 +35198,15 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
Abc_Print( -2, "usage: &write_ver [-S <file>] [-gvh] <file>\n" );
|
||||
Abc_Print( -2, "usage: &write_ver [-S <file>] [-glvh] <file>\n" );
|
||||
Abc_Print( -2, "\t writes hierarchical Verilog\n" );
|
||||
Abc_Print( -2, "\t-S file : file name for the original design (required when hierarchy is present)\n" );
|
||||
Abc_Print( -2, "\t-g : toggle output gates vs assign-statements [default = %s]\n", fUseGates? "gates": "assigns" );
|
||||
Abc_Print( -2, "\t-l : write LUT6-based Verilog for mapped AIGs [default = %s]\n", fUseLuts? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : print the command usage\n");
|
||||
Abc_Print( -2, "\t<file> : the file name\n");
|
||||
Abc_Print( -2, "\tNote: When AIG is mapped and -l is not specified, LUT-based output is automatically used.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue