252 lines
7.4 KiB
C++
252 lines
7.4 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, 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("disable fork;\n"
|
|
"x = x;");
|
|
verifyFormat("rand join x x;\n"
|
|
"x = x;");
|
|
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, 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
|