diff --git a/Changes b/Changes index bf631cdd0..d75b43b38 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,7 @@ Verilator 5.027 devel * Support conditional constraints (#5245). [Arkadiusz Kozdra, Antmicro Ltd.] * Add `--compiler-include` for additional C++ includes (#5139) (#5202). [Bartłomiej Chmiel, Antmicro Ltd.] * Add `--emit-accessors` (#5182) (#5227). [Ryan Ziegler] +* Add suggestions on misspelled PLI functions. * Fix fusing macro arguments to not ignore whitespace (#5061). [Tudor Timi] * Fix classes/modules of case-similar names (#5109). [Arkadiusz Kozdra] * Fix mis-removing $value$plusargs calls (#5127) (#5137). [Seth Pellegrino] diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 7f1e53667..a76e3dbd9 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -67,6 +67,7 @@ #include "V3Graph.h" #include "V3MemberMap.h" +#include "V3Parse.h" #include "V3String.h" #include "V3SymTable.h" @@ -3355,8 +3356,13 @@ class LinkDotResolveVisitor final : public VNVisitor { VL_DO_DANGLING(nodep->deleteTree(), nodep); return; } else { + VSpellCheck speller; + V3Parse::candidatePli(&speller); + const string suggest = speller.bestCandidateMsg(nodep->prettyName()); nodep->v3error( - "Unsupported or unknown PLI call: " << nodep->prettyNameQ()); + "Unsupported or unknown PLI call: " + << nodep->prettyNameQ() << '\n' + << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } } else { const string suggest = m_statep->suggestSymFallback( diff --git a/src/V3Parse.h b/src/V3Parse.h index 852af5328..3b2457ec1 100644 --- a/src/V3Parse.h +++ b/src/V3Parse.h @@ -49,6 +49,9 @@ public: // Push preprocessed text to the lexer static void ppPushText(V3ParseImp* impp, const string& text) VL_MT_DISABLED; + + // Suggest PLI functions for spell check + static void candidatePli(VSpellCheck* spellerp) VL_MT_DISABLED; }; #endif // Guard diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 6df87f7f5..5938335eb 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -63,6 +63,17 @@ const char* V3ParseImp::tokenName(int token) { #endif } +void V3ParseImp::candidatePli(VSpellCheck* spellerp) { +#if !YYERROR_VERBOSE +#error "Need lex token names" +#endif + for (int i = 0; yytname[i]; ++i) { + if (yytname[i][0] != '\"') continue; + if (yytname[i][1] != '$') continue; + spellerp->pushCandidate(string{yytname[i]}.substr(1, strlen(yytname[i]) - 2)); + } +} + void V3ParseImp::parserClear() { // Clear up any dynamic memory V3Parser required VARDTYPE(nullptr); diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 37c107e8a..2e2011c1c 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -693,3 +693,4 @@ void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrar void V3Parse::ppPushText(V3ParseImp* impp, const string& text) { if (text != "") impp->ppPushText(text); } +void V3Parse::candidatePli(VSpellCheck* spellerp) { V3ParseImp::candidatePli(spellerp); } diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 856f06c1e..c3f8dd95c 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -294,6 +294,7 @@ public: void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary, const string& errmsg) VL_MT_DISABLED; void dumpInputsFile() VL_MT_DISABLED; + static void candidatePli(VSpellCheck* spellerp) VL_MT_DISABLED; private: void preprocDumps(std::ostream& os); diff --git a/test_regress/t/t_pli_bad.out b/test_regress/t/t_pli_bad.out index b1f752c4f..162d3ed20 100644 --- a/test_regress/t/t_pli_bad.out +++ b/test_regress/t/t_pli_bad.out @@ -10,4 +10,12 @@ %Error: t/t_pli_bad.v:13:11: Unsupported or unknown PLI call: '$unknown_pli_function' 13 | i = $unknown_pli_function("arg", i); | ^~~~~~~~~~~~~~~~~~~~~ +%Error: t/t_pli_bad.v:15:7: Unsupported or unknown PLI call: '$sformatff' + : ... Suggested alternative: '$sformatf' + 15 | $sformatff(); + | ^~~~~~~~~~ +%Error: t/t_pli_bad.v:16:11: Unsupported or unknown PLI call: '$sformatff' + : ... Suggested alternative: '$sformatf' + 16 | i = $sformatff(); + | ^~~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_pli_bad.v b/test_regress/t/t_pli_bad.v index 5ae542377..cd8ba2d87 100644 --- a/test_regress/t/t_pli_bad.v +++ b/test_regress/t/t_pli_bad.v @@ -11,6 +11,10 @@ module t; $unknown_pli_task("arg", i); i = $unknown_pli_function; i = $unknown_pli_function("arg", i); + + $sformatff(); // Typo + i = $sformatff(); // Typo + $stop; end endmodule