blob: 20e63e19ed1cd48d7017281c8798ab1c86b5afb6 [file] [log] [blame]
// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "verilog/CST/verilog_matchers.h"
#include "gtest/gtest.h"
#include "common/analysis/matcher/core_matchers.h"
#include "common/analysis/matcher/matcher.h"
#include "common/analysis/matcher/matcher_builders.h"
#include "common/analysis/matcher/matcher_test_utils.h"
#include "verilog/CST/verilog_treebuilder_utils.h"
#include "verilog/analysis/verilog_analyzer.h"
namespace verilog {
namespace {
// Tests for SystemTFIdentifierLeaf matching
TEST(VerilogMatchers, SystemTFIdentifierLeafTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{SystemTFIdentifierLeaf(), EmbedInClassMethod("$psprintf(\"foo\");"), 1},
{SystemTFIdentifierLeaf(), EmbedInClassMethod("psprintf(\"foo\");"), 0},
{SystemTFIdentifierLeaf(), EmbedInClass(""), 0},
{SystemTFIdentifierLeaf(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for MacroCallIdLeaf matching
TEST(VerilogMatchers, MacroCallIdLeafTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{MacroCallIdLeaf(), "", 0},
{MacroCallIdLeaf(), EmbedInClass(""), 0},
{MacroCallIdLeaf(), EmbedInClassMethod("`uvm_foo"), 0}, // not a call
{MacroCallIdLeaf(), "`uvm_foo(\"foo\");", 1},
{MacroCallIdLeaf(), "`uvm_foo(\"foo\")\n", 1},
{MacroCallIdLeaf(), EmbedInClassMethod("`uvm_foo(\"foo\");"), 1},
{MacroCallIdLeaf(), EmbedInClassMethod("`uvm_foo(\"foo\")\n"), 1},
{MacroCallIdLeaf(), EmbedInClassMethod("uvm_foo(\"foo\");"), 0},
{MacroCallIdLeaf(), EmbedInClassMethod("$uvm_foo(\"foo\");"), 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NodekVoidcast matching
TEST(VerilogMatchers, VoidCastNodeTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NodekVoidcast(), EmbedInClassMethod("void'(bad());"), 1},
{NodekVoidcast(), EmbedInClassMethod("rar(bad());"), 0},
{NodekVoidcast(), EmbedInClass(""), 0},
{NodekVoidcast(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NodekExpression matching
TEST(VerilogMatchers, ExpressionNodeTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NodekExpression(), EmbedInClassMethod("x = 1;"), 1},
{NodekExpression(), EmbedInClassMethod("foo();"), 0},
{NodekExpression(), EmbedInClass(""), 0},
{NodekExpression(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for ExpressionHasFunctionCall matching
TEST(VerilogMatchers, ExpressionHasFunctionCallTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{ExpressionHasFunctionCall(), EmbedInClassMethod("foo();"), 1},
{ExpressionHasFunctionCall(), EmbedInClassMethod("x = foo();"), 1},
{ExpressionHasFunctionCall(), EmbedInClassMethod("foo(bar);"), 1},
{ExpressionHasFunctionCall(), EmbedInClassMethod("foo(bar, baz);"), 1},
{ExpressionHasFunctionCall(), EmbedInClassMethod("x = foo;"), 0},
{ExpressionHasFunctionCall(), EmbedInClass(""), 0},
{ExpressionHasFunctionCall(), "", 0},
// Qualified Id function call:
{ExpressionHasFunctionCall(), EmbedInClassMethod("bar::foo();"), 1},
{ExpressionHasFunctionCall(), EmbedInClassMethod("x = bar::foo();"), 1},
// This is a method call, different from a function call:
{ExpressionHasFunctionCall(), EmbedInClassMethod("bar.foo();"), 0},
{ExpressionHasFunctionCall(), EmbedInClassMethod("x = bar.foo();"), 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for ExpressionHasRandomizeCallExtension matching
TEST(VerilogMatchers, ExpressionHasRandomizeCallExtensionTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{ExpressionHasRandomizeCallExtension(),
EmbedInClassMethod("foo().randomize();"), 1},
{ExpressionHasRandomizeCallExtension(), EmbedInClassMethod("foo;"), 0},
{ExpressionHasRandomizeCallExtension(),
EmbedInClassMethod("randomize();"), 0},
{ExpressionHasRandomizeCallExtension(), EmbedInClass(""), 0},
{ExpressionHasRandomizeCallExtension(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for ExpressionHasRandomizeFunction matching
TEST(VerilogMatchers, ExpressionHasRandomizeFunctionTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{ExpressionHasRandomizeFunction(), EmbedInClassMethod("randomize();"), 1},
{ExpressionHasRandomizeFunction(), EmbedInClassMethod("foo.randomize();"),
0},
{ExpressionHasRandomizeFunction(), EmbedInClass(""), 0},
{ExpressionHasRandomizeFunction(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for FunctionCallHasId matching
TEST(VerilogMatchers, FunctionCallHasIdTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{FunctionCallHasId(), EmbedInClassMethod("foo();"), 1},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NumberHasConstantWidth matching
TEST(VerilogMatchers, NumberHasConstantWidthTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NumberHasConstantWidth(), "", 0},
{NumberHasConstantWidth(), "localparam x = 1'bx;", 1},
{NumberHasConstantWidth(), "localparam x = 2'b 01;", 1},
{NumberHasConstantWidth(), "localparam x = 8'b0000_1111;", 1},
{NumberHasConstantWidth(), "localparam x = `WIDTH'bx;", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NumberHasBasedLiteral matching
TEST(VerilogMatchers, NumberHasBasedLiteralTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NumberHasBasedLiteral(), "", 0},
{NumberHasBasedLiteral(), "localparam x = 1'0;", 0},
{NumberHasBasedLiteral(), "localparam x = 1'b0;", 1},
{NumberHasBasedLiteral(), "localparam x = 1'B1;", 1},
{NumberHasBasedLiteral(), "localparam x = 4'b 10_10;", 1},
{NumberHasBasedLiteral(), "localparam x = 8'b0000_1111;", 1},
{NumberHasBasedLiteral(), "localparam x = `WIDTH'bx;", 1},
{NumberHasBasedLiteral(), "localparam x = 2'sb0;", 1},
{NumberHasBasedLiteral(), "localparam x = 2'SB1;", 1},
{NumberHasBasedLiteral(), "localparam x = 32'd 2000;", 1},
{NumberHasBasedLiteral(), "localparam x = 32'D 4095;", 1},
{NumberHasBasedLiteral(), "localparam x = 32'o 66666;", 1},
{NumberHasBasedLiteral(), "localparam x = 32'O 777_777;", 1},
{NumberHasBasedLiteral(), "localparam x = 32'h 0000_4321;", 1},
{NumberHasBasedLiteral(), "localparam x = 64'H aaaa_bbbb_cccc_dddd;", 1},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NumberIsBinary matching
TEST(VerilogMatchers, NumberIsBinaryTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NumberIsBinary(), "", 0},
{NumberIsBinary(), "localparam x = 1'0;", 0},
{NumberIsBinary(), "localparam x = 1'b0;", 1},
{NumberIsBinary(), "localparam x = 1'B1;", 1},
{NumberIsBinary(), "localparam x = 4'b 10_10;", 1},
{NumberIsBinary(), "localparam x = 8'b0000_1111;", 1},
{NumberIsBinary(), "localparam x = `WIDTH'bx;", 1},
{NumberIsBinary(), "localparam x = `WIDTH'b`DIGITS;", 1},
{NumberIsBinary(), "localparam x = 2'sb0;", 1},
{NumberIsBinary(), "localparam x = 2'SB1;", 1},
{NumberIsBinary(), "localparam x = 32'd 2000;", 0},
{NumberIsBinary(), "localparam x = 32'D 4095;", 0},
{NumberIsBinary(), "localparam x = 32'o 66666;", 0},
{NumberIsBinary(), "localparam x = 32'O 777_777;", 0},
{NumberIsBinary(), "localparam x = 32'h 0000_4321;", 0},
{NumberIsBinary(), "localparam x = 64'H aaaa_bbbb_cccc_dddd;", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NumberHasBInaryDigits matching
TEST(VerilogMatchers, NumberHasBinaryDigitsTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NumberHasBinaryDigits(), "", 0},
{NumberHasBinaryDigits(), "localparam x = 1'0;", 0},
{NumberHasBinaryDigits(), "localparam x = 1'b0;", 1},
{NumberHasBinaryDigits(), "localparam x = 1'B1;", 1},
{NumberHasBinaryDigits(), "localparam x = 4'b 10_10;", 1},
{NumberHasBinaryDigits(), "localparam x = 8'b0000_1111;", 1},
{NumberHasBinaryDigits(), "localparam x = `WIDTH'bx;", 1},
{NumberHasBinaryDigits(), "localparam x = `WIDTH'b`DIGITS;", 0},
{NumberHasBinaryDigits(), "localparam x = 2'sb0;", 1},
{NumberHasBinaryDigits(), "localparam x = 2'SB1;", 1},
{NumberHasBinaryDigits(), "localparam x = 32'd 2000;", 0},
{NumberHasBinaryDigits(), "localparam x = 32'D 4095;", 0},
{NumberHasBinaryDigits(), "localparam x = 32'o 66666;", 0},
{NumberHasBinaryDigits(), "localparam x = 32'O 777_777;", 0},
{NumberHasBinaryDigits(), "localparam x = 32'h 0000_4321;", 0},
{NumberHasBinaryDigits(), "localparam x = 64'H aaaa_bbbb_cccc_dddd;", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NodekActualParameterList matching
TEST(VerilogMatchers, ActualParameterListNodeTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NodekActualParameterList(), EmbedInModule("foo #(1, 2) bar;"), 1},
{NodekActualParameterList(),
EmbedInModule("foo #(.foo(1), .bar(5)) bar;"), 1},
{NodekActualParameterList(), EmbedInModule("foo bar;"), 0},
{NodekActualParameterList(), EmbedInModule(""), 0},
{NodekActualParameterList(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for ActualParameterListHasPositionalParameterList matching
TEST(VerilogMatchers, ActualParameterListHasPositionalParameterListTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{ActualParameterListHasPositionalParameterList(),
EmbedInModule("foo #(1, 2) bar;"), 1},
{ActualParameterListHasPositionalParameterList(),
EmbedInModule("foo #(.foo(1), .bar(5)) bar;"), 0},
{ActualParameterListHasPositionalParameterList(), EmbedInModule(""), 0},
{ActualParameterListHasPositionalParameterList(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NodekGateInstance matching
TEST(VerilogMatchers, GateInstanceNodeTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NodekGateInstance(), EmbedInModule("foo bar(1, 2);"), 1},
{NodekGateInstance(), EmbedInModule("foo bar;"), 0},
{NodekGateInstance(), EmbedInModule("and a0(a, b, x1);"), 0},
{NodekGateInstance(), EmbedInModule(""), 0},
{NodekGateInstance(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for GateInstanceHasPortList matching
TEST(VerilogMatchers, GateInstanceHasPortListTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{GateInstanceHasPortList(), EmbedInModule("foo bar(1, 2);"), 1},
{GateInstanceHasPortList(), EmbedInModule("foo bar;"), 0},
{GateInstanceHasPortList(), EmbedInModule(""), 0},
{GateInstanceHasPortList(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NodekGenerateBlock matching
TEST(VerilogMatchers, GenerateBlockNodeTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NodekGenerateBlock(),
EmbedInModule("generate\n"
"if (TypeIsPosedge) begin : gen_posedge\n"
" always @(posedge clk) foo <= bar;\n"
"end\n"
"endgenerate"),
1},
{NodekGenerateBlock(),
EmbedInModule("generate\n"
"endgenerate"),
0},
{NodekGenerateBlock(), EmbedInModule(""), 0},
{NodekGenerateBlock(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for GenerateRegionNode matching
TEST(VerilogMatchers, GenerateRegionNodeTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NodekGenerateRegion(),
EmbedInModule("generate\n"
"if (TypeIsPosedge) begin : foobar\n"
" foo bar;\n"
"end\n"
"endgenerate"),
1},
{NodekGenerateRegion(),
EmbedInModule("generate\n"
"endgenerate"),
1},
{NodekGenerateRegion(), EmbedInModule("wire rats_nest;"), 0},
{NodekGenerateRegion(), EmbedInModule(""), 0},
{NodekGenerateRegion(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for HasBeginLabel matching
TEST(VerilogMatchers, HasBeginLabelTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{HasBeginLabel(),
EmbedInModule("generate\n"
"if (TypeIsPosedge) begin : gen_posedge\n"
" always @(posedge clk) foo <= bar;\n"
"end\n"
"endgenerate"),
1},
{HasBeginLabel(),
EmbedInModule("generate\n"
"if (TypeIsPosedge) begin\n"
" always @(posedge clk) foo <= bar;\n"
"end\n"
"endgenerate"),
0},
{HasBeginLabel(), EmbedInModule(""), 0},
{HasBeginLabel(), "", 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for HasGenerateBlock matching
TEST(VerilogMatchers, HasGenerateBlockTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{HasGenerateBlock(), "", 0},
{HasGenerateBlock(), EmbedInModule(""), 0},
{HasGenerateBlock(),
EmbedInModule("generate\n"
"begin\n"
" always @(posedge clk) foo <= bar;\n"
"end\n"
"endgenerate"),
1},
{HasGenerateBlock(),
EmbedInModule("generate\n"
"begin\n"
" genvar j;\n"
"end\n"
"endgenerate"),
1},
{HasGenerateBlock(),
EmbedInModule("generate\n"
"if (TypeIsPosedge) begin : gen_posedge\n"
" always @(posedge clk) foo <= bar;\n"
"end\n"
"endgenerate"),
0},
{HasGenerateBlock(),
EmbedInModule("generate\n"
"if (TypeIsPosedge) begin\n"
" always @(posedge clk) foo <= bar;\n"
"end\n"
"endgenerate"),
0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for integration between NodekGenerateBlock and HasBeginLabel
TEST(VerilogMatchers, GenerateBlockHasBeginLabelTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NodekGenerateBlock(verible::matcher::Unless(HasBeginLabel())),
EmbedInModule("generate\n"
"if (TypeIsPosedge) begin\n"
" always @(posedge clk) foo <= bar;\n"
"end\n"
"endgenerate"),
1},
{NodekGenerateBlock(verible::matcher::Unless(HasBeginLabel())),
EmbedInModule("generate\n"
"if (TypeIsPosedge) begin : gen_posedge\n"
" always @(posedge clk) foo <= bar;\n"
"end\n"
"endgenerate"),
0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for NodekAlwaysStatement matching
TEST(VerilogMatchers, AlwaysStatementNodeTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{NodekAlwaysStatement(), EmbedInModule(""), 0},
{NodekAlwaysStatement(), EmbedInModule("initial begin a <= 0; end"), 0},
{NodekAlwaysStatement(), EmbedInModule("always_ff begin a <= b; end"), 1},
{NodekAlwaysStatement(), EmbedInModule("always_comb begin a = b; end"),
1},
{NodekAlwaysStatement(), EmbedInModule("always @* begin a = b; end"), 1},
{NodekAlwaysStatement(), EmbedInModule("always @(*) begin a = b; end"),
1},
{NodekAlwaysStatement(),
EmbedInModule("always @(posedge foo) begin a <= b; end"), 1},
{NodekAlwaysStatement(),
EmbedInModule("always_ff begin a <= b; end\n"
"always_comb begin a = b; end"),
2},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for AlwaysKeyword matching
TEST(VerilogMatchers, AlwaysKeywordTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{AlwaysKeyword(), EmbedInModule(""), 0},
{AlwaysKeyword(), EmbedInModule("initial begin a <= 0; end"), 0},
{AlwaysKeyword(), EmbedInModule("always_ff begin a <= b; end"), 0},
{AlwaysKeyword(), EmbedInModule("always_comb begin a = b; end"), 0},
{AlwaysKeyword(), EmbedInModule("always @* begin a = b; end"), 1},
{AlwaysKeyword(), EmbedInModule("always @(*) begin a = b; end"), 1},
{AlwaysKeyword(),
EmbedInModule("always @(posedge foo) begin a <= b; end"), 1},
{AlwaysKeyword(),
EmbedInModule("always_ff begin a <= b; end\n"
"always_comb begin a = b; end"),
0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for AlwaysCombKeyword matching
TEST(VerilogMatchers, AlwaysCombKeywordTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{AlwaysCombKeyword(), EmbedInModule(""), 0},
{AlwaysCombKeyword(), EmbedInModule("initial begin a <= 0; end"), 0},
{AlwaysCombKeyword(), EmbedInModule("always_ff begin a <= b; end"), 0},
{AlwaysCombKeyword(), EmbedInModule("always_comb begin a = b; end"), 1},
{AlwaysCombKeyword(), EmbedInModule("always @* begin a = b; end"), 0},
{AlwaysCombKeyword(), EmbedInModule("always @(*) begin a = b; end"), 0},
{AlwaysCombKeyword(),
EmbedInModule("always @(posedge foo) begin a <= b; end"), 0},
{AlwaysCombKeyword(),
EmbedInModule("always_ff begin a <= b; end\n"
"always_comb begin a = b; end"),
1},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for AlwaysFFKeyword matching
TEST(VerilogMatchers, AlwaysFFKeywordTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{AlwaysFFKeyword(), EmbedInModule(""), 0},
{AlwaysFFKeyword(), EmbedInModule("initial begin a <= 0; end"), 0},
{AlwaysFFKeyword(), EmbedInModule("always_ff begin a <= b; end"), 1},
{AlwaysFFKeyword(), EmbedInModule("always_comb begin a = b; end"), 0},
{AlwaysFFKeyword(), EmbedInModule("always @* begin a = b; end"), 0},
{AlwaysFFKeyword(), EmbedInModule("always @(*) begin a = b; end"), 0},
{AlwaysFFKeyword(),
EmbedInModule("always @(posedge foo) begin a <= b; end"), 0},
{AlwaysFFKeyword(),
EmbedInModule("always_ff begin a <= b; end\n"
"always_comb begin a = b; end"),
1},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for AlwaysStatementHasEventControlStar matching
TEST(VerilogMatchers, AlwaysStatementHasEventControlStarTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{AlwaysStatementHasEventControlStar(), EmbedInModule(""), 0},
{AlwaysStatementHasEventControlStar(),
EmbedInModule("initial begin a <= 0; end"), 0},
{AlwaysStatementHasEventControlStar(),
EmbedInModule("always_ff begin a <= b; end"), 0},
{AlwaysStatementHasEventControlStar(),
EmbedInModule("always_comb begin a = b; end"), 0},
{AlwaysStatementHasEventControlStar(),
EmbedInModule("always @* begin a = b; end"), 1},
{AlwaysStatementHasEventControlStar(),
EmbedInModule("always @(*) begin a = b; end"), 1},
{AlwaysStatementHasEventControlStar(),
EmbedInModule("always @(posedge foo) begin a <= b; end"), 0},
{AlwaysStatementHasEventControlStar(),
EmbedInModule("always_ff begin a <= b; end\n"
"always_comb begin a = b; end"),
0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests that matcher finds left-hand-sides of assignments.
TEST(VerilogMatchers, LValueOfAssignmentTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{LValueOfAssignment(), EmbedInClassMethod(""), 0},
{LValueOfAssignment(), EmbedInClassMethod("foo();"), 0},
{LValueOfAssignment(), EmbedInClassMethod("x = 1;"), 1},
{LValueOfAssignment(), EmbedInClassMethod("x = a + b;"), 1},
{LValueOfAssignment(), EmbedInModule("initial begin\nfoo();\nend\n"), 0},
{LValueOfAssignment(), EmbedInModule("initial begin\nx = 1;\nend\n"), 1},
{LValueOfAssignment(), EmbedInClassMethod("x[1] = 1;"), 1},
{LValueOfAssignment(), EmbedInClassMethod("x.y = 2;"), 1},
{LValueOfAssignment(), EmbedInClassMethod("x[0].y = 3;"), 1},
{LValueOfAssignment(), EmbedInClassMethod("x.y[2] = 4;"), 1},
{LValueOfAssignment(), EmbedInClassMethod("x[0].y[0] = 5;"), 1},
{LValueOfAssignment(), EmbedInClassMethod("if (0) x = 1;"), 1},
{LValueOfAssignment(), EmbedInClassMethod("forever x = y;"), 1},
{LValueOfAssignment(), EmbedInClassMethod("x = 1;\ny = two();"), 2},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests that matcher finds assignments values that are function calls.
TEST(VerilogMatchers, RValueIsFunctionCallTest) {
const verible::matcher::RawMatcherTestCase tests[] = {
{RValueIsFunctionCall(), EmbedInModule(""), 0},
{RValueIsFunctionCall(), EmbedInClassMethod(""), 0},
{RValueIsFunctionCall(), EmbedInClassMethod("x = 1;"), 0},
{RValueIsFunctionCall(), EmbedInClassMethod("x = y / z;"), 0},
{RValueIsFunctionCall(), EmbedInClassMethod("x = y / z();"), 0},
{RValueIsFunctionCall(), EmbedInClassMethod("x = foo();"), 1},
{RValueIsFunctionCall(), EmbedInClassMethod("x = bar::foo();"), 1},
{RValueIsFunctionCall(), EmbedInClassMethod("x = bar::foo(a);"), 1},
{RValueIsFunctionCall(), EmbedInClassMethod("x.y = bar::foo(a);"), 1},
{RValueIsFunctionCall(), EmbedInClassMethod("x = bar.foo();"), 0},
{RValueIsFunctionCall(), EmbedInClassMethod("z = pkg::bar::foo();"), 1},
{RValueIsFunctionCall(), EmbedInClassMethod("x = bar::foo() -12;"), 0},
{RValueIsFunctionCall(), EmbedInClassMethod("x = a + bar::foo();"), 0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests that qualified function calls are found.
TEST(VerilogMatchers, FunctionCallIsQualifiedTest) {
const verible::matcher::RawMatcherTestCase tests[] = {
{FunctionCallIsQualified(), EmbedInModule(""), 0},
{FunctionCallIsQualified(), EmbedInClassMethod(""), 0},
{FunctionCallIsQualified(), EmbedInClassMethod("x = 1;"), 0},
{FunctionCallIsQualified(), EmbedInClassMethod("x = y / z;"), 0},
{FunctionCallIsQualified(), EmbedInClassMethod("x = y / z();"), 0},
{FunctionCallIsQualified(), EmbedInClassMethod("x = foo();"), 0},
{FunctionCallIsQualified(), EmbedInClassMethod("x = bar::foo();"), 1},
{FunctionCallIsQualified(), EmbedInClassMethod("x = bar::foo(a);"), 1},
{FunctionCallIsQualified(), EmbedInClassMethod("x.y = bar::foo(a);"), 1},
{FunctionCallIsQualified(), EmbedInClassMethod("x = bar.foo();"), 0},
{FunctionCallIsQualified(), EmbedInClassMethod("z = pkg::bar::foo();"),
1},
{FunctionCallIsQualified(), EmbedInClassMethod("x = bar::foo() -12;"), 1},
{FunctionCallIsQualified(), EmbedInClassMethod("x = a + bar::foo();"), 1},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests that assignments to qualified function calls are found.
TEST(VerilogMatchers, RValueFunctionCallIsQualifiedTest) {
const verible::matcher::RawMatcherTestCase tests[] = {
{RValueIsFunctionCall(FunctionCallIsQualified()), EmbedInModule(""), 0},
{RValueIsFunctionCall(FunctionCallIsQualified()), EmbedInClassMethod(""),
0},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = 1;"), 0},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = y / z;"), 0},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = y / z();"), 0},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = foo();"), 0},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = bar::foo();"), 1},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("bar::foo();"), 0}, // no assignment
// TODO(fangism): The following test case wrongly matches, but only
// because the matcher matches two different function calls: qqq is the
// outermost match, but the recursive inner match finds a qualified
// function call deeper in the syntax tree. Solution is to use a direct
// inner matcher that does not search recursively.
// {RValueIsFunctionCall(FunctionCallIsQualified()),
// EmbedInClassMethod("qqq(bar::foo(), 1, 2);"), 0},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("y = z();\nbar::foo();"),
0}, // no matching assignment
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = bar::foo(a);"), 1},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x.y = bar::foo(a);"), 1},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = bar.foo();"), 0},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("z = pkg::bar::foo();"), 1},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("z = pkg::bar::foo(\"a\", b, cc);"), 1},
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = bar::foo() -12;"), 0}, // outermost rvalue is -
{RValueIsFunctionCall(FunctionCallIsQualified()),
EmbedInClassMethod("x = a + bar::foo();"), 0}, // outermost rvalue is +
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests that function call arguments are matched.
TEST(VerilogMatchers, FunctionCallArgumentsTest) {
const verible::matcher::RawMatcherTestCase tests[] = {
{FunctionCallArguments(), EmbedInModule(""), 0},
{FunctionCallArguments(), EmbedInClassMethod(""), 0},
{FunctionCallArguments(), EmbedInClassMethod("a = 1 + 2;"), 0},
{FunctionCallArguments(), EmbedInClassMethod("foobar();"), 0},
{FunctionCallArguments(), EmbedInClassMethod("foobar(1);"), 1},
{FunctionCallArguments(), EmbedInClassMethod("foobar(a, b, c);"), 1},
{FunctionCallArguments(), EmbedInClassMethod("`foobar();"),
0}, // macro call arguments are different
{FunctionCallArguments(), EmbedInClassMethod("`foobar(1);"), 0},
{FunctionCallArguments(), EmbedInClassMethod("`foobar(a, b, c);"), 0},
{FunctionCallArguments(), EmbedInClassMethod("foo(bar());"), 1},
{FunctionCallArguments(), EmbedInClassMethod("x = foobar();"), 0},
{FunctionCallArguments(), EmbedInClassMethod("f.g.h = foobar(g);"), 1},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests that ranged dimensions are matched.
TEST(VerilogMatchers, DeclarationDimensionsHasRanges) {
const verible::matcher::RawMatcherTestCase tests[] = {
{DeclarationDimensionsHasRanges(), "", 0},
{DeclarationDimensionsHasRanges(), EmbedInModule(""), 0},
{DeclarationDimensionsHasRanges(), "wire w;", 0},
{DeclarationDimensionsHasRanges(), "wire [1:0] w;", 1},
{DeclarationDimensionsHasRanges(), "wire w [1:0];", 1},
{DeclarationDimensionsHasRanges(), "wire [1:2] w [1:0];", 2},
{DeclarationDimensionsHasRanges(), EmbedInModule("wire w;"), 0},
{DeclarationDimensionsHasRanges(), EmbedInModule("wire [1:0] w;"), 1},
{DeclarationDimensionsHasRanges(), EmbedInModule("wire w [1:0];"), 1},
{DeclarationDimensionsHasRanges(), EmbedInModule("wire [1:2] w [1:0];"),
2},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
// Tests for HasDefaultCase matching.
TEST(VerilogMatchers, HasDefaultCaseTests) {
const verible::matcher::RawMatcherTestCase tests[] = {
{HasDefaultCase(), "", 0},
{HasDefaultCase(),
R"(
function automatic int foo (input in);
case (in)
default: return 0;
endcase
endfunction
)",
1},
{HasDefaultCase(),
R"(
function automatic int foo (input in);
case (in)
1: return 0;
endcase
endfunction
)",
0},
};
for (const auto& test : tests)
verible::matcher::RunRawMatcherTestCase<VerilogAnalyzer>(test);
}
} // namespace
} // namespace verilog