From f9af41ba1bb6dff04e888c285052a9e1ec6d6456 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 31 Oct 2020 15:08:40 -0700 Subject: Adding an option to write Verilog with LUT instances. --- src/base/io/ioWriteVerilog.c | 177 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) (limited to 'src/base/io/ioWriteVerilog.c') diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index 2e481324..f524690f 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -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<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<> 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 /// //////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 2325cd77e3d6072b335dd551b3eda2ef20eaa92c Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 31 Oct 2020 16:14:52 -0700 Subject: Adding an option to write Verilog with LUT instances (compiler warnings). --- src/base/io/ioWriteVerilog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/base/io/ioWriteVerilog.c') diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index f524690f..ad49e93a 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -718,7 +718,7 @@ void Io_WriteVerilogObjectsLut( FILE * pFile, Abc_Ntk_t * pNtk, int 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, "%0*x", 1<<(nLutSize-2), Abc_InfoMask(1 << nLutSize) & (unsigned)Truth ); fprintf( pFile, ") lut_%0*d ( {", nDigits, Counter++ ); for ( k = nLutSize - 1; k >= Abc_ObjFaninNum(pObj); k-- ) fprintf( pFile, "%*s, ", Length, "1\'b0" ); @@ -804,7 +804,7 @@ void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize ) } if ( Counter ) { - printf( "In total, %d internal logic nodes exceeded the fanout count limit.\n", Counter ); + printf( "In total, %d internal logic nodes exceed the fanin count limit. Verilog is not written.\n", Counter ); return; } -- cgit v1.2.3 From de71e5f61038748b59bcbb2bf6f0c8666b45190a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 26 Apr 2021 18:52:44 -0700 Subject: Passing node labels. --- src/base/io/ioWriteVerilog.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/base/io/ioWriteVerilog.c') diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index ad49e93a..4c55b599 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -567,6 +567,14 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin))); // write the formula Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0, fOnlyAnds ); + if ( pObj->fPersist ) + { + Abc_Obj_t * pFan0 = Abc_ObjFanin0(Abc_ObjFanin(pObj, 0)); + Abc_Obj_t * pFan1 = Abc_ObjFanin0(Abc_ObjFanin(pObj, 1)); + int Cond = Abc_ObjIsNode(pFan0) && Abc_ObjIsNode(pFan1) && !pFan0->fPersist && !pFan1->fPersist; + fprintf( pFile, "; // MUXF7 %s\n", Cond ? "":"to be legalized" ); + } + else fprintf( pFile, ";\n" ); // clear the input names Abc_ObjForEachFanin( pObj, pFanin, k ) -- cgit v1.2.3 From 0ce11851bcb364abfd5d65685ab779faed4398ec Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 16 May 2021 20:33:53 -0700 Subject: Updating LUT synthesis code. --- src/base/io/ioWriteVerilog.c | 85 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 11 deletions(-) (limited to 'src/base/io/ioWriteVerilog.c') diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index 4c55b599..e05aed2e 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -639,10 +639,8 @@ int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ) 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')) ) + int i, Length = strlen(pName); + if ( pName[0] < '0' || pName[0] > '9' ) { for ( i = 0; i < Length; i++ ) if ( !((pName[i] >= 'a' && pName[i] <= 'z') || @@ -679,7 +677,39 @@ void Io_WriteLutModule( FILE * pFile, int nLutSize ) fprintf( pFile, " assign out = TT[in];\n" ); fprintf( pFile, "endmodule\n\n" ); } -void Io_WriteVerilogObjectsLut( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize ) +void Io_WriteFixedModules( FILE * pFile ) +{ + fprintf( pFile, "module LUT6 #( parameter INIT = 64\'h0000000000000000 ) (\n" ); + fprintf( pFile, " output O,\n" ); + fprintf( pFile, " input I0,\n" ); + fprintf( pFile, " input I1,\n" ); + fprintf( pFile, " input I2,\n" ); + fprintf( pFile, " input I3,\n" ); + fprintf( pFile, " input I4,\n" ); + fprintf( pFile, " input I5\n" ); + fprintf( pFile, ");\n" ); + fprintf( pFile, " assign O = INIT[ {I5, I4, I3, I2, I1, I0} ];\n" ); + fprintf( pFile, "endmodule\n\n" ); + + fprintf( pFile, "module MUXF7 (\n" ); + fprintf( pFile, " output O,\n" ); + fprintf( pFile, " input I0,\n" ); + fprintf( pFile, " input I1,\n" ); + fprintf( pFile, " input S\n" ); + fprintf( pFile, ");\n" ); + fprintf( pFile, " assign O = S ? I1 : I0;\n" ); + fprintf( pFile, "endmodule\n\n" ); + + fprintf( pFile, "module MUXF8 (\n" ); + fprintf( pFile, " output O,\n" ); + fprintf( pFile, " input I0,\n" ); + fprintf( pFile, " input I1,\n" ); + fprintf( pFile, " input S\n" ); + fprintf( pFile, ");\n" ); + fprintf( pFile, " assign O = S ? I1 : I0;\n" ); + fprintf( pFile, "endmodule\n\n" ); +} +void Io_WriteVerilogObjectsLut( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fFixed ) { Abc_Ntk_t * pNtkBox; Abc_Obj_t * pObj, * pTerm; @@ -719,6 +749,34 @@ void Io_WriteVerilogObjectsLut( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize ) // write LUT instances nDigits = Abc_Base10Log( Abc_NtkNodeNum(pNtk) ); Counter = 0; + if ( fFixed ) + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( pObj->fPersist ) + { + int One = Abc_ObjFanin0(Abc_ObjFanin(pObj, 1))->fPersist && Abc_ObjFanin0(Abc_ObjFanin(pObj, 2))->fPersist; + fprintf( pFile, " MUXF%d ", 7+One ); + fprintf( pFile, " mux_%0*d (", nDigits, Counter++ ); + fprintf( pFile, " %*s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + for ( k = Abc_ObjFaninNum(pObj) - 1; k >= 0; k-- ) + fprintf( pFile, ", %*s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin(pObj, k))) ); + fprintf( pFile, " );\n" ); + } + else + { + word Truth = Abc_SopToTruth( (char *)pObj->pData, Abc_ObjFaninNum(pObj) ); + fprintf( pFile, " LUT6 #(64\'h" ); + fprintf( pFile, "%08x%08x", (unsigned)(Truth >> 32), (unsigned)Truth ); + fprintf( pFile, ") lut_%0*d (", nDigits, Counter++ ); + fprintf( pFile, " %*s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + for ( k = 0; k < Abc_ObjFaninNum(pObj); k++ ) + fprintf( pFile, ", %*s", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin(pObj, k))) ); + for ( ; k < 6; k++ ) + fprintf( pFile, ", %*s", Length, "1\'b0" ); + fprintf( pFile, " );\n" ); + } + } + else Abc_NtkForEachNode( pNtk, pObj, i ) { word Truth = Abc_SopToTruth( (char *)pObj->pData, Abc_ObjFaninNum(pObj) ); @@ -735,7 +793,7 @@ void Io_WriteVerilogObjectsLut( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize ) fprintf( pFile, "}, %*s );\n", Length, Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); } } -void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize ) +void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize, int fFixed ) { // write inputs and outputs // fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); @@ -786,7 +844,7 @@ void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize ) fprintf( pFile, ";\n\n" ); } // write nodes - Io_WriteVerilogObjectsLut( pFile, pNtk, nLutSize ); + Io_WriteVerilogObjectsLut( pFile, pNtk, nLutSize, fFixed ); // write registers if ( Abc_NtkLatchNum(pNtk) > 0 ) { @@ -797,7 +855,7 @@ void Io_WriteVerilogLutInt( FILE * pFile, Abc_Ntk_t * pNtk, int nLutSize ) // finalize the file fprintf( pFile, "\nendmodule\n\n" ); } -void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize ) +void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int fFixed, int fNoModules ) { FILE * pFile; Abc_Ntk_t * pNtkTemp; @@ -827,11 +885,16 @@ void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize ) // 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 ); - + if ( !fNoModules ) + { + if ( fFixed ) + Io_WriteFixedModules( pFile ); + else + Io_WriteLutModule( pFile, nLutSize ); + } pNtkTemp = Abc_NtkToNetlist( pNtk ); Abc_NtkToSop( pNtkTemp, -1, ABC_INFINITY ); - Io_WriteVerilogLutInt( pFile, pNtkTemp, nLutSize ); + Io_WriteVerilogLutInt( pFile, pNtkTemp, nLutSize, fFixed ); Abc_NtkDelete( pNtkTemp ); fprintf( pFile, "\n" ); -- cgit v1.2.3