[clang] b67ee18 - [clang-format] Handle Verilog user-defined primitives

via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 28 17:39:08 PDT 2022


Author: sstwcw
Date: 2022-07-29T00:38:30Z
New Revision: b67ee18e85f30334792e33a71c883fcfdcb83436

URL: https://github.com/llvm/llvm-project/commit/b67ee18e85f30334792e33a71c883fcfdcb83436
DIFF: https://github.com/llvm/llvm-project/commit/b67ee18e85f30334792e33a71c883fcfdcb83436.diff

LOG: [clang-format] Handle Verilog user-defined primitives

Differential Revision: https://reviews.llvm.org/D128713

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 90dc1f010a8e..f95a27630a79 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -143,6 +143,8 @@ namespace format {
   TYPE(VerilogDimensionedTypeName)                                             \
   /* for the base in a number literal, not including the quote */              \
   TYPE(VerilogNumberBase)                                                      \
+  /* Things inside the table in user-defined primitives. */                    \
+  TYPE(VerilogTableItem)                                                       \
   TYPE(Unknown)
 
 /// Determines the semantic type of a syntactic token, e.g. whether "<" is a

diff  --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 4f5ca9fed3aa..3dd550256469 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -917,6 +917,10 @@ class AnnotatingParser {
   bool consumeToken() {
     FormatToken *Tok = CurrentToken;
     next();
+    // In Verilog primitives' state tables, `:`, `?`, and `-` aren't normal
+    // operators.
+    if (Tok->is(TT_VerilogTableItem))
+      return true;
     switch (Tok->Tok.getKind()) {
     case tok::plus:
     case tok::minus:
@@ -3996,8 +4000,16 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
       return true;
     }
   } else if (Style.isVerilog()) {
+    // Add space between things in a primitive's state table unless in a
+    // transition like `(0?)`.
+    if ((Left.is(TT_VerilogTableItem) &&
+         !Right.isOneOf(tok::r_paren, tok::semi)) ||
+        (Right.is(TT_VerilogTableItem) && Left.isNot(tok::l_paren))) {
+      const FormatToken *Next = Right.getNextNonComment();
+      return !(Next && Next->is(tok::r_paren));
+    }
     // Don't add space within a delay like `#0`.
-    if (!Left.is(TT_BinaryOperator) &&
+    if (Left.isNot(TT_BinaryOperator) &&
         Left.isOneOf(Keywords.kw_verilogHash, Keywords.kw_verilogHashHash)) {
       return false;
     }

diff  --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 3253e5703077..719532b28ffc 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1913,6 +1913,10 @@ void UnwrappedLineParser::parseStructuralElement(
       }
 
       if (Style.isVerilog()) {
+        if (FormatTok->is(Keywords.kw_table)) {
+          parseVerilogTable();
+          return;
+        }
         if (Keywords.isVerilogBegin(*FormatTok) ||
             Keywords.isVerilogHierarchy(*FormatTok)) {
           parseBlock();
@@ -4039,7 +4043,8 @@ void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
 }
 
 void UnwrappedLineParser::parseVerilogSensitivityList() {
-  assert(FormatTok->is(tok::at));
+  if (!FormatTok->is(tok::at))
+    return;
   nextToken();
   // A block event expression has 2 at signs.
   if (FormatTok->is(tok::at))
@@ -4064,15 +4069,13 @@ unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
     nextToken();
     if (Keywords.isVerilogIdentifier(*FormatTok))
       nextToken();
-    if (FormatTok->is(tok::at))
-      parseVerilogSensitivityList();
+    parseVerilogSensitivityList();
     if (FormatTok->is(tok::semi))
       nextToken();
   } else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
                                 Keywords.kw_casez, Keywords.kw_randcase,
                                 Keywords.kw_randsequence)) {
-    if (Style.IndentCaseLabels)
-      ++AddLevels;
+    AddLevels += Style.IndentCaseLabels;
     nextToken();
     if (FormatTok->is(tok::l_paren))
       parseParens();
@@ -4154,6 +4157,25 @@ unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
   return AddLevels;
 }
 
+void UnwrappedLineParser::parseVerilogTable() {
+  assert(FormatTok->is(Keywords.kw_table));
+  nextToken(/*LevelDifference=*/1);
+  addUnwrappedLine();
+
+  auto InitialLevel = Line->Level++;
+  while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) {
+    FormatToken *Tok = FormatTok;
+    nextToken();
+    if (Tok->is(tok::semi))
+      addUnwrappedLine();
+    else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus))
+      Tok->setFinalizedType(TT_VerilogTableItem);
+  }
+  Line->Level = InitialLevel;
+  nextToken(/*LevelDifference=*/-1);
+  addUnwrappedLine();
+}
+
 LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
                                                  StringRef Prefix = "") {
   llvm::dbgs() << Prefix << "Line(" << Line.Level

diff  --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 5a6319f06041..15c279dbe3df 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -183,6 +183,7 @@ class UnwrappedLineParser {
   // Returns the number of levels of indentation in addition to the normal 1
   // level for a block, used for indenting case labels.
   unsigned parseVerilogHierarchyHeader();
+  void parseVerilogTable();
 
   // Used by addUnwrappedLine to denote whether to keep or remove a level
   // when resetting the line state.

diff  --git a/clang/unittests/Format/FormatTestVerilog.cpp b/clang/unittests/Format/FormatTestVerilog.cpp
index 8b3b10c982ef..3460065e3efb 100644
--- a/clang/unittests/Format/FormatTestVerilog.cpp
+++ b/clang/unittests/Format/FormatTestVerilog.cpp
@@ -441,5 +441,46 @@ TEST_F(FormatTestVerilog, Preprocessor) {
   }
 }
 
+TEST_F(FormatTestVerilog, Primitive) {
+  verifyFormat("primitive multiplexer\n"
+               "    (mux, control, dataA, dataB);\n"
+               "  output mux;\n"
+               "  input control, dataA, dataB;\n"
+               "  table\n"
+               "    0 1 ? : 1;\n"
+               "    0 0 ? : 0;\n"
+               "    1 ? 1 : 1;\n"
+               "    1 ? 0 : 0;\n"
+               "    x 0 0 : 0;\n"
+               "    x 1 1 : 1;\n"
+               "  endtable\n"
+               "endprimitive");
+  verifyFormat("primitive latch\n"
+               "    (q, ena_, data);\n"
+               "  output q;\n"
+               "  reg q;\n"
+               "  input ena_, data;\n"
+               "  table\n"
+               "    0 1 : ? : 1;\n"
+               "    0 0 : ? : 0;\n"
+               "    1 ? : ? : -;\n"
+               "    ? * : ? : -;\n"
+               "  endtable\n"
+               "endprimitive");
+  verifyFormat("primitive d\n"
+               "    (q, clock, data);\n"
+               "  output q;\n"
+               "  reg q;\n"
+               "  input clock, data;\n"
+               "  table\n"
+               "    (01) 0 : ? : 0;\n"
+               "    (01) 1 : ? : 1;\n"
+               "    (0?) 1 : 1 : 1;\n"
+               "    (0?) 0 : 0 : 0;\n"
+               "    (?0) ? : ? : -;\n"
+               "    (?\?) ? : ? : -;\n"
+               "  endtable\n"
+               "endprimitive");
+}
 } // namespace format
 } // end namespace clang


        


More information about the cfe-commits mailing list