Author: sstwcw Date: 2023-03-14T03:49:56Z New Revision: a1f8bab9bad7dc7ef5bae518bc3289f4111846f3
URL: https://github.com/llvm/llvm-project/commit/a1f8bab9bad7dc7ef5bae518bc3289f4111846f3 DIFF: https://github.com/llvm/llvm-project/commit/a1f8bab9bad7dc7ef5bae518bc3289f4111846f3.diff LOG: [clang-format] Recognize Verilog always blocks The small `Coverage` test was added because we added the space rule about 2 at signs along with the rule about only 1 of it. We have not fully covered covergroup yet. Reviewed By: MyDeveloperDay, owenpan Differential Revision: https://reviews.llvm.org/D145794 Added: Modified: clang/lib/Format/FormatToken.h clang/lib/Format/TokenAnnotator.cpp clang/lib/Format/UnwrappedLineParser.cpp clang/lib/Format/UnwrappedLineParser.h clang/unittests/Format/FormatTestVerilog.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 70ecf7cacccb2..86bd85c3bbef5 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -1801,6 +1801,13 @@ struct AdditionalKeywords { kw_input, kw_output, kw_sequence))); } + /// Returns whether \p Tok is a Verilog keyword that starts a + /// structured procedure like 'always'. + bool isVerilogStructuredProcedure(const FormatToken &Tok) const { + return Tok.isOneOf(kw_always, kw_always_comb, kw_always_ff, kw_always_latch, + kw_final, kw_forever, kw_initial); + } + bool isVerilogQualifier(const FormatToken &Tok) const { switch (Tok.Tok.getKind()) { case tok::kw_extern: diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index f8ef22736abb7..5362f2f58e1eb 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4348,6 +4348,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, (Left.is(TT_VerilogNumberBase) && Right.is(tok::numeric_constant))) { return false; } + // Don't add spaces between two at signs. Like in a coverage event. + // Don't add spaces between at and a sensitivity list like + // `@(posedge clk)`. + if (Left.is(tok::at) && Right.isOneOf(tok::l_paren, tok::star, tok::at)) + return false; // Add space between the type name and dimension like `logic [1:0]`. if (Right.is(tok::l_square) && Left.isOneOf(TT_VerilogDimensionedTypeName, Keywords.kw_function)) { diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 8576de7b72396..f08a51f93e2ff 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1389,6 +1389,11 @@ void UnwrappedLineParser::parseStructuralElement( } if (Style.isVerilog()) { + if (Keywords.isVerilogStructuredProcedure(*FormatTok)) { + parseForOrWhileLoop(/*HasParens=*/false); + return; + } + // Skip things that can exist before keywords like 'if' and 'case'. while (true) { if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique, @@ -2963,8 +2968,14 @@ void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) { NestedTooDeep.pop_back(); } -void UnwrappedLineParser::parseForOrWhileLoop() { - assert(FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) && +void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) { + assert((FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) || + (Style.isVerilog() && + FormatTok->isOneOf(Keywords.kw_always, Keywords.kw_always_comb, + Keywords.kw_always_ff, Keywords.kw_always_latch, + Keywords.kw_final, Keywords.kw_initial, + Keywords.kw_foreach, Keywords.kw_forever, + Keywords.kw_repeat))) && "'for', 'while' or foreach macro expected"); const bool KeepBraces = !Style.RemoveBracesLLVM || !FormatTok->isOneOf(tok::kw_for, tok::kw_while); @@ -2975,8 +2986,11 @@ void UnwrappedLineParser::parseForOrWhileLoop() { nextToken(); if (Style.isCpp() && FormatTok->is(tok::kw_co_await)) nextToken(); - if (FormatTok->is(tok::l_paren)) + if (HasParens && FormatTok->is(tok::l_paren)) parseParens(); + // Event control. + if (Style.isVerilog()) + parseVerilogSensitivityList(); handleAttributes(); parseLoopBody(KeepBraces, /*WrapRightBrace=*/true); diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 20ea2956058b9..4a48fa856247a 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -166,7 +166,7 @@ class UnwrappedLineParser { FormatToken *parseIfThenElse(IfStmtKind *IfKind, bool KeepBraces = false); void parseTryCatch(); void parseLoopBody(bool KeepBraces, bool WrapRightBrace); - void parseForOrWhileLoop(); + void parseForOrWhileLoop(bool HasParens = true); void parseDoWhile(); void parseLabel(bool LeftAlignLabel = false); void parseCaseLabel(); diff --git a/clang/unittests/Format/FormatTestVerilog.cpp b/clang/unittests/Format/FormatTestVerilog.cpp index fc23dd8ea1d0a..aae62668c4b84 100644 --- a/clang/unittests/Format/FormatTestVerilog.cpp +++ b/clang/unittests/Format/FormatTestVerilog.cpp @@ -252,6 +252,12 @@ TEST_F(FormatTestVerilog, Case) { Style); } +TEST_F(FormatTestVerilog, Coverage) { + verifyFormat("covergroup x\n" + " @@(begin x);\n" + "endgroup"); +} + TEST_F(FormatTestVerilog, Declaration) { verifyFormat("wire mynet;"); verifyFormat("wire mynet, mynet1;"); @@ -809,5 +815,50 @@ TEST_F(FormatTestVerilog, Primitive) { " endtable\n" "endprimitive"); } + +TEST_F(FormatTestVerilog, StructuredProcedure) { + // Blocks should be indented correctly. + verifyFormat("initial begin\n" + "end"); + verifyFormat("initial begin\n" + " x <= x;\n" + " x <= x;\n" + "end"); + verifyFormat("initial\n" + " x <= x;\n" + "x <= x;"); + verifyFormat("always @(x) begin\n" + "end"); + verifyFormat("always @(x) begin\n" + " x <= x;\n" + " x <= x;\n" + "end"); + verifyFormat("always @(x)\n" + " x <= x;\n" + "x <= x;"); + // Various keywords. + verifyFormat("always @(x)\n" + " x <= x;"); + verifyFormat("always @(posedge x)\n" + " x <= x;"); + verifyFormat("always\n" + " x <= x;"); + verifyFormat("always @*\n" + " x <= x;"); + verifyFormat("always @(*)\n" + " x <= x;"); + verifyFormat("always_comb\n" + " x <= x;"); + verifyFormat("always_latch @(x)\n" + " x <= x;"); + verifyFormat("always_ff @(posedge x)\n" + " x <= x;"); + verifyFormat("initial\n" + " x <= x;"); + verifyFormat("final\n" + " x <= x;"); + verifyFormat("forever\n" + " x <= x;"); +} } // namespace format } // end namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits