//===- 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 Ranges(1, tooling::Range(Offset, Length)); tooling::Replacements Replaces = reformat(Style, Code, Ranges); auto Result = applyAllReplacements(Code, Replaces); EXPECT_TRUE(static_cast(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