blob: 92931d3e5e74cbfd75df5bbe77087ca59f4e29ad [file] [log] [blame]
//===- 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, Case) {
verifyFormat("case (data)\n"
"endcase");
verifyFormat("casex (data)\n"
"endcase");
verifyFormat("casez (data)\n"
"endcase");
verifyFormat("case (data) inside\n"
"endcase");
verifyFormat("case (data)\n"
" 16'd0:\n"
" result = 10'b0111111111;\n"
"endcase");
verifyFormat("case (data)\n"
" xxxxxxxx:\n"
" result = 10'b0111111111;\n"
"endcase");
// Test labels with multiple options.
verifyFormat("case (data)\n"
" 16'd0, 16'd1:\n"
" result = 10'b0111111111;\n"
"endcase");
verifyFormat("case (data)\n"
" 16'd0, //\n"
" 16'd1:\n"
" result = 10'b0111111111;\n"
"endcase");
// Test that blocks following labels are indented.
verifyFormat("case (data)\n"
" 16'd1: fork\n"
" result = 10'b1011111111;\n"
" join\n"
"endcase\n");
verifyFormat("case (data)\n"
" 16'd1: fork : x\n"
" result = 10'b1011111111;\n"
" join : x\n"
"endcase\n");
// Test default.
verifyFormat("case (data)\n"
" default\n"
" result = 10'b1011111111;\n"
"endcase");
verifyFormat("case (data)\n"
" default:\n"
" result = 10'b1011111111;\n"
"endcase");
// Test that question marks and colons don't get mistaken as labels.
verifyFormat("case (data)\n"
" 8'b1???????:\n"
" instruction1(ir);\n"
"endcase");
verifyFormat("case (data)\n"
" x ? 8'b1??????? : 1:\n"
" instruction3(ir);\n"
"endcase");
// Test indention options.
auto Style = getLLVMStyle(FormatStyle::LK_Verilog);
Style.IndentCaseLabels = false;
verifyFormat("case (data)\n"
"16'd0:\n"
" result = 10'b0111111111;\n"
"endcase",
Style);
verifyFormat("case (data)\n"
"16'd0: begin\n"
" result = 10'b0111111111;\n"
"end\n"
"endcase",
Style);
Style.IndentCaseLabels = true;
verifyFormat("case (data)\n"
" 16'd0:\n"
" result = 10'b0111111111;\n"
"endcase",
Style);
verifyFormat("case (data)\n"
" 16'd0: begin\n"
" result = 10'b0111111111;\n"
" end\n"
"endcase",
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, Hierarchy) {
verifyFormat("module x;\n"
"endmodule");
// Test that the end label is on the same line as the end keyword.
verifyFormat("module x;\n"
"endmodule : x");
// Test that things inside are indented.
verifyFormat("module x;\n"
" generate\n"
" endgenerate\n"
"endmodule");
verifyFormat("program x;\n"
" generate\n"
" endgenerate\n"
"endprogram");
verifyFormat("interface x;\n"
" generate\n"
" endgenerate\n"
"endinterface");
verifyFormat("task x;\n"
" generate\n"
" endgenerate\n"
"endtask");
verifyFormat("function x;\n"
" generate\n"
" endgenerate\n"
"endfunction");
verifyFormat("class x;\n"
" generate\n"
" endgenerate\n"
"endclass");
// Test that they nest.
verifyFormat("module x;\n"
" program x;\n"
" program x;\n"
" endprogram\n"
" endprogram\n"
"endmodule");
// Test that an extern declaration doesn't change the indentation.
verifyFormat("extern module x;\n"
"x = x;");
// Test complex headers
verifyFormat("extern module x\n"
" import x.x::x::*;\n"
" import x;\n"
" #(parameter x)\n"
" (output x);");
verifyFormat("module x\n"
" import x.x::x::*;\n"
" import x;\n"
" #(parameter x)\n"
" (output x);\n"
" generate\n"
" endgenerate\n"
"endmodule : x");
verifyFormat("virtual class x\n"
" (x)\n"
" extends x(x)\n"
" implements x, x, x;\n"
" generate\n"
" endgenerate\n"
"endclass : x\n");
verifyFormat("function automatic logic [1 : 0] x\n"
" (input x);\n"
" generate\n"
" endgenerate\n"
"endfunction : x");
}
TEST_F(FormatTestVerilog, If) {
verifyFormat("if (x)\n"
" x = x;");
verifyFormat("unique if (x)\n"
" x = x;");
verifyFormat("unique0 if (x)\n"
" x = x;");
verifyFormat("priority 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};");
// With attributes.
verifyFormat("(* x *) if (x)\n"
" x = x;");
verifyFormat("(* x = \"x\" *) if (x)\n"
" x = x;");
verifyFormat("(* x, x = \"x\" *) if (x)\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));
}
}
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