
Now stuff inside begin-end blocks get indented. Some tests are moved into FormatTestVerilog.Block from FormatTestVerilog.If because they have nothing to do with if statements. Reviewed By: HazardyKnusperkeks, owenpan Differential Revision: https://reviews.llvm.org/D128711
377 lines
11 KiB
C++
377 lines
11 KiB
C++
//===- unittest/Format/FormatTestVerilog.cpp ------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "FormatTestUtils.h"
|
|
#include "clang/Format/Format.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
#define DEBUG_TYPE "format-test"
|
|
|
|
namespace clang {
|
|
namespace format {
|
|
|
|
class FormatTestVerilog : public ::testing::Test {
|
|
protected:
|
|
static std::string format(llvm::StringRef Code, unsigned Offset,
|
|
unsigned Length, const FormatStyle &Style) {
|
|
LLVM_DEBUG(llvm::errs() << "---\n");
|
|
LLVM_DEBUG(llvm::errs() << Code << "\n\n");
|
|
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
|
|
tooling::Replacements Replaces = reformat(Style, Code, Ranges);
|
|
auto Result = applyAllReplacements(Code, Replaces);
|
|
EXPECT_TRUE(static_cast<bool>(Result));
|
|
LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
|
|
return *Result;
|
|
}
|
|
|
|
static std::string
|
|
format(llvm::StringRef Code,
|
|
const FormatStyle &Style = getLLVMStyle(FormatStyle::LK_Verilog)) {
|
|
return format(Code, 0, Code.size(), Style);
|
|
}
|
|
|
|
static void verifyFormat(
|
|
llvm::StringRef Code,
|
|
const FormatStyle &Style = getLLVMStyle(FormatStyle::LK_Verilog)) {
|
|
EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
|
|
EXPECT_EQ(Code.str(),
|
|
format(test::messUp(Code, /*HandleHash=*/false), Style));
|
|
}
|
|
};
|
|
|
|
TEST_F(FormatTestVerilog, BasedLiteral) {
|
|
verifyFormat("x = '0;");
|
|
verifyFormat("x = '1;");
|
|
verifyFormat("x = 'X;");
|
|
verifyFormat("x = 'x;");
|
|
verifyFormat("x = 'Z;");
|
|
verifyFormat("x = 'z;");
|
|
verifyFormat("x = 659;");
|
|
verifyFormat("x = 'h837ff;");
|
|
verifyFormat("x = 'o7460;");
|
|
verifyFormat("x = 4'b1001;");
|
|
verifyFormat("x = 5'D3;");
|
|
verifyFormat("x = 3'b01x;");
|
|
verifyFormat("x = 12'hx;");
|
|
verifyFormat("x = 16'hz;");
|
|
verifyFormat("x = -8'd6;");
|
|
verifyFormat("x = 4'shf;");
|
|
verifyFormat("x = -4'sd15;");
|
|
verifyFormat("x = 16'sd?;");
|
|
}
|
|
|
|
TEST_F(FormatTestVerilog, Block) {
|
|
verifyFormat("begin\n"
|
|
" x = x;\n"
|
|
"end");
|
|
verifyFormat("begin : x\n"
|
|
" x = x;\n"
|
|
"end : x");
|
|
verifyFormat("begin\n"
|
|
" x = x;\n"
|
|
" x = x;\n"
|
|
"end");
|
|
verifyFormat("fork\n"
|
|
" x = x;\n"
|
|
"join");
|
|
verifyFormat("fork\n"
|
|
" x = x;\n"
|
|
"join_any");
|
|
verifyFormat("fork\n"
|
|
" x = x;\n"
|
|
"join_none");
|
|
verifyFormat("generate\n"
|
|
" x = x;\n"
|
|
"endgenerate");
|
|
verifyFormat("generate : x\n"
|
|
" x = x;\n"
|
|
"endgenerate : x");
|
|
// Nested blocks.
|
|
verifyFormat("begin\n"
|
|
" begin\n"
|
|
" end\n"
|
|
"end");
|
|
verifyFormat("begin : x\n"
|
|
" begin\n"
|
|
" end\n"
|
|
"end : x");
|
|
verifyFormat("begin : x\n"
|
|
" begin : x\n"
|
|
" end : x\n"
|
|
"end : x");
|
|
verifyFormat("begin\n"
|
|
" begin : x\n"
|
|
" end : x\n"
|
|
"end");
|
|
// Test that 'disable fork' and 'rand join' don't get mistaken as blocks.
|
|
verifyFormat("disable fork;\n"
|
|
"x = x;");
|
|
verifyFormat("rand join x x;\n"
|
|
"x = x;");
|
|
}
|
|
|
|
TEST_F(FormatTestVerilog, Delay) {
|
|
// Delay by the default unit.
|
|
verifyFormat("#0;");
|
|
verifyFormat("#1;");
|
|
verifyFormat("#10;");
|
|
verifyFormat("#1.5;");
|
|
// Explicit unit.
|
|
verifyFormat("#1fs;");
|
|
verifyFormat("#1.5fs;");
|
|
verifyFormat("#1ns;");
|
|
verifyFormat("#1.5ns;");
|
|
verifyFormat("#1us;");
|
|
verifyFormat("#1.5us;");
|
|
verifyFormat("#1ms;");
|
|
verifyFormat("#1.5ms;");
|
|
verifyFormat("#1s;");
|
|
verifyFormat("#1.5s;");
|
|
// The following expression should be on the same line.
|
|
verifyFormat("#1 x = x;");
|
|
EXPECT_EQ("#1 x = x;", format("#1\n"
|
|
"x = x;"));
|
|
}
|
|
|
|
TEST_F(FormatTestVerilog, If) {
|
|
verifyFormat("if (x)\n"
|
|
" x = x;");
|
|
verifyFormat("if (x)\n"
|
|
" x = x;\n"
|
|
"x = x;");
|
|
|
|
// Test else
|
|
verifyFormat("if (x)\n"
|
|
" x = x;\n"
|
|
"else if (x)\n"
|
|
" x = x;\n"
|
|
"else\n"
|
|
" x = x;");
|
|
verifyFormat("if (x) begin\n"
|
|
" x = x;\n"
|
|
"end else if (x) begin\n"
|
|
" x = x;\n"
|
|
"end else begin\n"
|
|
" x = x;\n"
|
|
"end");
|
|
verifyFormat("if (x) begin : x\n"
|
|
" x = x;\n"
|
|
"end : x else if (x) begin : x\n"
|
|
" x = x;\n"
|
|
"end : x else begin : x\n"
|
|
" x = x;\n"
|
|
"end : x");
|
|
|
|
// Test block keywords.
|
|
verifyFormat("if (x) begin\n"
|
|
" x = x;\n"
|
|
"end");
|
|
verifyFormat("if (x) begin : x\n"
|
|
" x = x;\n"
|
|
"end : x");
|
|
verifyFormat("if (x) begin\n"
|
|
" x = x;\n"
|
|
" x = x;\n"
|
|
"end");
|
|
verifyFormat("if (x) fork\n"
|
|
" x = x;\n"
|
|
"join");
|
|
verifyFormat("if (x) fork\n"
|
|
" x = x;\n"
|
|
"join_any");
|
|
verifyFormat("if (x) fork\n"
|
|
" x = x;\n"
|
|
"join_none");
|
|
verifyFormat("if (x) generate\n"
|
|
" x = x;\n"
|
|
"endgenerate");
|
|
verifyFormat("if (x) generate : x\n"
|
|
" x = x;\n"
|
|
"endgenerate : x");
|
|
|
|
// Test that concatenation braces don't get regarded as blocks.
|
|
verifyFormat("if (x)\n"
|
|
" {x} = x;");
|
|
verifyFormat("if (x)\n"
|
|
" x = {x};");
|
|
verifyFormat("if (x)\n"
|
|
" x = {x};\n"
|
|
"else\n"
|
|
" {x} = {x};");
|
|
}
|
|
|
|
TEST_F(FormatTestVerilog, Operators) {
|
|
// Test that unary operators are not followed by space.
|
|
verifyFormat("x = +x;");
|
|
verifyFormat("x = -x;");
|
|
verifyFormat("x = !x;");
|
|
verifyFormat("x = ~x;");
|
|
verifyFormat("x = &x;");
|
|
verifyFormat("x = ~&x;");
|
|
verifyFormat("x = |x;");
|
|
verifyFormat("x = ~|x;");
|
|
verifyFormat("x = ^x;");
|
|
verifyFormat("x = ~^x;");
|
|
verifyFormat("x = ^~x;");
|
|
verifyFormat("x = ++x;");
|
|
verifyFormat("x = --x;");
|
|
|
|
// Test that operators don't get split.
|
|
verifyFormat("x = x++;");
|
|
verifyFormat("x = x--;");
|
|
verifyFormat("x = x ** x;");
|
|
verifyFormat("x = x << x;");
|
|
verifyFormat("x = x >> x;");
|
|
verifyFormat("x = x <<< x;");
|
|
verifyFormat("x = x >>> x;");
|
|
verifyFormat("x = x <= x;");
|
|
verifyFormat("x = x >= x;");
|
|
verifyFormat("x = x == x;");
|
|
verifyFormat("x = x != x;");
|
|
verifyFormat("x = x === x;");
|
|
verifyFormat("x = x !== x;");
|
|
verifyFormat("x = x ==? x;");
|
|
verifyFormat("x = x !=? x;");
|
|
verifyFormat("x = x ~^ x;");
|
|
verifyFormat("x = x ^~ x;");
|
|
verifyFormat("x = x && x;");
|
|
verifyFormat("x = x || x;");
|
|
verifyFormat("x = x->x;");
|
|
verifyFormat("x = x <-> x;");
|
|
verifyFormat("x += x;");
|
|
verifyFormat("x -= x;");
|
|
verifyFormat("x *= x;");
|
|
verifyFormat("x /= x;");
|
|
verifyFormat("x %= x;");
|
|
verifyFormat("x &= x;");
|
|
verifyFormat("x ^= x;");
|
|
verifyFormat("x |= x;");
|
|
verifyFormat("x <<= x;");
|
|
verifyFormat("x >>= x;");
|
|
verifyFormat("x <<<= x;");
|
|
verifyFormat("x >>>= x;");
|
|
verifyFormat("x <= x;");
|
|
|
|
// Test that space is added between operators.
|
|
EXPECT_EQ("x = x < -x;", format("x=x<-x;"));
|
|
EXPECT_EQ("x = x << -x;", format("x=x<<-x;"));
|
|
EXPECT_EQ("x = x <<< -x;", format("x=x<<<-x;"));
|
|
}
|
|
|
|
TEST_F(FormatTestVerilog, Preprocessor) {
|
|
auto Style = getLLVMStyle(FormatStyle::LK_Verilog);
|
|
Style.ColumnLimit = 20;
|
|
|
|
// Macro definitions.
|
|
EXPECT_EQ("`define X \\\n"
|
|
" if (x) \\\n"
|
|
" x = x;",
|
|
format("`define X if(x)x=x;", Style));
|
|
EXPECT_EQ("`define X(x) \\\n"
|
|
" if (x) \\\n"
|
|
" x = x;",
|
|
format("`define X(x) if(x)x=x;", Style));
|
|
EXPECT_EQ("`define X \\\n"
|
|
" x = x; \\\n"
|
|
" x = x;",
|
|
format("`define X x=x;x=x;", Style));
|
|
// Macro definitions with invocations inside.
|
|
EXPECT_EQ("`define LIST \\\n"
|
|
" `ENTRY \\\n"
|
|
" `ENTRY",
|
|
format("`define LIST \\\n"
|
|
"`ENTRY \\\n"
|
|
"`ENTRY",
|
|
Style));
|
|
EXPECT_EQ("`define LIST \\\n"
|
|
" `x = `x; \\\n"
|
|
" `x = `x;",
|
|
format("`define LIST \\\n"
|
|
"`x = `x; \\\n"
|
|
"`x = `x;",
|
|
Style));
|
|
EXPECT_EQ("`define LIST \\\n"
|
|
" `x = `x; \\\n"
|
|
" `x = `x;",
|
|
format("`define LIST `x=`x;`x=`x;", Style));
|
|
// Macro invocations.
|
|
verifyFormat("`x = (`x1 + `x2 + x);");
|
|
// Lines starting with a preprocessor directive should not be indented.
|
|
std::string Directives[] = {
|
|
"begin_keywords",
|
|
"celldefine",
|
|
"default_nettype",
|
|
"define",
|
|
"else",
|
|
"elsif",
|
|
"end_keywords",
|
|
"endcelldefine",
|
|
"endif",
|
|
"ifdef",
|
|
"ifndef",
|
|
"include",
|
|
"line",
|
|
"nounconnected_drive",
|
|
"pragma",
|
|
"resetall",
|
|
"timescale",
|
|
"unconnected_drive",
|
|
"undef",
|
|
"undefineall",
|
|
};
|
|
for (auto &Name : Directives) {
|
|
EXPECT_EQ("if (x)\n"
|
|
"`" +
|
|
Name +
|
|
"\n"
|
|
" ;",
|
|
format("if (x)\n"
|
|
"`" +
|
|
Name +
|
|
"\n"
|
|
";",
|
|
Style));
|
|
}
|
|
// Lines starting with a regular macro invocation should be indented as a
|
|
// normal line.
|
|
EXPECT_EQ("if (x)\n"
|
|
" `x = `x;\n"
|
|
"`timescale 1ns / 1ps",
|
|
format("if (x)\n"
|
|
"`x = `x;\n"
|
|
"`timescale 1ns / 1ps",
|
|
Style));
|
|
EXPECT_EQ("if (x)\n"
|
|
"`timescale 1ns / 1ps\n"
|
|
" `x = `x;",
|
|
format("if (x)\n"
|
|
"`timescale 1ns / 1ps\n"
|
|
"`x = `x;",
|
|
Style));
|
|
std::string NonDirectives[] = {
|
|
// For `__FILE__` and `__LINE__`, although the standard classifies them as
|
|
// preprocessor directives, they are used like regular macros.
|
|
"__FILE__", "__LINE__", "elif", "foo", "x",
|
|
};
|
|
for (auto &Name : NonDirectives) {
|
|
EXPECT_EQ("if (x)\n"
|
|
" `" +
|
|
Name + ";",
|
|
format("if (x)\n"
|
|
"`" +
|
|
Name +
|
|
"\n"
|
|
";",
|
|
Style));
|
|
}
|
|
}
|
|
|
|
} // namespace format
|
|
} // end namespace clang
|