[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