blob: 73caf44931c9c0f97e0a8bcb659af2b00e20ca9c [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.
// Verilog parser unit tests
#include <algorithm>
#include <cstddef>
#include <initializer_list>
#include <string>
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "common/parser/bison_parser_common.h"
#include "common/parser/parser_test_util.h"
#include "common/text/constants.h"
#include "common/text/symbol.h"
#include "common/text/token_info.h"
#include "common/text/token_info_test_util.h"
#include "gtest/gtest.h"
#include "verilog/CST/verilog_nonterminals.h"
#include "verilog/analysis/verilog_analyzer.h"
#include "verilog/analysis/verilog_excerpt_parse.h"
#include "verilog/parser/verilog_token_enum.h"
namespace verilog {
using ParserTestData = verible::TokenInfoTestData;
using ParserTestCaseArray = std::initializer_list<const char*>;
static constexpr VerilogPreprocess::Config kDefaultPreprocess;
// No syntax tree expected from these inputs.
static const ParserTestCaseArray kEmptyTests = {
"", " ", "\t\t\t", "\n\n", "// comment\n", "/* comment */\n",
};
static const ParserTestCaseArray kPreprocessorTests = {
"`define TRUTH\n", // definition without value
"`define FOO BAR-1\n", // definition with value
"`include \"foo.svh\"\n" // include directive
"`ifndef SANITY\n"
"`define SANITY\n"
"`endif\n",
"`include `EXPAND_TO_STRING\n" // include directive
"`include `EXPAND_TO_PATH // path\n"
"`define SANITY 1+1\n"
"`ifdef INSANITY\n"
"`undef INSANITY\n" // undefine
"`define INSANITY\n"
"`endif\n",
"`ifdef INSANITY\n" // definition also in else clause
"`define INSANITY // comment\n" // definition with comment
"`else\n"
"`define SANITY 1\n"
"`endif\n",
"`define INCEPTION(a, b, c)\n", // with parameters, no body
"`define INCEPTION(a, b, c) (a*b-c)\n", // with parameters, body
"`define INCEPTION(a, b, c) \\\n" // with line-conitnuation
" (a*b-c)\n",
"`define INCEPTION(xyz) \\\n" // definition that defines
" `define DEEPER (xyz)\n",
"`define LONG_MACRO(\n"
" a, b, c)\n", // parameters span multiple lines
"`define LONG_MACRO(\n"
" a,\n" // parameters span multiple lines without continuation
" b, c) text goes here\n",
"`define LONG_MACRO(\n"
" a,\n" // parameters span multiple lines without continuation
" b\n"
", c\n"
") \\\n"
"more text c, b, a \\\n"
"blah blah macro ends here\n",
"`define LONG_MACRO(\n"
" a, b=2, c=42) \\\n" // parameters with defaults
"a + b /c +345\n",
"`define LONG_MACRO(\n"
" a, b=\"(3,2)\", c=(3,2)) \\\n" // parameters with defaults
"a + b /c +345\n",
// escaped identifier macro call argument
"`FOO(\\BAR )\n", //
"`FOO(\\BAR\t)\n", //
"`FOO(\\BAR\n)\n", //
"`FOO(\\BAR.BAZ )\n", //
"`FOO(\\BAR , \\BAZ )\n", //
"`WE(`MUST(`GO(\\deeper )))\n", //
"`MACRO()\n", //
"`MACRO(123badid)\n", // call arg contains a lexical error, but remains
// unlexed
"`MACRO(`)\n", // call arg contains a lexical error, but remains unlexed
"`MACRO(` )\n", // call arg contains a lexical error, but remains unlexed
"`MACRO(`DEEPER(`))\n", // call arg contains a lexical error, but remains
// unlexed
"`c(;d());\n" // ";d()" remains unlexed
};
// Make sure line continuations, newlines and spaces get filtered out
static const ParserTestCaseArray kLexerFilterTests = {
"parameter \tfoo =\t\t0;",
"parameter\n\nfoo =\n 0;",
"parameter \\\nfoo =\\\n 0;",
"//comment with line-continuation\\\n",
"//comment1 with line-continuation\\\n"
"//comment2 with line-continuation\\\n",
};
// Numbers are parsed as ([width], [signed]base, digits)
static const ParserTestCaseArray kNumberTests = {
"parameter foo = 0;",
"parameter int foo = 0;",
"parameter int foo = '0;",
"parameter int foo = '1;",
// binary
"parameter int foo = 'b0;",
"parameter int foo = 'b 0;",
"parameter int foo = 1'b0;",
"parameter int foo = 1'B0;",
"parameter int foo = 1 'b 0;",
"parameter int foo = 1'b1;",
"parameter int foo = 1'bx;",
"parameter int foo = 1 'b x;",
"parameter int foo = 1'bz;",
"parameter int foo = 4'bxxxx;",
"parameter int foo = 4'bzzzz;",
"parameter int foo = 4'sb1111;",
"parameter int foo = 4'Sb0000;",
"parameter int foo = 16'b`DIGITS;",
"parameter int foo = 16'b`DIGITS();",
"parameter int foo = 16'b`DIGITS(bar);",
"parameter int foo = 16'b`DIGITS(bar, baz);",
"parameter int foo = 16 'b `DIGITS;",
"parameter int foo = 16 'b `DIGITS();",
"parameter int foo = `WIDTH'b`DIGITS;",
// decimal
"parameter int foo = 'd0;",
"parameter int foo = 'd 0;",
"parameter int foo = 32'd1;",
"parameter int foo = 32'D1;",
"parameter int foo = 32 'd 1;",
"parameter int foo = 32'sd1;",
"parameter int foo = 32'Sd1;",
"parameter int foo = 32'dx;",
"parameter int foo = 32'dx_;",
"parameter int foo = 32'dx__;",
"parameter int foo = 32'dX;",
"parameter int foo = 32'dz;",
"parameter int foo = 32'dZ;",
"parameter int foo = 32'd`DIGITS;",
"parameter int foo = 32 'd `DIGITS;",
"parameter int foo = 32'd`DIGITS();",
"parameter int foo = 32'd`DIGITS(bar);",
"parameter int foo = `WIDTH'd`DIGITS;",
// octal
"parameter int foo = 'o0;",
"parameter int foo = 'o 0;",
"parameter int foo = 32'o7;",
"parameter int foo = 32'o7_7_7;",
"parameter int foo = 32'O7;",
"parameter int foo = 32 'o 7;",
"parameter int foo = 32'so7;",
"parameter int foo = 32'So7;",
"parameter int foo = 32'oxxx;",
"parameter int foo = 32'oXX;",
"parameter int foo = 32'ozz;",
"parameter int foo = 32'oZZ;",
"parameter int foo = 32'o`DIGITS;",
"parameter int foo = 32 'o `DIGITS;",
"parameter int foo = 32'o`DIGITS();",
"parameter int foo = 32'o`DIGITS(bar);",
"parameter int foo = `WIDTH'o`DIGITS;",
// hexadecimal
"parameter int foo = 'h0;",
"parameter int foo = 'h 0;",
"parameter int foo = 32'h7;",
"parameter int foo = 32'H7fFF;",
"parameter int foo = 32'H_7f_FF_;",
"parameter int foo = 32'hdeadbeef;",
"parameter int foo = 32'hFEEDFACE;",
"parameter int foo = 32 'h 7;",
"parameter int foo = 32'sh7;",
"parameter int foo = 32'Sh7;",
"parameter int foo = 32'hxxx;",
"parameter int foo = 32'hXX;",
"parameter int foo = 32'hzz;",
"parameter int foo = 32'hZZ;",
"parameter int foo = 32'h`DIGITS;",
"parameter int foo = 32 'h `DIGITS;",
"parameter int foo = 32'h`DIGITS();",
"parameter int foo = 32'h`DIGITS(bar);",
"parameter int foo = `WIDTH'h`DIGITS;",
};
// classes are a System Verilog construct
static const ParserTestCaseArray kClassTests = {
"class semicolon_classy; ; ;;; ; ; ;endclass",
"class Foo; endclass",
"class static Foo; endclass",
"class automatic Foo; endclass",
"virtual class Foo; endclass",
"virtual class automatic Foo; endclass",
"class Foo extends Bar; endclass",
"class Foo extends Package::Bar; endclass",
"class Foo extends Bar #(x,y,z); endclass",
"class Foo #(int N);\n" // parameter without default value
"endclass",
"class Foo #(int N, P);\n"
"endclass",
"class Foo #(int N, int P);\n"
"endclass",
"class Foo #(int N=1, int P=2) extends Bar #(x,y,z);\n"
"endclass",
"class Foo #(int W=8, type Int=int) extends Bar #(x,y,z);\n"
"endclass",
"class Foo #(T=int);\n" // default type
"endclass",
"class Foo #(type KeyType=int, Int=int);\n" // default type
"endclass",
"class Foo #(IFType=virtual x_if);\n" // interface type
"endclass",
"class Foo #(type IFType=virtual x_if);\n" // interface type
"endclass",
"class Foo #(type IFType=virtual interface x_if);\n"
"endclass",
"class Foo extends Package::Bar #(x,y,z); endclass",
"class Foo extends Package::Bar #(.v1(x),.v2(y)); endclass",
"class Foo extends Package::Bar #(x,y,z); endclass",
"class Foo extends Package::Bar #(.v1(x),.v2(y)); endclass",
"class Foo implements Bar; endclass",
"class Foo implements Bar, Blah, Baz; endclass",
"class Foo implements Package::Bar; endclass",
"class Foo implements Bar#(N); endclass",
"class Foo implements Package::Bar#(1, 2); endclass",
"class Foo extends Base implements Bar; endclass",
"class Foo extends Base implements Pkg::Bar, Baz; endclass",
"class Foo;\n"
"integer size;\n"
"function new (integer size);\n"
" begin\n"
" this.size = size;\n"
" end\n"
"endfunction\n"
"task print();\n"
" begin\n"
" $write(\"Hello, world!\");\n"
" end\n"
"endtask\n"
"endclass",
"typedef class myclass_fwd;",
"class zzxx;\n"
"extern function void set_port(analysis_port #(1) ap);\n"
"endclass",
"class zzxy;\n"
"extern function void set_port(dbg_pkg::analysis_port app);\n"
"endclass",
"class zzyyy;\n"
"extern function void set_port(dbg_pkg::analysis_port #(1,N) apb);\n"
"endclass",
"class zzxx;\n"
"extern function automatic void set_port(int ap);\n"
"endclass",
// import declarations
"class foo;\n"
" import fedex_pkg::box;\n"
" import fedex_pkg::*;\n"
"endclass",
"virtual class foo extends bar;\n"
" import fedex_pkg::box;\n"
" import fedex_pkg::*;\n"
"endclass",
// macros as class items
"class macros_as_class_item;\n"
" `moobar()\n"
" `zoobar( )\n"
" `zootar(\n)\n"
"endclass",
"class macros_as_class_item;\n"
" `moobar(,)\n"
" `zoobar( , )\n"
" `zootar(12,)\n"
" `zoojar(,34)\n"
"endclass",
"class macros_as_class_item;\n"
" `uvm_object_registry(myclass, \"class_name\")\n"
"endclass",
"class macros_as_class_item;\n"
" `uvm_object_utils(stress_seq)\n"
" `uvm_object_registry(myclass, \"class_name\")\n"
" `uvm_sweets(dessert)\n"
" `non_uvm_macro(apple, `banana, \"cherry\")\n"
"endclass",
"class macros_as_class_item;\n"
" `uvm_object_utils_begin(foobar)\n"
" `uvm_object_utils(blah)\n"
" `uvm_object_utils_end\n" // macro-id alone treated as call
"endclass",
"class macros_as_class_item;\n"
" `uvm_object_utils_begin(foobar)\n"
" `uvm_field_int(node, UVM_DEFAULT);\n" // with semicolon
" `uvm_field_int(foo::bar_t, UVM_DEFAULT);\n" // with semicolon
" `uvm_field_enum(offset, UVM_DEFAULT)\n" // without semicolon
" `uvm_object_utils_end\n" // macro-id alone treated as call
"endclass",
"class macros_as_class_item;\n"
" `uvm_field_utils_begin(my_class)\n"
" `uvm_field_int(blah1, flag1)\n"
" `uvm_field_real(blah2, flag2)\n"
" `uvm_field_enum(blah3, flag3)\n"
" `uvm_field_object(blah4, flag4)\n"
" `uvm_field_event(blah5, flag5)\n"
" `uvm_field_string(blah6, flag6)\n"
" `uvm_field_array_int(blah7, flag7)\n"
" `uvm_field_sarray_int(blah8, flag8)\n"
" `uvm_field_aa_int_string(blah9, flag9)\n"
" `uvm_field_utils_end\n" // macro-id alone treated as call
"endclass",
"class macros_as_class_item;\n"
" `uvm_object_param_utils_begin(my_class)\n"
" `uvm_field_int(blah1, F1)\n"
" `uvm_field_real(blah2, F2)\n"
" `uvm_field_enum(blah3, F3)\n"
" `uvm_object_utils_end\n" // macro-id alone treated as call
"endclass",
"class macros_as_class_item;\n"
" `uvm_component_utils(my_type)\n"
" `uvm_component_utils_begin(my_type)\n"
" `uvm_field_object(blah1, F1)\n"
" `uvm_field_event(blah2, F2)\n"
" `uvm_field_string(blah3, F3)\n"
" `uvm_component_utils_end\n" // macro-id alone treated as call
"endclass",
"class macros_id_as_call;\n"
" `uvm_new_func\n"
" `uvm_new_func2 // comment\n"
" `uvm_new_func3 /* comment */\n"
"endclass",
"class pp_as_class_item;\n"
" `undef EVIL_MACRO\n"
"endclass",
// parameters and local parameters
"class params_as_class_item;\n"
" parameter N = 2;\n"
" parameter reg P = '1;\n"
" localparam M = f(glb::arr[N]) + 1;\n"
"endclass",
"class params_as_class_item;\n"
" localparam M = {\"hello\", \"world\"}, X = \"spot\";\n"
" parameter int N = 2, P = Q(R), S = T[U];\n"
"endclass",
"class how_wide;\n"
" localparam Max_int = {$bits(int) - 1{1'b1}};\n"
"endclass",
"class how_wide #(type DT=int) extends uvm_sequence_item;\n"
" localparam Max_int = {$bits(DT) - 1{1'b1}};\n"
" localparam Min_int = {$bits(int) - $bits(DT){1'b1}};\n"
"endclass",
"class param_types_as_class_item;\n"
" parameter type AT;\n"
" parameter type BT = BrickType;\n"
" parameter type CT1 = Ctype1, CT2 = Ctype2;\n"
" localparam type GT = mypkg::GlueType, GT2;\n"
" localparam type HT1, HT2 = mypkg::ModuleType#(N+M);\n"
"endclass",
// event declaration
"class event_calendar;\n"
" event birthday;\n"
" event first_date, anniversary;\n"
" event revolution[4:0], independence[2:0];\n"
"endclass",
// associative array declaration
"class Driver;\n"
" Packet pNP [*];\n"
" Packet pNP1 [* ];\n"
" Packet pNP2 [ *];\n"
" Packet pNP3 [ * ];\n"
"endclass",
// class property declarations
"class c;\n"
" foo bar;\n"
"endclass\n",
"class c;\n"
" const foo bar;\n"
"endclass\n",
"class c;\n"
" protected int count;\n"
"endclass\n",
"class c;\n"
" foo #(.baz) bar;\n"
"endclass\n",
"class c;\n"
" foo #(.baz(bah)) bar;\n"
"endclass\n",
"class c;\n"
" foo #(.baz) bar1, bar2;\n"
"endclass\n",
"class Driver;\n"
" data_type_or_module_type foo1;\n"
" data_type_or_module_type foo2 = 1'b1;\n"
" data_type_or_module_type foo3, foo4;\n"
" data_type_or_module_type foo5 = 5, foo6 = 6;\n"
"endclass",
"class fields_with_modifiers;\n"
" const data_type_or_module_type foo1 = 4'hf;\n"
" static data_type_or_module_type foo3, foo4;\n"
"endclass",
"class fields_with_modifiers;\n"
" const static data_type_or_module_type foo1 = 4'hf;\n"
" static const data_type_or_module_type foo3, foo4;\n"
"endclass",
// preprocessor balanced class items
"class pp_class;\n"
"`ifdef DEBUGGER\n" // empty
"`endif\n"
"endclass",
"class pp_class;\n"
"`ifdef DEBUGGER\n"
"`ifdef VERBOSE\n" // nested, empty
"`endif\n"
"`endif\n"
"endclass",
"class pp_class;\n"
"`ifndef DEBUGGER\n" // `ifndef
"`endif\n"
"endclass",
"class pp_class;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
"`endif\n"
" int router_size;\n"
"endclass",
"class pp_class;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
" string source_name;\n" // single item
"`endif\n"
" int router_size;\n"
"endclass",
"class pp_class;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
" string source_name;\n" // multiple items
" string dest_name;\n"
"`endif\n"
" int router_size;\n"
"endclass",
"class pp_class;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
" string source_name;\n"
" string dest_name;\n"
"`else\n" // `else empty
"`endif\n"
" int router_size;\n"
"endclass",
"class pp_class;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
" string source_name;\n"
" string dest_name;\n"
"`elsif LAZY\n" // `elsif empty
"`endif\n"
" int router_size;\n"
"endclass",
"class pp_class;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
"`elsif LAZY\n" // `elsif with multiple items
" string source_name;\n"
" string dest_name;\n"
"`endif\n"
" int router_size;\n"
"endclass",
"class pp_class;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
"`elsif BORED\n"
" string source_name;\n"
" string dest_name;\n"
"`elsif LAZY\n" // second `elsif
"`endif\n"
" int router_size;\n"
"endclass",
"class pp_class;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
"`elsif BORED\n"
"`else\n" // `else with multiple items
" string source_name;\n"
" string dest_name;\n"
"`endif\n"
" int router_size;\n"
"endclass",
};
static const ParserTestCaseArray kFunctionTests = {
"function integer add;\n"
"input a, b;\n"
"begin\n"
" add = (a+b);\n"
"end\n"
"endfunction",
"function integer mini_me;\n"
"input a, b;\n"
"mini_me = (a<b) ? a:b;\n"
"endfunction",
"function myclass::numtype mini_me;\n"
"input a, b;\n"
"mini_me = (a<b) ? a:b;\n"
"endfunction",
"function mypkg::myclass::numtype mini_me;\n"
"input a, b;\n"
"mini_me = (a<b) ? a:b;\n"
"endfunction",
"function myclass::numtype #(W) mini_me;\n"
"input a, b;\n"
"mini_me = (a<b) ? a:b;\n"
"endfunction",
"function void compare;\n"
"input int a, b;\n"
"output bit c;\n"
"c = (a == b);\n"
"endfunction",
"function void vcompare;\n"
"input int a, b;\n"
"output bit [N:0] c;\n"
"c = (a ^ b);\n"
"endfunction",
"function void nonsense;\n"
"input int a[3:0], b[M:0];\n"
"output bit [N:0] c [11:0];\n"
"c = (a ^ b);\n"
"endfunction",
"function integer twiddle;\n"
"input a, b;\n"
"`MACRO(a, b);\n"
"endfunction",
"function integer twiddle;\n"
"input a, b;\n"
"`undef MACRO\n"
"endfunction",
// const ref formals
"function integer reader(const ref rw);\n"
"endfunction",
"function void reader(\n"
" const ref in_value, ref out_value\n"
");\n"
"endfunction",
// preprocessor directives in ports
"function void twiddle(\n"
"`ifdef ASDF\n"
" string a,\n"
"`else\n"
" int bb,\n"
"`endif\n"
" bit cc\n"
");\n"
"endfunction",
"function void processor(\n"
" string a,\n"
"`ifdef ASDF\n"
" bit cc\n"
"`else\n"
" int bb\n"
"`endif\n"
");\n"
"endfunction",
// local variables, various qualifiers
"function void declare_stuff;\n"
"int a_count;\n"
"const int b_count;\n"
"var int c_count;\n"
"static foo::int_t d_count;\n"
"automatic bool e_enabled;\n"
"const static string incantation;\n"
"static const string curse = \"dang nabbit\";\n"
"const var automatic string password;\n"
"endfunction",
// let declaration
"function void declare_stuff;\n"
"let Max(a,b) = (a > b) ? a : b;\n"
"endfunction",
// with no function_items
"function void twiddle;\n"
" `MACRO(a, b);\n"
"endfunction",
"function void twiddle;\n"
" if (enable_stats) begin\n"
" $display(\"stuff\");\n"
" end\n"
"endfunction",
// array return types
"function integer[1:0] twiddle;\n"
"input integer a, b;\n"
"endfunction",
"function integer[1:0][3:0] twiddle;\n"
"input integer a, b;\n"
"endfunction",
"function string[2:0] twiddle;\n"
"input bit b [4:0];\n"
"endfunction",
"function monster[n:0] twiddle;\n"
"input integer a[n:0];\n"
"endfunction",
"function scope_name::type_name[n:0] twiddle;\n"
"input integer a[n:0];\n"
"endfunction",
"function scope_name::type_name #(M) [n:0] twiddle;\n"
"input integer a[n:0];\n"
"endfunction",
// streaming concatenation lvalue
"function void unpack_id(int nums);\n"
"{>>8 {foo, bar}} = nums;\n"
"endfunction",
"function void unpack_id(utils_pkg::bytestream_t bytes);\n"
"{<< byte {this.reserved, this.id}} = bytes;\n"
"endfunction",
// concatenation lvalue
"module foo;\n"
" initial begin\n"
" {A, B, C} = bar;\n"
" end\n"
"endmodule\n",
// nested concatenation lvalue
"module foo;\n"
" initial begin\n"
" {{A, B}, {C, D}} = bar;\n"
" end\n"
"endmodule\n",
// assignment pattern lvalue
"module foo;\n"
" initial begin\n"
" '{A, B, C} = bar;\n"
" end\n"
"endmodule\n",
// assignment pattern lvalue and rvalue
"module foo;\n"
" initial begin\n"
" '{A, B, C} = '{D, E, F};\n"
" end\n"
"endmodule\n",
// nested assignment pattern lvalue
"module foo;\n"
" initial begin\n"
" '{'{A, B}, '{C, D}} = bar;\n"
" end\n"
"endmodule\n",
// mixed nested lvalue
"module foo;\n"
" initial begin\n"
" '{{A, B}, {C, D}} = bar1;\n"
" {'{E, F}, '{G, H}} = bar2;\n"
" end\n"
"endmodule\n",
// qualified expressions
"function void scoper;\n"
" a = b::c;\n"
" d = $unit::c;\n"
" e = $unit::xx::yy + zz::ww;\n"
"endfunction",
// cast expressions
"function void caster(int foo);\n"
" ret = ($bits(mux::info_t))'(ctrl_info);\n"
" rdata_address[$clog2(Aspect_ratio)-1:0] =\n"
" $unsigned(($clog2(Aspect_ratio))'(rndx));\n"
" credit = ($bits(credit))'(sq_ub::chunks_per_bank);\n"
"endfunction",
// various index expressions
"function void dollar(utils_pkg::bytestream_t bytes);\n"
" return bar[num_bytes:$];\n"
"endfunction",
// builtin functions
"function int optimize();\n"
" return max(a, b) / min(c, d);\n"
"endfunction",
"function num_pkg::float64_t tangent();\n"
" return sin(angle) / cos(angle);\n"
"endfunction",
// out-of-line method (class member function) definitions
"function void my_class::method_name();\n"
" idle();\n"
"endfunction",
"function my_class::m_name();\n" // implicit return type
"endfunction : m_name",
"function return_type my_class::method_name();\n"
" return to_sender;\n"
"endfunction",
"function qualified::return_type my_class::method_name();\n"
" return to_sender;\n"
"endfunction",
"function return_type[K:0] my_class::method_name();\n"
" return to_sender;\n"
"endfunction",
// out-of-line constructor definitions
"function my_class::new;\n"
"endfunction",
"function my_class::new();\n"
"endfunction",
"function my_class::new;\n"
"endfunction : new",
"function my_class::nested::new;\n"
"endfunction",
"function foo::new (string name, uvm_component parent);\n"
" super.new(name, parent);\n"
"endfunction : new",
// calling array-locator methods
"function void finder;\n"
" a0 = b.find;\n"
" a1 = b.find();\n"
" a2 = x.b.find() with (x < 1);\n"
" a3 = c[j].b.find(x) with (x != 0 && y > 2);\n"
" a4 = x.b.find with (x+y < 1);\n"
" a5 = x.b. find with (x.y < 1);\n"
"endfunction",
"function void finder;\n"
" a1 = b.find_index;\n"
" a2 = x.b.find_index with (x < 1);\n"
" a3 = x.b.find_index() with (x < 1);\n"
" a4 = d.c[j].find_index(x) with (x != z && y > 2);\n"
"endfunction",
"function void finder;\n"
" a0 = b.find_first with (x.y.z);\n"
" a1 = b.find_first();\n"
" a2 = x.b.find_first(item) with (item.count > 1);\n"
" a3 = d.c[j].find_first(x) with (x != z && y > 2);\n"
"endfunction",
"function void finder;\n"
" a0 = b.find_first_index with (x.y.z);\n"
" a1 = b.find_first_index();\n"
" a2 = x.b.find_first_index(item) with (item.count > 1);\n"
" a3 = d.c[j].find_first_index(x) with (x != z && y > 2);\n"
"endfunction",
"function void finder;\n"
" a0 = b.find_last with (x.y.z);\n"
" a1 = b.find_last();\n"
" a2 = x.b.find_last(item) with (item.count > 1);\n"
" a3 = d.c[j].find_last(x) with (x != z && y > 2);\n"
"endfunction",
"function void finder;\n"
" a0 = b.find_last_index with (x.y.z);\n"
" a1 = b.find_last_index();\n"
" a2 = x.b.find_last_index(item) with (item.count > 1);\n"
" a3 = d.c[j].find_last_index(x) with (x != z && y > 2);\n"
"endfunction",
"function void finder;\n"
" a0 = b. min with (x.y.z);\n"
" a1 = b. min();\n"
" a2 = x.b.min(item) with (item.count > 1);\n"
" a3 = d.c[j].min(x) with (x != z && y > 2);\n"
"endfunction",
"function void finder;\n"
" a0 = b. max with (x.y.z);\n"
" a1 = b. max();\n"
" a2 = x.b.max(item) with (item.count > 1);\n"
" a3 = d.c[j].max(x) with (x != z && y > 2);\n"
"endfunction",
"function void finder;\n"
" a0 = b. unique with (x.y.z);\n"
" a1 = b. unique();\n"
" a2 = x.b.unique(item) with (item.count > 1);\n"
" a3 = d.c[j].unique(x) with (x != z && y > 2);\n"
"endfunction",
"function void finder;\n"
" a0 = b. unique_index with (x.y.z);\n"
" a1 = b. unique_index();\n"
" a2 = x.b.unique_index(item) with (item.count > 1);\n"
" a3 = d.c[j].unique_index(x) with (x != z && y > 2);\n"
"endfunction",
"function void sorter;\n"
" b. sort;\n"
" b. sort();\n"
" x.b.sort with (item.count);\n"
" d.c[j].sort(x) with (x + 2);\n"
"endfunction",
"function void rsorter;\n"
" b. rsort;\n"
" b. rsort();\n"
" x.b.rsort with (item.count);\n"
" d.c[j].rsort(x) with (x + 2);\n"
"endfunction",
"function void reverser;\n"
" b. reverse;\n"
" b. reverse();\n"
"endfunction",
"function void shuffler;\n"
" b. shuffle;\n"
" b. shuffle();\n"
"endfunction",
"function void summer;\n"
" a0 = b. sum;\n"
" a1 = b. sum();\n"
" a2 = x.b.sum with (item.count);\n"
" a3 = d.c[j].sum(x) with (x + 2);\n"
"endfunction",
"function void multiplier;\n"
" a0 = b. product;\n"
" a1 = b. product();\n"
" a2 = x.b.product with (item.count);\n"
" a3 = d.c[j].product(x) with (x - 2);\n"
"endfunction",
"function void ander;\n"
" a0 = b. and;\n"
" a1 = b. and();\n"
" a2 = x.b.and with (item.predicate);\n"
" a3 = d.c[j].and(x) with (~x);\n"
"endfunction",
"function void orer;\n"
" a0 = b. or;\n"
" a1 = b. or();\n"
" a2 = x.b.or with (item.predicate);\n"
" a3 = d.c[j].or(x) with (~x);\n"
"endfunction",
"function void xorer;\n"
" a0 = b. xor;\n"
" a1 = b. xor();\n"
" a2 = x.b.xor with (item.predicate);\n"
" a3 = d.c[j].xor(x) with (~x);\n"
"endfunction",
// testing for preprocessor-balanced statements
"function void preprocess_statement_test();\n"
" a0 = b.x;\n"
"`ifdef POINTLESS\n" // empty `ifdef
"`endif\n"
" a1 = b.x;\n"
"endfunction",
"function void preprocess_statement_test();\n"
" a0 = b.x;\n"
"`ifdef POINTLESS\n" // and empty `else
"`else\n"
"`endif\n"
" a1 = b.x;\n"
"endfunction",
"function void preprocess_statement_test();\n"
" a0 = b.x;\n"
"`ifdef POINTLESS\n"
"`elsif DUMB\n" // empty `elsif's
"`elsif DUMBER\n"
"`else\n"
"`endif\n"
" a1 = b.x;\n"
"endfunction",
"function void preprocess_statement_test();\n"
" a0 = b.x;\n"
"`ifdef POINTLESS\n"
" b0 = f(x, y, z);\n" // one statement in clause
"`endif\n"
" a1 = b.x;\n"
"endfunction",
"function void preprocess_statement_test();\n"
" a0 = b.x;\n"
"`ifdef POINTLESS\n"
" b0 = f(x, y, z);\n" // multiple statements in clause
" b1 = g(y, x, z);\n"
"`endif\n"
" a1 = b.x;\n"
"endfunction",
"function void preprocess_statement_test();\n"
" a0 = b.x;\n"
"`ifdef POINTLESS\n"
" b0 = f(x, y, z);\n" // multiple statements in clause
" b1 = g(y, x, z);\n"
"`elsif DUMB\n"
" c0 = pp(x, y);\n" // multiple statements in clause
" c1 = qq(y, x);\n"
"`else\n"
" d0 = fg(\"error\");\n" // multiple statements in clause
" d1 = gf(13);\n"
"`endif\n"
" a1 = b.x;\n"
"endfunction",
"function net_type_decls;\n"
" nettype shortreal analog_wire;\n"
"endfunction\n",
"function net_type_decls;\n"
" nettype foo::bar[1:0] analog_wire with fire;\n"
"endfunction\n",
};
static const ParserTestCaseArray kTaskTests = {
"task task_a;\n"
"endtask",
"task static task_a;\n"
"endtask",
"task automatic task_a;\n"
"endtask",
"task flask;\n"
"input [7:0] intake;\n"
"output [7:0] outtake [3:0];\n"
"endtask",
"task convertCtoF;\n"
"input [7:0] temp_in;\n"
"output [7:0] temp_out;\n"
"begin\n"
" temp_out = ((9/5) *temp_in) + 32;\n"
"end\n"
"endtask",
// interface task
"task intf.task1();\n"
"endtask",
// package import declaration
"task task_a;\n"
" import tb_pkg::*;\n"
"endtask",
"task task_b();\n"
" import tb_pkg::*;\n"
" w_cell cell_q[$];\n"
"endtask",
// various port types
"task spindle;\n"
"input string intake;\n"
"output string [7:0] outtake [3:0];\n"
"endtask",
"task spindle;\n"
"input spkg::StringN#(N) intake;\n"
"output spkg::StringN#(K) [7:0] outtake [3:0];\n"
"endtask",
"task spindle;\n"
"const ref StringType intake;\n" // const ref
"ref StringType [7:0] outtake [3:0];\n" // ref
"endtask",
"task t(virtual foo_if vif);\n"
"endtask\n",
"task t(virtual foo_if#(12) vif);\n"
"endtask\n",
"task t(virtual foo_if#(.W(12)) vif);\n"
"endtask\n",
"task t(virtual interface foo_if vif);\n"
"endtask\n",
"task t(ref virtual foo_if vif);\n"
"endtask\n",
"task t(ref virtual foo_if vifs[]);\n"
"endtask\n",
"task t(ref virtual foo_if vifs[N]);\n"
"endtask\n",
"task t(ref virtual foo_if vifs[N:M]);\n"
"endtask\n",
"task t(ref virtual foo_if vifs[N:M][X:Y]);\n"
"endtask\n",
"task t(ref virtual interface foo_if#(P,Q,R) vifs[N:M][X:Y]);\n"
"endtask\n",
// macro
"task stringer;\n"
" `uvm_error(`gtn, \"frownie =(\")\n" // string with balance character
"endtask",
"task stringer;\n"
" `undef ERROR\n" // preprocessor
"endtask",
// local variables, various qualifiers
"task variable_soup;\n"
"int a_count;\n"
"const int b_count;\n"
"var int c_count;\n"
"static int d_count;\n"
"automatic bool e_enabled;\n"
"const static string incantation;\n"
"static const string cheer = \"Go!\";\n"
"const var automatic string password;\n"
"endtask",
// example referencing globals
"reg [7:0] tempC;\n"
"reg [7:0] tempF;\n"
"task convertCtoF;\n"
"begin\n"
" tempF = ((9/5) *tempC) + 32;\n"
"end\n"
"endtask",
"task swap;\n"
"inout a, b;\n"
"reg temp;\n"
"begin\n"
" temp = a;\n"
" a = b;\n"
" b = temp;\n"
"end\n"
"endtask",
// queue reference
"task queue_or_not_to_queue;\n"
" if(item_to_queue.count < request_queue[$].count) begin\n"
" end\n"
"endtask",
"task queue_or_not_to_queue;\n"
" x_fifo = x_fifo[$-Line_width/2:$];\n"
" t_fifo[line] = t_fifo[line][0:$-Line_width/2];\n"
"endtask",
// expect property statements
"task great_expectations;\n"
" expect ( B |-> C );\n"
" expect ( C |-> A ) else sleep();\n"
"endtask",
// case statements
"task mysterious_case;\n"
"input a;\n"
"output b;\n"
"case (a)\n"
"1: b = 2;\n"
"2-a: b = 3;\n"
"default: b = 4;\n"
"endcase\n"
"endtask",
"task mysterious_casex;\n"
"input a;\n"
"output b;\n"
"casex (a)\n"
"1: b = 2;\n"
"default: b = 4;\n"
"endcase\n"
"endtask",
"task mysterious_casez;\n"
"input a;\n"
"output b;\n"
"casez (a)\n"
"1: b = 2;\n"
"default: b = 4;\n"
"endcase\n"
"endtask",
"task mysterious_case;\n"
"case (a)\n"
"1: b = 2;\n"
"`ifdef MOO\n"
"2-a: b = 3;\n"
"`endif\n"
"`include \"more_cases.sv\"\n" // preprocessing
"default: b = 4;\n"
"endcase\n"
"endtask",
// case-inside statement
"task inside_case;\n"
"case (a) inside\n"
" 6'b00_?1??: select_next = 2'd1;\n"
" 6'b00_?01?: select_next = 2'd2;\n"
" 6'b00_?001: select_next = 2'd3;\n"
"default: select_next = select;\n"
"endcase\n"
"endtask",
"task inside_case;\n"
"case (a) inside\n"
" 1,4,7: select_next = 2'd1;\n"
" 2,5,8: select_next = 2'd2;\n"
" 3,6,9: select_next = 2'd3;\n"
"default: select_next = select;\n"
"endcase\n"
"endtask",
"task inside_case;\n"
"case (a) inside\n"
" [1:3],10,11: select_next = 2'd1;\n"
" [4:6],[12:14]: select_next = 2'd2;\n"
" [7:9]: select_next = 2'd3;\n"
"default: select_next = select;\n"
"endcase\n"
"endtask",
"task inside_case;\n"
"case (a) inside\n"
"`ifdef LOO\n"
" [1:3],10,11: select_next = 2'd1;\n"
"`else\n"
" [4:6],[12:14]: select_next = 2'd2;\n"
"`endif\n"
" [7:9]: select_next = 2'd3;\n"
"default: select_next = select;\n"
"endcase\n"
"endtask",
// randcase statement
"task mysterious_randcase;\n"
"input a;\n"
"output b;\n"
"randcase\n"
"1: b = 2;\n"
"1: b = 4;\n"
"endcase\n"
"endtask",
"task mysterious_randcase;\n"
"randcase\n"
"1: b = 2;\n"
"`ifdef NONDET\n"
"1: b = 4;\n"
"`endif\n"
"endcase\n"
"endtask",
// case-matches statement (patterns)
"task inside_case;\n"
"case (a) matches\n"
" .FooBar: select_next = 4'd0;\n"
" 123: select_next = 4'd1;\n"
" 123 &&& x == y: select_next = 4'd5;\n"
" \"abc\": select_next = 4'd2;\n"
" '{123, \"xyz\", .*}: select_next = 4'd3;\n" // pattern list
" '{X:123, Y:456, Z:.*}: select_next = 4'd4;\n" // member pattern list
" .*: select_next = 4'd9;\n"
" default: select_next = select;\n"
"endcase\n"
"endtask",
"task inside_case;\n"
"case (a) matches\n"
" .FooBar: select_next = 4'd0;\n"
"`ifndef STUFF /* stuff */\n"
" 123: select_next = 4'd1;\n"
"`endif // comment\n"
" 123 &&& x == y: select_next = 4'd5;\n"
" .*: select_next = 4'd9;\n"
"`include \"more_patterns.sv\"\n"
" default: select_next = select;\n"
"endcase\n"
"endtask",
// conditional statement
"task looper();\n"
"if (a && b != c.d)\n"
" continue;\n"
"else if (e < f[g])\n"
" break;\n"
"else\n"
" return j/k;\n"
"endtask",
// dynamic array assignments
"task it_is_dynamic;\n"
" bit[W:0] m_data[] = new[1];\n"
" integer mi_data[][K:0] = new[W](a+b);\n"
"endtask",
"task more_dynamic;\n"
" bit[W:0] m_data[] = new[1], m_data_2[] = new[2];\n"
" integer mi_data[][K:0][L:0] = new[K*L](a+b), b_data = '0;\n"
"endtask",
"task expression_copy;\n"
" match_cmd = new rsrc_wr_q[src][q_to_chk[i]][0];\n" // reference
"endtask",
// assertion statements
"task automatic with_interfaces;\n"
" virtual blah_if blah_if_inst;\n"
" virtual blah_if blah_if_inst[3:0];\n"
" virtual blah_if blah_if_inst1, blah_if_inst2;\n"
" virtual interface blah_if2 blah_if2_inst;\n"
" virtual blah_if3 #(N, M) blah_if3_inst;\n"
"endtask",
// copy (class-new)
"task copy;\n"
" clone = new();\n"
"endtask",
"task copy;\n"
" clone = new(\"Name\", N+1);\n" // positional constructor args
"endtask",
"task copy;\n"
" clone = new(.name(\"Name\"), .size(N));\n" // named constructor args
"endtask",
"task copy(ref seqitem clone);\n"
" clone = new this;\n" // new this
"endtask",
"task catcat;\n"
"agent_pkg::req exp_pkt = new({get_full_name(), \".hello\"});\n"
"endtask",
"task catcat;\n"
"agent_pkg::req exp_pkt = new(get_full_name(), \".hello\");\n" // 2 args
"endtask",
// assertion statements
"task assert_me;\n"
" assert(0);\n"
" assert(epic_fail) $display(\"FAIL.\");\n"
" assert final (wrong && wronger) $display(\"FAIL.\");\n"
" assert #0 (incorrect);\n"
"endtask",
"task assert_me;\n"
" assert(value1 ==? pattern);\n" // wildcard equivalence
" assert(value2 !=? pattern);\n" // wildcard equivalence
"endtask",
"task assume_me;\n"
" assume(counter == 1);\n"
" assume(we_are_good) $display(\"GOOD.\");\n"
" assume final (right || !wrong) $display(\"might makes right.\");\n"
" assume #0 (state_is_valid());\n"
"endtask",
"task cover_me;\n"
" cover(num_eggs == 1);\n"
" cover(we_are_good) $display(\"Yup, good.\");\n"
" cover final (right || !wrong) $display(\"are you covered?\");\n"
" cover #0 (state_is_valid());\n"
"endtask",
"task assert_me;\n"
" assert(good) else bad();\n"
" assert(great) celebrate(); else lament();\n"
" assert(better) begin\n"
" celebrate();\n"
" end else begin\n"
" weep();\n"
" end\n"
"endtask",
"task assume_me;\n"
" assume(good) else bad();\n"
" assume(great) celebrate(); else lament();\n"
" assume(better) begin\n"
" celebrate();\n"
" end else begin\n"
" weep();\n"
" end\n"
"endtask",
// member of method
"task printer;\n"
"r_field().parent().child(status).name().print(stdout);\n"
"endtask",
"task updater;\n"
"write_q[i].r_field.parent().update(status, UVM_FRONTDOOR);\n"
"endtask",
// randomize
"task magic8ball;\n"
" randomize();\n"
" randomize(dice);\n"
" deck.randomize();\n"
" deck.randomize;\n"
" coin.randomize(dice[k]);\n"
"endtask",
"task magic8ball;\n"
" randomize(dice[i]);\n" // vendor extension allows indexed reference
" std::randomize(coin[j]);\n"
"endtask",
"task magic8ball;\n"
" if (!coin.randomize() with {\n"
" r_w > 2;\n"
" bar() == n_y;\n"
" }) begin\n"
" $payout();\n"
" end\n"
"endtask",
"task body_unique;\n"
"value = std::randomize();\n"
"success = std::randomize(interrupt_id) with {\n"
" unique {interrupt_id};\n" // with unique_expression
"};\n"
"endtask",
"task local_ref;\n"
"if (!foo.randomize(interrupt_id) with {\n"
" a.count == local::count;})\n" // with local class qualifier
" `uvm_error();\n"
"endtask",
"task local_ref;\n"
"if (!foo.randomize with { a.count == xyz;})\n"
" `uvm_error(\"oops\");\n"
"endtask",
// out-of-line task member definitions
"task class_name::high_roller;\n"
"endtask",
"task class_name::high_roller();\n"
" roll_dice();\n"
"endtask",
"task class_name::high_roller(input bit loaded);\n"
" if (loaded) begin\n"
" roll_twice();\n"
" end else begin\n"
" roll_dice();\n"
" end\n"
"endtask",
// delay statements
"task waiter;\n"
" #done_timeout;\n" // simple delay value
" `uvm_fatal(`gtn, \"Timeout\");\n"
"endtask",
"task waiter;\n"
" #cfg.done_timeout;\n" // reference
" `uvm_fatal(`gtn, \"Timeout\");\n"
"endtask",
"task waiter;\n"
" #mypkg::done_timeout;\n" // package-scoped reference
" `uvm_fatal(`gtn, \"Timeout\");\n"
"endtask",
// cycle delay statements
"task waiter;\n"
" `uvm_info(\"blah\");\n"
" ## 10;\n"
" ##200 deck.randomize();\n"
" ##Duration;\n"
" `uvm_info(\"done\");\n"
"endtask",
"task schmoo3;\n"
"begin\n"
" z0 <= y;\n" // clocking_drive or nonblocking assignment
" z1 <= ##value yy;\n" // clocking_drive with cycle_delay
" z2 <= ##(value) xx;\n"
" z3 <= ##50 yy;\n"
" z4.dfg[0] <= ##50 ww[1].xx;\n"
"end\n"
"endtask",
"task net_type_decls;\n"
" nettype shortreal analog_wire;\n"
"endtask\n",
"task net_type_decls;\n"
" nettype foo::bar[1:0] analog_wire with fire;\n"
"endtask\n",
// event trigger and logical implication expressions '->'
"task trigger_happy;\n"
" ->e1;\n"
"endtask\n",
"task trigger_happy;\n"
" ;\n" // null
" ->e1;\n"
"endtask\n",
"task trigger_happy;\n"
" ->e1;\n"
" ->e2;\n"
"endtask\n",
"task trigger_happy;\n"
" ->e1;\n"
" g();\n"
" ->e2;\n"
"endtask\n",
"task logical_happy;\n"
" a = f->g;\n"
"endtask\n",
"task mixed_happy;\n"
" ->bb;\n"
" a = f->g;\n"
" ->cc;\n"
"endtask\n",
"task mixed_happy;\n"
" a = f->g;\n"
" ->bb;\n"
" p = q->r;\n"
"endtask\n",
"task mixed_happy;\n"
" if (x)\n"
" ->bb;\n"
"endtask\n",
"task mixed_happy;\n"
" for (int i=0; i<N; ++i)\n"
" ->bb;\n"
"endtask\n",
};
static const ParserTestCaseArray kModuleTests = {
"module modular_thing;\n"
"endmodule",
"module semicolon_madness;;;;;\n"
"endmodule",
"module automatic modular_thing;\n"
"endmodule",
"module modular_thing();\n"
"endmodule",
"module `MODULE_NAME;\n"
"endmodule",
"module `MODULE_NAME1;\n"
"endmodule : `MODULE_NAME1",
"module `MODULE_NAME2;\n"
"endmodule : `MODULE_NAME2\n", // with newline
"module `MODULE_NAME3\n"
" (input foo);\n"
"endmodule",
// K&R-style ports
"module addf (a, b, ci, s, co);\n"
"input a, b, ci;\n"
"output s, co;\n"
"always @(a, b, ci)\n"
"begin\n"
" s = (a^b^ci);\n"
" co = (a&b)|(a&ci)|(b&ci);\n"
"end\n"
"endmodule",
"module addf (a, b, ci, sum, co);\n" // 'sum' not as keyword
"input a, b, ci;\n"
"output sum, co;\n"
"always @(a, b, ci)\n"
"begin\n"
" sum = (a^b^ci);\n"
" co = (a&b)|(a&ci)|(b&ci);\n"
"end\n"
"endmodule",
"module asdf (a[N:0], o);\n"
"input [N:0] a;\n"
"output co;\n"
"endmodule",
"module portlogic (a[N:0], o);\n"
"input logic [N:0] a;\n"
"output logic co;\n"
"endmodule",
"module zoom (a, co);\n"
"input bus_type a;\n"
"output bus_type [3:0] co;\n"
"endmodule",
"module zoom (a, co);\n"
"input somepkg::bus_type a;\n"
"output somepkg::bus_type [3:0] co;\n"
"endmodule",
"module zoomzoom (a, co);\n"
"input somepkg::bus_type #(2*W) a;\n"
"output somepkg::bus_type #(W) [3:0] co;\n"
"endmodule",
"module nonansi_ports_unpacked_array(a, b, c);\n"
"output a;\n"
"input b;\n"
"input c[2:0];\n"
"endmodule",
"module nonansi_ports_unpacked_array(a, b, c);\n"
"output a, a2, a3;\n"
"input b, b2[1:0], b3;\n"
"input c[2:0], c2[N:0], c3[M:N];\n"
"endmodule",
"module nonansi_ports(a, b, c);\n"
"endmodule",
"module nonansi_ports(a[7:4], b[3:0]);\n"
"endmodule",
"module nonansi_ports(a[7:4][1:0], b[3:0][1:0]);\n"
"endmodule",
"module nonansi_ports(.a(), .b(), .c());\n"
"endmodule",
"module nonansi_ports(.a(a), .b(b), .c(c));\n"
"endmodule",
"module nonansi_ports({c, d}, {e, f});\n"
"endmodule",
"module nonansi_ports(.a({c, d}), .b({e, f}));\n"
"endmodule",
"module nonansi_ports({c[3:2], d}, {e, f[1:0]});\n"
"endmodule",
"module nonansi_ports(.x({c[3:2], d}), .y({e, f[1:0]}));\n"
"endmodule",
// full port declarations
"module addf (\n"
"input a, b, ci,\n"
"output s, co);\n"
"always @(a, b, ci)\n"
"begin\n"
" s = (a^b^ci);\n"
" co = (a&b)|(a&ci)|(b&ci);\n"
"end\n"
"endmodule",
"module addf (\n"
"input a, b, ci,\n"
"output sum, co);\n" // 'sum' not as a keyword
"always @(a, b, ci)\n"
"begin\n"
" sum = (a^b^ci);\n"
" co = (a&b)|(a&ci)|(b&ci);\n"
"end\n"
"endmodule",
"module zxc (\n"
"input [3:0] b,\n"
"output co);\n"
"endmodule",
"module qwert (\n"
"intf::in_bus [3:0] b,\n"
"intf::out_bus co);\n"
"endmodule",
"module foo (interface bar_if, interface baz_if);\n" // interface port
"endmodule",
"module foo (interface .fgh bar_if);\n" // interface port
"endmodule",
"module tryme (\n"
"tri1 a,\n"
"tri0 b);\n"
"endmodule",
"module preprocessor_pain (\n"
" input a,\n"
"`ifdef PORT_B\n"
" input b,\n"
"`endif // PORT_B\n"
" input c);\n"
"endmodule",
"module preprocessor_pain (\n"
" input a,\n"
"`ifdef PORT_B\n"
" input b,\n"
"`else // PORT_B\n" // with else clause
" input b2,\n"
"`endif // PORT_B\n"
" input c);\n"
"endmodule",
"module preprocessor_pain (\n"
" input a,\n"
"`ifdef PORT_B\n"
" input b\n" // no trailing comma in both clauses
"`else // PORT_B\n"
" input c\n" // no trailing comma in both clauses
"`endif // PORT_B\n" // preprocessing directive last
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`ifdef PORT_B\n" // preprocessing directive first
" input b1,\n"
" input b2\n"
"`else\n"
" input c1,\n"
" input c2\n"
"`endif\n" // preprocessing directive last
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`ifdef BLAH\n"
"`else\n"
"`endif\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
" output foo,\n"
"`ifdef BLAH\n"
" bar = 1'b1\n" // trailing assign, no comma
"`else\n"
" bar = 1'b0\n"
"`endif\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`ifdef BLAH\n" // non-ANSI style ports
" a,\n"
"`else\n"
" b,\n"
"`endif\n"
" c\n"
" );\n"
"input a;\n"
"input b;\n"
"endmodule",
"module preprocessor_pain (\n"
" a,\n"
"`ifdef BLAH\n" // non-ANSI style ports
" b\n" // no trailing comma
"`else\n"
" c\n"
"`endif\n"
" );\n"
"input a;\n"
"output c;\n"
"endmodule",
"`define BCD b,c,d,\n"
"module preprocessor_pain (\n"
" a,\n"
" `BCD\n" // macro-expanded ports
" e);\n"
"endmodule",
"`define BCD(b,c,d) x,b,c,d,y,\n"
"module preprocessor_pain (\n"
" a,\n"
" `BCD(p,q,r)\n" // macro-expanded ports
" e);\n"
"endmodule",
"module preprocessor_pain (\n"
" output foo,\n"
"`ifdef BLAH\n"
" bar = 1'b1,\n" // trailing assign, with comma
"`else\n"
" bar = 1'b0,\n"
"`endif\n"
" input clk\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
" output foo,\n"
"`ifdef BLAH\n"
" bar = 1'b1,\n" // trailing assign, with comma
"`elsif BLAH2\n" // multiple `elseif clauses
" bar = 2'b0,\n"
"`elsif BLAH3\n"
" bar = `INITBAR,\n"
"`else\n"
" bar = 1'b0,\n"
"`endif\n"
" input clk\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
" output foo,\n"
"`ifdef BLAH\n" // all empty clauses
"`elsif BLAH2\n"
"`elsif BLAH3\n"
"`else\n"
"`endif\n"
" input clk\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`include \"BLAH.svh\"\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`define FOO BAR\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`undef FOO\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
" input foo,\n" // with comma
"`include \"BLAH.svh\"\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
" input foo\n" // without comma
"`include \"BLAH.svh\"\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`include \"BLAH.svh\"\n"
" , output bar\n" // without comma
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`include \"BLAH.svh\"\n"
" , output bar\n" // with comma
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`ifdef V1\n"
"`include \"BLAH_V1.svh\"\n"
"`else\n"
"`include \"BLAH_V2.svh\"\n"
"`endif\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`ifdef V1\n"
"`include \"BLAH_V1.svh\"\n"
"`elsif V2\n"
"`include \"BLAH_V2.svh\"\n"
"`else\n"
"`include \"BLAH_V3.svh\"\n"
"`endif\n"
" );\n"
"endmodule",
"module preprocessor_pain (\n"
"`ifndef V1\n"
"`define FOO\n"
"`include \"BLAH_V1.svh\"\n"
"`endif\n"
" );\n"
"endmodule",
"module clkgen (\n"
" output bit clk=0, input bit run_clock,\n"
" int clock_phase_a, int clock_phase_b,\n" // int port
" int phase_init, bit edge_init);\n"
"endmodule",
"module foo (\n"
" input wire bar);\n" // input wire port
"endmodule",
"module foo (\n"
" input wire bar = 1);\n" // input wire port with trailing assign
"endmodule",
"module foo (\n"
" wire bar);\n" // wire port, no direction
"endmodule",
"module foo (\n"
" wire bar = 1);\n" // wire port, no direction, with trailing assign
"endmodule",
"module foo (\n"
" input real bar);\n" // real port
"endmodule",
"module foo (\n"
" input var i,\n" // var keyword
" output var o);\n"
"endmodule",
"module foo (\n"
" ref int o);\n" // ref declaration
"endmodule",
"module foo (\n"
" ref var o);\n" // ref declaration
"endmodule",
"module foo (\n"
" ref var int o);\n" // ref declaration
"endmodule",
// port connections
"module tryme;\n"
"foo a;\n"
"foo b();\n"
"foo c(x, y, z);\n"
"foo d(.x(x), .y(y), .w(z));\n"
"foo e(x, a, .y(y), .w(z));\n" // positional + named arguments
"endmodule",
"module tryme;\n"
"foo c(sum, product, find);\n" // built-in method names ok as identifiers
"foo d(.sum(sum), .product(product), .find(find));\n"
"foo e(.unique, .unique_index(), .and());\n"
"endmodule",
"module blank_ports;\n"
"s_type xyz(,,,);\n" // blank ports
"bus_type abc(\n"
" sig_A,\n"
" /* blah */,\n"
" sig_C,\n"
" sig_D,\n"
" /* blah */,\n"
" /* blah */\n"
");\n"
"endmodule",
"module preprocessor_love;\n"
"foo d(\n"
"`ifdef CONNECT_X\n"
" .x(x),\n"
"`endif\n"
" .y(y),\n"
" .w(z)\n"
");\n"
"endmodule",
"module preprocessor_love;\n"
"foo d(\n"
" .x(x),\n"
" .y(y),\n"
"`ifdef CONNECT_X\n"
" .w(z)\n"
"`else\n"
" .w(1'b0)\n"
"`endif\n"
");\n"
"endmodule",
"module macro_ports;\n"
" foo bar(\n"
" `my_ports\n"
" );\n"
"endmodule\n",
"module macro_ports;\n"
" foo bar(\n"
" `my_ports()\n"
" );\n"
"endmodule\n",
"module macro_ports;\n"
" foo bar(\n"
" `my_ports // with comment\n"
" );\n"
"endmodule\n",
"module macro_ports;\n"
" foo bar(\n"
" `my_ports() // with comment\n"
" );\n"
"endmodule\n",
"module macro_ports;\n"
" foo bar(\n"
" .a(a),\n"
" `my_ports\n"
" );\n"
"endmodule\n",
"module macro_ports;\n"
" foo bar(\n"
" .a(a),\n"
" `my_ports()\n"
" );\n"
"endmodule\n",
"module macro_ports;\n"
" foo bar(\n"
" `my_ports,\n" // with comma, macro is interpreted as an expression
" .b(b)\n"
" );\n"
"endmodule\n",
"module macro_ports;\n"
" foo bar(\n"
" `my_ports(),\n" // with comma, macro is interpreted as an expression
" .b(b)\n"
" );\n"
"endmodule\n",
#if 0
// TODO(b/36237582): accept macro item in ports, without trailing comma
"module macro_ports;\n"
" foo bar(\n"
" `my_ports()\n"
" .b(b)\n"
" );\n"
"endmodule\n",
#endif
"module cast_with_constant_functions;\n"
"foo dut(\n"
" .bus_in({brn::Num_blocks{$bits(dbg::bus_t)'(0)}}),\n"
" .bus_mid({brn::Num_bits{$clog2(dbg::bus_t)'(1)}}),\n"
" .bus_out(out));\n"
"endmodule",
// keyword tests
"module keyword_identifiers;\n"
"reg branch; // branch is a Verilog-AMS keyword\n"
"input from; // from is a Verilog-AMS keyword\n"
"wire access; // access is a Verilog-AMS keyword\n"
"wire exclude; // exclude is a Verilog-AMS keyword\n"
"Timer timer; // timer is a Verilog-AMS keyword\n"
"High above; // above is a Verilog-AMS keyword (but not below)\n"
"Bee discrete; // discrete is a Verilog-AMS keyword\n"
"banana split; // split is a Verilog-AMS keyword inside connect\n"
"split hairs; // split is a Verilog-AMS keyword inside connect\n"
"merged traffic; // merged is a Verilog-AMS keyword inside connect\n"
"Blood sample; // sample is used in SystemVerilog coverage_event\n"
"connect four; // connect is a Verilog-AMS keyword\n"
"option option; // option is a keyword only inside covergroups\n"
"ddt pesticide; // Verilog-A keyword\n"
"ddx derivative; // Verilog-A keyword\n"
"idt current; // Verilog-A keyword\n"
"idtmod current; // Verilog-A keyword\n"
"table salt; // table is a keyword inside primitives\n"
"Blackjack table;\n"
"swimming bool; // bool is an Icarus Verilog extension\n"
"endmodule",
// net declarations
"module m; wire #(100) x = y,z=k,foo; endmodule\n",
"module m; wire #1.5 x = y; endmodule;\n"
"module m; wire #(100) x = y; endmodule;\n"
"module m; wire [1:0] #1 x = y; endmodule;\n"
"module m; wire signed foo; endmodule\n",
"module m; wire signed [7:0] foo; endmodule\n",
"module m; wire unsigned foo; endmodule\n",
"module m; wire unsigned [7:0][3:0] foo; endmodule\n",
"module m(input wire signed foo); endmodule\n",
"module m(input wire signed [1:0] foo); endmodule\n",
"module m(input wire unsigned foo); endmodule\n",
"module m; wire foo_t foo; endmodule\n",
"module m(wire foo_t foo); endmodule\n",
"module m; wire foo_t [1:0] foo [0:2]; endmodule\n",
"module m(wire foo_t [1:0] foo [0:3]); endmodule\n",
"module m; wire p_pkg::foo_t foo; endmodule\n",
"module m(wire p_pkg::foo_t foo); endmodule\n",
"module m; wire p_pkg::foo_t [2:0] foo [0:1]; endmodule\n",
"module m(wire p_pkg::foo_t [2:0] foo [0:2]); endmodule\n",
"module m; wire continuous; endmodule\n", // Regression #672
"module m; wire infinite; endmodule\n", // infinite also a keyword
"module m; wire slew; endmodule\n", // Regression #753
"interface _if; wire p_pkg::foo_t foo; endinterface\n",
"interface _if; wire p_pkg::foo_t [1:0] foo [0:1]; endinterface\n",
// system task calls
"module caller;\n"
"initial begin\n"
" $warning(\"dangerous.\");\n"
"end\n"
"endmodule",
"module caller;\n"
"generate\n"
" if (width > 2) begin : LBL\n"
" $display(\"Aloha.\");\n"
" end : LBL\n"
"endgenerate\n"
"endmodule",
"module caller;\n"
"generate\n"
" if (width > 2) begin : LBL\n"
" $info(\"Aloha.\");\n"
" $error(\"Panic[%m] %s.\", `STRINGIFY(__name), \"blah\");\n"
" end : LBL\n"
"endgenerate\n"
"endmodule",
// direct assignment
"module addf (\n"
"input a, input b, input ci,\n"
"output s, output co);\n"
"assign s = (a^b^ci);\n"
"assign co = (a&b)|(a&ci)|(b&ci);\n"
"endmodule",
"module foob;\n"
"assign s = a, y[0] = b[1], z.z = c -jkl;\n" // multiple assignments
"endmodule",
"module foob;\n"
"assign `BIT_ASSIGN_MACRO(l1, r1)\n" // as module item
"endmodule",
"module foob;\n"
"assign `BIT_ASSIGN_MACRO(l2, r2);\n" // with semicolon
"endmodule",
"module foob;\n"
"initial begin\n"
"assign `BIT_ASSIGN_MACRO(l1, r1)\n" // as statement item
"end\n"
"endmodule",
"module foob;\n"
"initial begin\n"
"assign `BIT_ASSIGN_MACRO(l2, r2);\n" // with semicolon
"end\n"
"endmodule",
"module mon;\n"
"scoreboard #(.MAX(nf::sliced * nf::depth_c))\n"
" blah2blah (.ivld({rdv,\n"
" $past(rdv, 1, 1'b1, @(posedge clk))}));\n" // $past, event control
"endmodule",
"module mon;\n"
"scoreboard blah2blah (.ivld({rdv,\n"
" $past(rdv,, , @(posedge clk))}));\n" // $past, empty arguments
"endmodule",
"module labeled_statements;\n"
"initial begin\n"
" a = 0;\n"
" foo: b = 0;\n" // with label
"end\n"
"endmodule",
"module labeled_single_statements;\n"
"always_comb\n"
" foo_implies_bar: assert #0 (valid);\n"
"endmodule",
"module labeled_single_statements;\n"
"initial\n"
" foo_implies_bar: assert #0 (valid);\n"
"endmodule",
"module labeled_single_statements;\n"
"final\n"
" foo_implies_bar: assert #0 (valid);\n"
"endmodule",
"module labeled_statements;\n"
"always_comb begin\n"
" foo_implies_bar: assert #0 (valid);\n" // with label
"end\n"
"endmodule",
"module case_statements;\n" // case statements
"always_comb begin\n"
" case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd: w = z;\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements;\n" // unique case statements
"always_comb begin\n"
" unique case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd: w = z;\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements;\n" // unique0 case statements
"always_comb begin\n"
" unique0 case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd: w = z;\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements;\n" // unique0 casex statements
"always_comb begin\n"
" unique0 casex (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd: w = z;\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements;\n" // unique0 casez statements
"always_comb begin\n"
" unique0 casez (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd: w = z;\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements;\n"
"always_comb begin\n"
" case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd: begin\n" // statement block
" y = f(w);\n"
" w = z;\n"
" end\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements_with_preprocessing;\n"
"always_comb begin\n"
" case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd:\n"
"`ifdef ZZZ\n"
" w = z;\n"
"`endif\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements_with_preprocessing;\n"
"always_comb begin\n"
" case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd:\n"
"`ifndef ZZZ\n"
" w = z;\n"
"`endif\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements_with_preprocessing;\n"
"always_comb begin\n"
" case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd:\n"
"`ifdef ZZZ\n"
" w = z;\n"
"`else\n"
" w = q;\n"
"`endif\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements_with_preprocessing;\n"
"always_comb begin\n"
" case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd:\n"
"`ifdef ZZZ\n"
" w = z;\n"
"`elsif YYY\n"
" w = q;\n"
"`endif\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements_with_preprocessing;\n"
"always_comb begin\n"
" case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd:\n"
"`ifdef ZZZ\n"
" w = z;\n"
"`elsif YYY\n"
" w = q;\n"
"`elsif XXX\n"
" w = 1;\n"
"`else\n"
" w = 2;\n"
"`endif\n"
" endcase\n"
"end\n"
"endmodule",
"module case_statements_with_preprocessing;\n"
"always_comb begin\n"
" case (blah.blah)\n"
" aaa,bbb: x = y;\n"
" ccc,ddd:\n"
"`ifdef ZZZ\n" // all empty clauses
"`elsif YYY\n"
"`elsif XXX\n"
"`else\n"
"`endif\n"
" endcase\n"
"end\n"
"endmodule",
// default clocking
"module clock_it;\n"
"default clocking fastclk;\n"
"endmodule",
"module clock_it;\n"
"if (clocked_mode)\n"
" default clocking fastclk;\n"
"endmodule",
// default disable
"module diss;\n"
"default disable iff should_be_disabled;\n"
"default disable iff (x * y < 4);\n"
"endmodule",
"module diss;\n"
"if (shutdown) begin\n"
" default disable iff z >= 9;\n"
" default disable iff (x || y);\n"
"end\n"
"endmodule",
// always_comb
"module comb_stuff;\n"
"always_comb begin\n"
" unique if (d1 == nf::B) begin\n" // unique-if
" data = b_data;\n"
" end\n"
" else if (d1 == nf::H) begin\n"
" data = h_data;\n"
" end\n"
" else begin\n"
" data = 1'b0;\n"
" end\n"
"end\n"
"endmodule",
// assignment expressions
"module rooter;\n"
"initial begin\n"
" $root.xx = yy.zz;\n" // $root
" xx.yy = $root.zz;\n"
"end\n"
"endmodule",
"module yoonary;\n"
"initial begin\n"
" x = ~ ~y;\n"
" z = - -w;\n"
" a = ~^b;\n"
" a = ^~b;\n"
" a = ~|b;\n"
" a = ~&b;\n"
" c = ^~~^&d;\n"
"end\n"
"endmodule",
"module schmoo (\n"
"input [7:0] wr, input [7:0] rd, input clk,\n"
"output wptr, output rptr);\n"
"always @(posedge clk)\n"
"begin\n"
" wptr <= wr ? (wptr == (FDEPTH-1)) ? '0 : (wptr + 1) : wptr;\n"
" rptr <= rd ? (rptr == (FDEPTH-1)) ? '0 : (rptr + 1) : rptr;\n"
"end\n"
"endmodule",
"module schmoo2 (\n"
"input x, input y,\n"
"output z1, output z2, output z3, output z4, output z5);\n"
"always @*\n"
"begin\n"
" z1 <= #value y;\n"
" z2 <= #(value) x;\n"
" z3 <= #50 y;\n"
" z4 <= #20ps x;\n"
" z5 <= #(20ps) y;\n"
"end\n"
"endmodule",
"module assigner;\n"
" initial begin\n"
" n1 <= @(negedge k) r1;\n" // nonblocking assign, edge
" end\n"
"endmodule\n",
"module assigner;\n"
" initial begin\n"
" n1 = @(negedge k) r1;\n" // blocking assign, edge
" end\n"
"endmodule\n",
"module assigner;\n"
" initial begin\n"
" n1 <= @foo r1;\n" // nonblocking assign, event control
" end\n"
"endmodule\n",
"module assigner;\n"
" initial begin\n"
" n2 = @bar r1;\n" // blocking assign, event control
" end\n"
"endmodule\n",
"module assigner;\n"
" initial begin\n"
" n1 <= repeat(k) @foo r1;\n" // nonblocking assign, repeat control
" end\n"
"endmodule\n",
"module assigner;\n"
" initial begin\n"
" n2 = repeat(k) @bar r1;\n" // blocking assign, repeat control
" end\n"
"endmodule\n",
"module triggerer;\n"
" initial\n"
" ->a;\n" // blocking event trigger
"endmodule\n",
"module triggerer;\n"
" final\n"
" ->a;\n" // blocking event trigger
"endmodule\n",
"module triggerer;\n"
" always\n"
" ->a;\n" // blocking event trigger
"endmodule\n",
"module triggerer;\n"
" always_ff\n"
" ->a;\n" // blocking event trigger
"endmodule\n",
"module triggerer;\n"
" always_comb\n"
" ->a;\n" // blocking event trigger
"endmodule\n",
"module triggerer;\n"
" always_latch\n"
" ->a;\n" // blocking event trigger
"endmodule\n",
#if 0
// TODO(b/171362636): lexical context needs to understand event_control
"module triggerer;\n"
" always @*\n"
" ->a;\n" // blocking event trigger
"endmodule\n",
"module triggerer;\n"
" always @(posedge clk)\n"
" ->a;\n" // blocking event trigger
"endmodule\n",
#endif
"module triggerer;\n"
" always @(posedge clk) begin\n"
" ->a;\n" // blocking event trigger
" end\n"
"endmodule\n",
"module triggerer;\n"
" always @* begin\n"
" ->a;\n" // blocking event trigger
" x = 0;\n"
" end\n"
"endmodule\n",
"module triggerer;\n"
" always @* begin\n"
" ->a.b[1].c;\n" // blocking event trigger
" x = 0;\n"
" end\n"
"endmodule\n",
"module triggerer;\n"
" always @* begin\n"
" ->>c;\n" // nonblocking event trigger
" end\n"
"endmodule\n",
"module triggerer;\n"
" always @* begin\n"
" ->> #5 c;\n" // nonblocking event trigger, delayed
" end\n"
"endmodule\n",
"module triggerer;\n"
" always @* begin\n"
" ->> @(posedge y) c;\n" // nonblocking event trigger, edge
" end\n"
"endmodule\n",
"module triggerer;\n"
" always @* begin\n"
" ->> repeat(2) @foo c;\n" // nonblocking event trigger, repeat
" end\n"
"endmodule\n",
// streaming concatenations with macros
"module streaming_cats;\n"
"assign s1 = {>>`BAR};\n"
"assign s2 = {>>`BAR(foo)};\n"
"assign s3 = {>>16 `BAR};\n"
"assign s4 = {>>32 `BAR(foo)};\n"
"assign s5 = {>>`WIDTH `BAR};\n"
"assign s6 = {>>`WIDTH `BAR(foo)};\n"
"endmodule",
// assignment using logical implication expressions
"module logical_implication;\n"
"logic a, b, c;\n"
"assign a = b -> c;\n"
"endmodule",
"module logical_implication;\n"
" initial\n"
" a = b -> c;\n"
"endmodule",
"module logical_implication;\n"
" initial begin\n"
" a = b -> c;\n"
" end\n"
"endmodule",
"module logical_implication;\n"
" initial\n"
" a = (b -> c);\n"
"endmodule",
"module logical_implication;\n"
" initial\n"
" a = (b -> c) & (d -> e);\n"
"endmodule",
"module logical_implication;\n"
" initial\n"
" {x, y} = {b -> c, d -> e};\n"
"endmodule",
"module logical_implication;\n"
" final\n"
" a = (b -> c) & (d -> e);\n"
"endmodule",
"module logical_implication;\n"
" final begin\n"
" a = (b -> c) & (d -> e);\n"
" end\n"
"endmodule",
"module logical_implication;\n"
" always @* begin\n"
" a <= b -> c;\n"
" end\n"
"endmodule",
"module logical_implication;\n"
" always @* begin\n"
" a <= b -> c || (f->g);\n"
" end\n"
"endmodule",
// if-else
"module ifelsey ();\n"
" if (i==0) begin\n"
" end\n"
"endmodule",
"module ifelsey ();\n"
" if (i.f==0) begin\n"
" end else begin\n"
" end\n"
"endmodule",
"module ifelsey ();\n"
" if (func()) begin\n"
" end else begin\n"
" end\n"
"endmodule",
"module ifelsey ();\n"
" if (obj.func()) begin\n"
" end else begin\n"
" end\n"
"endmodule",
"module ifelsey ();\n"
" if (pkg::func()) begin\n"
" end else begin\n"
" end\n"
"endmodule",
// function calls
"module funky ();\n"
"initial begin\n"
" func2(1'b0);\n"
" pkg::func3(1'b0, \"joe\");\n"
" void'(obj.func(chicken, dinner));\n"
"end\n"
"endmodule",
"module funky ();\n"
"initial begin\n"
" func();\n"
" func2(.val(1'b0));\n"
" func3(.val(1'b0), .name(\"joe\"));\n"
" obj.func();\n"
" pkg::func();\n"
" void'(pkg::func());\n"
" void'(obj.func(chicken));\n"
"end\n"
"endmodule",
"module funky ();\n"
"initial begin\n"
" func1(0, .x());\n"
" func2(1'b0, 13, .narg1(1'b1));\n"
" pkg::func3(1'b0, \"joe\", .z(), .y(foo.bar));\n"
" void'(obj.func(chicken, dinner, .knife(spoon.handle)));\n"
"end\n"
"endmodule",
"module funkier ();\n"
"initial begin\n"
" cls #(Z)::func1(a, b, c);\n"
" pkg::cls #(Z)::func2(1, 2, 3);\n"
" cls #(virtual t_if)::func3(a, b, c);\n" // interface parameter type
" cls #(virtual interface t_if.mp)::func4(a, b, c);\n" // with modport
"end\n"
"endmodule",
"module preprocessor_revenge ();\n"
"initial begin\n"
" func1(\n"
"`ifndef BLAH\n" // preprocessor directives
" a,\n"
"`endif // BLAH\n"
" b,\n"
" .x()\n"
");\n"
"end\n"
"endmodule",
"module preprocessor_revenge ();\n"
"initial begin\n"
" func1(zzz, yyy,\n"
"`ifndef BLAH\n" // preprocessor directives
" a\n"
"`else // BLAH\n"
" b,\n"
" .x(ccc + 1)\n"
"`endif // BLAH\n"
");\n"
"end\n"
"endmodule",
// special functions: randomize
"module randomizer ();\n"
"initial begin\n"
" randomize;\n"
" std::randomize;\n"
" void'(std::randomize);\n"
" void'(randomize(flt) with {flt[k:0] == '0;});\n"
" void'(randomize(null));\n"
" void'(randomize(x, y, z) with (b, c) {flt[k:0] == '0;});\n"
" void'(std::randomize with (b, c) {});\n"
" void'(std::randomize with (bb) {\n"
" c < z;\n"
" w + 2;\n"
" });\n"
"end\n"
"endmodule",
"module randomizer ();\n"
"initial begin\n"
" randval = std::randomize(dur) with {\n"
" dur >= mind;\n"
" dur <= maxd;\n"
" dur + c <= cfg.max_dur;\n"
" };\n"
"end\n"
"endmodule",
"module randomizer ();\n"
"initial begin\n"
" randval = std::randomize(dur) with {\n"
"`ifdef CONDITION\n"
" dur >= mind;\n"
"`else\n"
" dur <= maxd;\n"
"`endif\n"
" dur <= maxd;\n"
" dur + c <= cfg.max_dur;\n"
" };\n"
"end\n"
"endmodule",
"module randomizer ();\n"
"initial begin\n"
" randval = std::randomize(del) with {\n"
" del >= mind && del <= maxd;\n"
" !(del inside {bad_dels});\n"
" };\n"
"end\n"
"endmodule",
"module randomizer ();\n"
"initial begin\n"
" randval = std::randomize(foo) with {\n"
" foo inside {a, b, c};\n"
" foo dist { a<2 };\n"
" };\n"
"end\n"
"endmodule",
"module randomizer ();\n"
"initial begin\n"
" randval = !std::randomize(foo) with {\n"
" if (foo.e == 0) foo.f == 0;\n"
" if (foo.e == 1) foo.f[j] != 1; else foo[k].f > g;\n"
" };\n"
"end\n"
"endmodule",
"module randomizer ();\n"
"initial begin\n"
" foo.randomize();\n"
"end\n"
"endmodule",
// inside expression
"module insider ();\n"
"initial begin\n"
" ranges = {a, b, c};\n"
" lval = foo inside ranges;\n" // grammar extension to LRM
"end\n"
"endmodule",
"module insider ();\n"
"initial begin\n"
" int slice[$] = '{3, 4, 5};\n"
" lval = ex inside {1, 2, slice};\n"
"end\n"
"endmodule",
// task calls
"module task_caller;\n"
"initial begin\n"
" undefined_task();\n"
" undefined_task(\"hello\", \"world\");\n"
" undefined_task(.str(\"goodbye\"), .greet(\"world\"));\n"
"end\n"
"endmodule",
/* FIXME:
// seen this "pkg#(N)::func()" construct in our verilog source code,
// but having difficulty supporting it without causing grammar conflicts.
// This *looks* like a package parameter, but I haven't found an
// official description.
"module ifelsey ();\n"
" if (pkg #(42)::func()) begin\n"
" end else begin\n"
" end\n"
"endmodule",
*/
// for loops and conditionals
"module addf ();\n"
"generate\n"
" for (i=0;i<N;i++) begin\n"
" end\n"
"endgenerate\n"
"endmodule",
"module addf ();\n"
"generate\n"
" for (genvar i=0;i<N;i++) begin\n" // genvar
" end\n"
"endgenerate\n"
"endmodule",
"module addf ();\n"
"generate\n"
" for (genvar i=0; ;i++) begin\n" // no loop condition
" end\n"
"endgenerate\n"
"endmodule",
"module loopit ();\n"
"generate\n"
" for (i=0;i<N;) begin\n" // no for-step
" end\n"
"endgenerate\n"
"endmodule",
"module loopit ();\n"
"initial begin\n"
" for (i=0;i<N;) begin\n" // no for-step
" end\n"
"end\n"
"endmodule",
"module loopit ();\n"
"initial begin\n"
" for (i=0; ;i++) begin\n" // no loop condition
" end\n"
"end\n"
"endmodule",
"module semi ();\n"
"generate\n"
" ;;;;;;\n"
"endgenerate\n"
"endmodule",
"module semi ();\n"
"generate\n"
" let max(a,b) = (a > b) ? a : b;\n" // let declaration
"endgenerate\n"
"generate\n"
" begin\n"
" let max(a,b) = (a > b) ? a : b;\n" // let declaration
" end\n"
"endgenerate\n"
"endmodule",
"module shifter ();\n"
"generate\n"
" for (i=0;i<N;i++,j--) begin\n" // multiple step assignments
" end\n"
"endgenerate\n"
"endmodule",
"module addf ();\n"
"generate for (i=0;i<N;i++) begin : loop_name\n"
"end\nendgenerate\n"
"endmodule",
"module addf ();\n"
"generate for (i=0;i<N;i++) loop_name : begin\n"
"end\nendgenerate\n"
"endmodule",
"module addf ();\n"
"generate for (i=0;i<N;i++) begin : loop_name\n"
"end : loop_name\nendgenerate\n"
"endmodule",
"module addf ();\n"
"generate if (x < y) begin : cond_name\n"
"end\nendgenerate\n"
"endmodule",
"module addf ();\n"
"generate if (x < y) begin : cond_name\n"
"end : cond_name\nendgenerate\n"
"endmodule",
"module addf ();\n"
"generate\n"
" for (i=0;i<N;i+=1) begin : myloop\n"
" end\n"
" for (j=0;j<N;j+=1) begin : myloop2\n"
" end : myloop2\n"
" for (genvar k=0;k<N;++k) begin : myloop3\n"
" end : myloop3\n"
"endgenerate\n"
"endmodule",
"module macmac ();\n"
"generate if (x < y) begin : cond_name\n"
" logic upipe;\n"
" `FF(a, b, c, d)\n" // macro call
" `undef FF\n"
"end : cond_name\nendgenerate\n"
"endmodule",
"module wiry ();\n"
"generate\n"
" if (need_more_wires) begin\n"
" wire happy_net;\n"
" wire nappy_net [3:0];\n"
" wire slappy_net = 1'b0;\n"
" wire zappy_net = 1'b1, yappy_net = 1'b0;\n"
" end\n"
"endgenerate\n"
"endmodule",
// foreach
"module oneforall;\n"
"initial begin\n"
" foreach ( foo[i] )\n"
" func(foo[i]);\n"
"end\n"
"endmodule",
"module oneforall;\n"
"initial begin\n"
" foreach ( foo[i,j,k] )\n"
" func(foo[i,j,k]);\n"
"end\n"
"endmodule",
"module oneforall;\n"
"initial begin\n"
" foreach ( foo[,j,k] )\n"
" func(foo[j,k]);\n"
" foreach ( bar[] )\n"
" func();\n"
" foreach ( bar1[,] )\n"
" func();\n"
" foreach ( bar2[row,] )\n"
" func();\n"
" foreach ( bar3[,col] )\n"
" func();\n"
"end\n"
"endmodule",
"module oneforall;\n"
"initial begin\n"
" foreach ( this.foo[j] )\n"
" func(this.foo[j]);\n"
"end\n"
"endmodule",
"module oneforall;\n"
"initial begin\n"
" foreach ( super.bar[i][j,k] )\n"
" func(super.baz[i][j,k]);\n"
"end\n"
"endmodule",
// wire decls
"module foobar ();\n"
"wire x0;\n"
"wire x1, x2, x3;\n"
"wire [N-1:0] x4;\n"
"wire x5[2:0];\n"
"wire [7:0] x6[2:0];\n"
"wire sometype x7;\n"
"wire sometype x8[2:0];\n"
"wire sometype [7:0] x9;\n"
"wire sometype [7:0] x10[2:0];\n"
"endmodule",
// fifo decls
"module qoobar;\n"
"QueueValue x0 [$];\n"
"QueueValue y0 [$:N+1];\n"
"endmodule",
// intermediate value wires
"module addf (\n"
"input a, input b, input ci,\n"
"output s, output co);\n"
"wire x1, x2, x3;\n"
"wire x4 = x1;\n"
"assign x1 = a*b;\n"
"assign x2 = a*ci;\n"
"assign x3 = b*ci;\n"
"assign s = a^b^ci;\n"
"assign co = x1 +x2 +x3;\n"
"endmodule",
"module foobarf (\n"
"input [1:0] a,\n"
"input [1:0] b,\n"
"output [1:0] c);\n"
"wire [1:0] #delay d = a ^ b;\n"
"assign #delay c = d;\n"
"endmodule",
// using logic primitives
"module addf (\n"
"input a, b, ci,\n"
"output s, co);\n"
"wire x1, x2, x3, p;\n"
"and a0(a, b, x1);\n"
"and a1(a, c1, x2);\n"
"and a2(b, c1, x3);\n"
"or o1(x1, x2, x3, co);\n"
"xor y1(a, b, p);\n"
"xor y2(ci, p, s);\n"
"endmodule",
// with localparam in parameter ports
"module foo #(\n"
"localparam bar = 2\n"
") (\n"
"output reg zzz[bar-1:0]);\n"
"endmodule",
// with localparam in body
"module rotator ();\n"
"localparam foo = 2;\n"
"localparam larry = 1, curly = 2, moe = 3;\n"
"localparam bar [1:0] = '{1, 2};\n"
"localparam [3:0] baz = 4'ha;\n"
"localparam [1:0] ick [2:0] = '{'{0,1},'{1,2},'{2,3}};\n"
"endmodule",
// with parameter
"module signer;\n"
"parameter int M = 4;\n"
"parameter int unsigned N = 5;\n"
"parameter int signed O = 6;\n"
"parameter int unsigned [M-1:0] P = {0,1,2,3};\n"
"endmodule",
"module paramtest #();\n" // empty parameters
"endmodule",
"module paramtest #(int M);\n" // without default value
"endmodule",
"module paramtest #(int M, N);\n"
"endmodule",
"module paramtest #(int M, int N);\n"
"endmodule",
"module paramtest #(int M=4);\n"
"endmodule",
"module paramtest #() ();\n" // empty parameter, empty ports
"endmodule",
"module paramtest #(int M=4) ();\n"
"endmodule",
"module signerer #(\n"
"parameter int M = 4,\n"
"parameter int unsigned N = 5,\n"
"parameter int signed O = 6,\n"
"parameter int unsigned [M-1:0] P = {3,2,1,0}\n"
");\n"
"endmodule",
"module rotator ();\n"
"parameter foo = 2;\n"
"parameter reg [7:0] foo = 2;\n"
"parameter larry = 1, curly = 2, moe = 3;\n"
"parameter PType _larry_ = 0;\n"
"parameter bar [1:0] = '{1, 2};\n"
"parameter PType bar2 [1:0] = '{1, 2};\n"
"parameter [3:0] baz = 4'ha;\n"
"parameter [1:0] ick [2:0] = '{'{0,1},'{1,2},'{2,3}};\n"
"parameter Ptype2 [3:0] bazzy = 4'ha;\n"
"parameter Ptype2 [1:0] icky [2:0] = '{'{0,1},'{1,2},'{2,3}};\n"
"endmodule",
"module rotator;\n"
"parameter foo = `WWW 'hfeedf00d;\n" // macro-id as width
"endmodule",
// type parameters
"module rotator ();\n"
"localparam type Foo;\n"
"localparam type Goo = Zoo#(V, W, X);\n"
"localparam type Koo, Loo, Moo;\n"
"parameter type Woo;\n"
"parameter type Yoo = MMM::TPP, Xoo = JJJ::KKK::LLL;\n"
"parameter type Zoo = Zoo#(V, W, X)::BusType;\n"
"endmodule",
// with parameter (keyword and type optional)
"module rotator #(parameter width=8) (\n"
"input clk,\n"
"output reg [width-1:0] out);\n"
"always @(posedge clk)\n"
" out <= {out[0], out[width-1:1]};\n"
"endmodule",
"module rotator #(width=8) (\n"
"input clk,\n"
"output reg [width-1:0] out);\n"
"endmodule",
"module rotator #(integer width=8) (\n"
"input clk,\n"
"output reg [width-1:0] out);\n"
"endmodule",
"module rotator #(parameter integer width=8) (\n"
"input clk,\n"
"output reg [width-1:0] out);\n"
"endmodule",
// with parameters
"module rotator #(\n"
"parameter width=8, dir=0\n"
") (\n"
"input clk,\n"
"output reg [width-1:0] out);\n"
"always @(posedge clk)\n"
" if (dir) out <= {out[0], out[width-1:1]};\n"
" else out <= {out[width-2:0], out[width-1]};\n"
"endmodule",
// with user-defined type parameter
"module biggerinter #(parameter SomeEnumType mode=DefaultMode) (\n"
"input clk,\n"
"output reg out);\n"
"endmodule",
"module biggerinter\n"
" #(parameter yourpkg::EnumType mode=DefaultMode) (\n"
" input clk,\n"
" output reg out);\n"
"endmodule",
// type parameters
"module typer #(\n"
" parameter type Mtype\n"
") ();\n"
"endmodule",
"module typer #(\n"
" parameter type Mtype = X::Y,\n"
" parameter type Qtype = X::ZZ #(NA, NB),\n"
" parameter type Ztype = integer\n"
") ();\n"
"endmodule",
"module typer #(\n"
" type Mtype = X::Y,\n"
" type Qtype = ZZ #(.NA(A), .NB(B)),\n"
" type Ztype = bit\n"
") ();\n"
"endmodule",
"module typer #(\n"
" parameter type Mtype = type(Xtype)\n"
") ();\n"
"endmodule",
// type references
"module type_reffer;\n"
"real a = 4.76;\n"
"var type(a) c;\n"
"endmodule\n",
"module type_reffer;\n"
"wreal a;\n"
"wreal b = 4.76;\n"
"endmodule\n",
"module type_reffer;\n"
"real a = 4.76;\n"
"real b = 0.74;\n"
"var type(a+b) c;\n"
"endmodule\n",
"module type_reffer;\n"
"type(a) c;\n"
"endmodule\n",
"module type_reffer;\n"
"type(a::b) c;\n"
"endmodule\n",
"module type_reffer;\n"
"type(f()) c;\n"
"endmodule\n",
"module type_reffer;\n"
"type(f(x)) c;\n"
"endmodule\n",
"module type_reffer;\n"
"type(f(x, y)) c;\n"
"endmodule\n",
"module type_reffer;\n"
"type(a::b()) c;\n"
"endmodule\n",
"module type_reffer;\n"
"type(type(a)) c;\n"
"endmodule\n",
"module preprocessor_in_parameters #(\n"
" parameter int M = 4\n"
"`ifdef MORE_PARAMS\n" // preprocessor directive
" , parameter int N = 8\n"
"`endif // MORE_PARAMS\n"
") ();\n"
"endmodule",
"module preprocessor_in_parameters #(\n"
"`ifdef MORE_PARAMS\n" // preprocessor directive
" parameter int M = 4,\n"
"`endif // MORE_PARAMS\n"
" parameter int N = 8\n"
") ();\n"
"endmodule",
"module preprocessor_in_parameters #(\n"
"`ifdef MORE_PARAMS\n" // preprocessor directive
" parameter int M = 4,\n"
" parameter int N = 8\n"
"`endif // MORE_PARAMS\n"
") ();\n"
"endmodule",
// passing subinstance parameter
"module rotator #(parameter width=8) (\n"
"input clk,\n"
"output reg [width-1:0] out);\n"
"foo #(.WIDTH(width)) bar(clk, out);\n"
"endmodule",
"module spammer;\n"
"foo #(.clk) bar;\n"
"foo #(bit) bar0();\n"
"foo #(.ValType(integer)) bar1();\n"
"foo #(.ValType(virtual t_if)) barif1();\n" // interface type
"foo #(virtual interface t_if) barif2();\n" // interface type
"foo #(logic[N:0][k:0], integer[1:0]) bar2();\n"
"foo #(.ValType(logic[N:0][k:0]), .Val2Type(bit[2:0])) bar3();\n"
"foo #($, $) bar4();\n"
"foo #(.XYZ($), .ABC($)) bar5();\n"
"endmodule",
"module spammer;\n"
"foo #(`VALUE1,\n" // macro-id expression
" `VALUE2,\n" // macro-id expression
" `VALUE3\n" // macro-id expression (MacroGenericItem)
") bar_x0();\n"
"endmodule",
"module splammer;\n"
"foo #(`FUNC(a, 1),\n" // macro-call expression
" `FUNC(b, 2),\n" // macro-call expression
" `FUNC(c, 4)\n" // macro-call expression (MacroGenericItem)
") bar_y0();\n"
"endmodule",
"module parameter_conditioner;\n"
"foo #(.A(1),\n"
"`ifdef HAVE_B\n" // preprocessing directive
" .B(2),\n"
"`endif\n"
" .C(8))\n"
" bar_y0();\n"
"endmodule",
"module parameter_conditioner;\n"
"foo #(\n"
"`ifdef HAVE_B\n" // preprocessing directive
" .B(2),\n"
" .C(8)\n"
"`endif\n"
") bar_y0();\n"
"endmodule",
// package::type
"module foobar (\n"
"mypackage::type1 ins,\n"
"mypackage::type2 outs,\n"
"mypackage::type2 [3:0] more_outs\n"
");\n"
"endmodule",
"module goobar (\n"
"mypackage::myclass::type1 ins,\n" // nested class type
"mypackage::myclass::type2 outs\n"
");\n"
"endmodule",
"module hoobar (\n"
"mypackage::type1 #(1,2) ins,\n" // parameterized type
"mypackage::type2 outs\n"
");\n"
"module goobar (\n"
"mypackage::myclass #(4)::type1 ins, ctrls,\n" // template class member
"mypackage::myclass::type2 outs\n"
");\n"
"endmodule\n"
"endmodule",
"module foobar (\n"
"input mypackage::type1 ins,\n"
"output mypackage::type2 outs,\n"
"output mypackage::type2 [N-1:0] more_outs\n"
");\n"
"endmodule",
// interface.modport
"module barfoo (\n"
"myinterface.mymodport1 ins,\n"
"myinterface.mymodport2 [N-1:0] outs\n"
");\n"
"endmodule",
// import export
"import thatpkg::thing;\n"
"module import_tax;\n"
"endmodule",
"module import_tax\n"
" import thatpkg::thing;\n"
"();\n" // empty ports
"endmodule",
"module import_tax\n"
" import thatpkg::thing;\n"
"#() ();\n" // empty parameters and empty ports
"endmodule",
"module import_tax\n"
" import thatpkg::*;\n" // wildcard
"();\n"
"endmodule",
"module import_tax\n"
" import thispkg::blah, thatpkg::*;\n" // multiple imports
"();\n"
"endmodule",
"module import_tax\n"
" import thispkg::blah;\n" // separate imports
" import thatpkg::*;\n"
"();\n"
"endmodule",
"module import_tax\n"
" import thispkg::blah, baz::*;\n"
" import thatpkg::*, another_one::foobar;\n"
"#(int p = 4) (input clk);\n"
"endmodule",
"import thatpkg::*;\n"
"module import_tax;\n"
"endmodule",
"module barzoo ();\n"
"import pkg::ident;\n"
"export \"name\" task rabbit;\n"
"endmodule",
"import \"DPI\" function bar;\n",
"import \"DPI-C\" function bar;\n",
"import \"DPI-C\" foo = function bar;\n",
"import \"DPI-C\" foo = function void bar;\n",
"import \"DPI-C\" foo = function void bar();\n",
"import \"DPI-C\" foo = function void bar(input chandle ch);\n",
// using escaped identifier as alias:
"import \"DPI-C\" \\foo = function void bar(input chandle ch);\n",
"import \"DPI-C\" `foo = function void bar(input chandle ch);\n", // macro
"import \"DPI-C\" foo = function longint unsigned bar(input chandle "
"ch);\n",
"module zoobar ();\n"
"import \"DPI-C\" function void fizzbuzz (\n"
" input in val, output int nothing);\n"
"endmodule",
"module woobar ();\n"
"import \"DPI-C\" context function void fizzbuzz (\n"
" input in val, output int nothing);\n"
"endmodule",
"module zoofar ();\n"
"export \"DPI-C\" function twiddle;\n"
"endmodule",
"module zoofar ();\n"
"export \"DPI-C\" function void twiddle;\n"
"endmodule",
"module toofar ();\n"
"export \"DPI-C\" task swiddle;\n"
"endmodule",
// attributes (ignored)
"(* war=peace, freedom=slavery, ignorance=strength *)\n"
"module moofar;\n"
"(*\n"
"lexer ignores this for now\n"
"*)\n"
"(*******)\n"
"(**)\n"
"endmodule",
// macro calls
"module moofar;\n"
" `DFF(c, d, q)\n" // as a module_item or block_item
"endmodule",
"module moofar;\n"
" `ASSERT (True == False)\n"
" `ASSERT (Ignorance == Strength);\n" // with semicolon
" initial begin end\n"
" `COVER (your, a__)\n"
"endmodule",
"module moofar;\n"
"initial `WAIT(for_it)\n"
"initial begin\n"
" `SLEEP(duration)\n" // as a statement
" `SLEEP(duration);\n" // with semicolon
"end\n"
"endmodule",
"module moofar;\n"
"initial begin\n"
" xyz = `SLEEP(duration);\n" // as an expression
" abc[`INDEX(2)] = jkl;\n" // as an index
"end\n"
"endmodule",
// event control
"module moofar;\n"
"always @ (*) begin end\n"
"always @ (*) begin end\n"
"endmodule",
"module noofar;\n"
"always @ doo.xyz begin end\n"
"always @ (foo.xyz) begin end\n"
"endmodule",
"module poofar;\n"
"always @ (xyz, bar.bq) begin end\n"
"endmodule",
"module qoofar;\n"
"always @ (posedge xyz, negedge bar.bq) begin end\n"
"endmodule",
"module qoofar;\n"
"always @ (posedge xyz iff bar.bq) begin end\n" // trailing iff
"endmodule",
"module qoofar;\n"
"always_ff @(posedge(clk) iff rst_clk == 1'b0) begin\n"
"end\n"
"endmodule",
// assignment patterns
"module assignment_test1;\n"
"initial begin\n"
" xx = \'{a, b, c};\n"
" xy = \'{4{a}};\n"
" xz = \'{4{a, b}};\n"
"end\n"
"endmodule",
"module assignment_test2;\n"
"initial begin\n"
" x1 = \'{default:0};\n"
" x[2] = \'{int:1};\n"
" x3 = \'{byte:127,bit:1};\n"
" x4 = \'{bool:1};\n"
" x5 = \'{bit:0};\n"
"end\n"
"endmodule",
"module assignment_test3;\n"
"initial begin\n"
" xx = byte\'{a, b, c};\n"
"end\n"
"endmodule",
// struct literals
"module struct_literal;\n"
"always_comb begin\n"
" x = t_foo\'{bar: 0, boo: 1};\n"
"end\n"
"endmodule\n",
// assertion items
"module assertion_items;\n"
"assert property ( A + B <= C );\n"
"triangle1: assert property ( A + B >= C );\n"
"assert property ( A + C <= B ) do_something();\n"
"assume property ( C + B <= A ) do_something_else();\n"
"assume property ( C + B <= A ) /* do nothing */;\n"
"rect1: cover property ( D + B <= A ) do_something2();\n"
"restrict property ( D <= E );\n"
"endmodule",
"module assumption_items;\n"
"assert property ( A + B <= C ) else give_up();\n" // with else clause
"triangle1: assert property ( A + B >= C ) else give_up();\n"
"endmodule",
"module cover_sequences;\n"
"cover sequence ( F );\n"
"cover sequence ( @(posedge gg) F );\n"
"cover sequence ( disable iff (kill_this) sequence_expr_H );\n"
"cover sequence ( @x.y disable iff (kill_that) sequence_expr_J );\n"
"endmodule",
// temporal property expressions
"module props;\n"
" assert property (nexttime x > y);\n"
" assert property (nexttime [11] x > z);\n"
" assert property (s_nexttime w < y);\n"
" assert property (s_nexttime [12] w < z);\n"
"endmodule",
"module props;\n"
" assert property (always x > y);\n"
" assert property (always [11:$] x > z);\n"
" assert property (s_always [12:15] w < z);\n"
"endmodule",
"module props;\n"
" assert property (eventually [8:$] z);\n"
" assert property (s_eventually y);\n"
" assert property (s_eventually [9:14] w);\n"
"endmodule",
"module props;\n"
" assert property (s_eventually always y);\n"
" assert property (always s_eventually z);\n"
"endmodule",
// bind directives
"module bind_me;\n"
"bind dut.rtl.mm ib_if ib_if_inst ();\n"
"bind dut.rtl.ff tc_c tc_c_inst (.clk(clk_tc), .*);\n"
"endmodule",
// encrypted contents
"module secrets;\n"
"`protected\n"
"(*&^%$#1aALkc@!!@#$%^&*(a8sayasd\n"
"87y&*H*!@9FbnASDLCZ)HYgyGYh@#BH)72361^&*\n"
"`endprotected\n"
"endmodule",
"module secrets;\n"
"//pragma protect begin_protected\n"
"(*&^%$#1aALkc@!!@#$%^&*(a8sayasd\n"
"87y&*H*!@9FbnASDLCZ)HYgyGYh@#BH)72361^&*\n"
"//pragma protect end_protected\n"
"endmodule",
// timescale directives
"`timescale 1ns / 1ns\n"
"module modular_thing;\n"
"endmodule",
"`timescale `DEFAULT_TIMESCALE\n" // unexpanded macro
"module modular_thing;\n"
"endmodule",
"`ifdef FOO\n"
"`timescale 1ns / 1ns\n"
"`else\n"
"`timescale 100 ps / 100 ps\n" // with spaces before unit
"`endif\n"
"module modular_thing;\n"
"endmodule",
"`timescale 100 ps / 100 ps\n" // with spaces before unit
// celldefine directives
"`celldefine\n"
"module modmod;\n"
"endmodule\n"
"`endcelldefine\n"
"`celldefine\n"
"module modmod2;\n"
"endmodule\n"
"`endcelldefine\n",
"`resetall\n"
"`pragma black magic\n"
"module startover;\n"
"endmodule",
"`unconnected_drive pull0\n"
"module startover;\n"
"endmodule\n"
"`nounconnected_drive",
"`default_decay_time 99\n"
"`default_trireg_strength 64\n"
"module blank;\n"
"endmodule",
"`default_nettype wire\n"
"module blank;\n"
"endmodule",
"`default_nettype none\n"
"module blank;\n"
"endmodule\n"
"`default_nettype tri\n"
"module blank;\n"
"endmodule",
"`default_nettype supply0\n"
"`default_nettype supply1\n"
"`default_nettype tri0\n"
"module blank;\n"
"endmodule",
"`suppress_faults\n"
"`nosuppress_faults\n"
"module blank;\n"
"endmodule",
"`enable_portfaults\n"
"`disable_portfaults\n"
"module blank;\n"
"endmodule",
"`delay_mode_distributed\n"
"`delay_mode_path\n"
"`delay_mode_unit\n"
"`delay_mode_zero\n"
"module blank;\n"
"endmodule",
"`begin_keywords \"1364-2005\"\n"
"module blank;\n"
"endmodule\n"
"`end_keywords",
"`uselib lib=foo libext=.vv\n"
"module blank;\n"
"endmodule",
"module blank;\n"
"`protect\n"
"wire secret;\n"
"`endprotect\n"
"endmodule",
// specify block
"module specify_recmem_tests;\n"
"specify\n"
" $recrem (posedge ASYNC_R, posedge CE1_TCLK,\n"
" `REC_TIME, `REM_TIME);\n"
"endspecify\n"
"endmodule",
"module specify_recmem_tests;\n"
"specify\n"
" $recrem (negedge ASYNC_R, posedge CE0_TCLK &&& (ZZZ==1'b1),\n"
" `REC_TIME, `REM_TIME);\n"
"endspecify\n"
"endmodule",
"module specify_recmem_tests;\n"
"specify\n"
" $recrem (edge ASYNC_R, edge CE1_TCLK,\n"
" `REC_TIME, `REM_TIME);\n"
"endspecify\n"
"endmodule",
"module specify_recmem_tests;\n"
"specify\n"
" $recrem (ASYNC_R, CE1_TCLK &&& (YYY==1'b0),\n"
" `REC_TIME, `REM_TIME);\n"
"endspecify\n"
"endmodule",
"module specify_recmem_tests;\n" // with edge specifiers
"specify\n"
" $recrem (edge ASYNC_R, edge [ 01, 0x ] CE1_TCLK &&& (YYY==1'b0),\n"
" `REC_TIME, `REM_TIME);\n"
"endspecify\n"
"endmodule",
"module specparams_test;\n"
"specify\n"
" specparam PATHPULSE$ = ( 0, 0.001 );\n"
" specparam tCD = (`CM_ACCESS);\n"
"`ifdef SQUASHING\n"
" specparam tHOLD = (`CM_ACCESS);\n"
"`else\n"
" specparam tHOLD = (`CM_RETAIN);\n"
"`endif\n"
"endspecify\n"
"endmodule",
// preprocessor balanced module items
"module pp_mod;\n"
"`ifdef MONEY\n"
"`endif // MONEY\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifdef MONEY\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifndef MONEY\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifndef MONEY\n"
"`else // MONEY\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifndef MONEY\n"
"`elsif BROKE\n"
"`else // MONEY\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifdef MONEY\n"
"`elsif BROKE\n"
"`elsif BROKER\n"
"`else // MONEY\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifdef MONEY\n"
"wire sender;\n"
"wire [2:0] receiver;\n"
"`elsif BROKE\n"
"`elsif BROKER\n"
"`else // MONEY\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifdef MONEY\n"
"`elsif BROKE\n"
"wire sender;\n"
"wire [2:0] receiver;\n"
"`else // MONEY\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifdef MONEY\n"
"`elsif BROKE\n"
"`else // MONEY\n"
"wire sender;\n"
"wire [2:0] receiver;\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
"module pp_mod;\n"
"wire transfer;\n"
"`ifdef MONEY\n"
"`else // MONEY\n"
"wire sender;\n"
"wire [2:0] receiver;\n"
"`endif // MONEY\n"
"assign receiver = transfer;\n"
"endmodule",
// preprocessor balanced generate items
"module balancer_generator;\n"
"generate\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`define BAR FOO\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`undef BAR\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n" // empty `ifdef
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n" // empty `ifdef
"`define BARRY\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
" clocker clkr;\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n" // two items
" clocker clkr;\n"
" clicker clkr;\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifndef BAR\n" // empty `ifndef
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifndef BAR\n"
" clicker clkr;\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifndef BAR\n" // two items
" clicker clkr;\n"
" clacker clkr;\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`else\n" // empty `else clause
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifndef BAR\n"
"`else\n" // empty `else clause
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`elsif BLARG\n" // empty `elsif clause
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`elsif BLARG\n" // empty `elsif clause
"`elsif ZERG\n" // second `elsif
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifndef BAR\n"
"`elsif BLARG\n" // empty `elsif clause
"`elsif ZERG\n" // second `elsif
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`elsif BLARG\n" // `elsif clause
" wire frame;\n"
" wire line;\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`elsif BLARG\n" // `elsif clause
" wire frame;\n"
" wire line;\n"
"`else\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`elsif BLARG\n" // `elsif clause
"`else\n"
" wire frame;\n"
" wire line;\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`elsif BLARG\n"
"`undef DEF\n"
"`else\n"
" wire frame;\n"
" wire line;\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`ifdef NESTED\n" // nested `ifdef
" wire frame;\n"
" wire line;\n"
"`endif\n"
"`endif\n"
"endgenerate\n"
"endmodule",
"module balancer_generator;\n"
"generate\n"
"`ifdef BAR\n"
"`elsif BLARG\n"
"`else\n"
"`ifdef NESTED\n" // nested `ifdef
" wire frame;\n"
" wire line;\n"
"`endif\n"
"`endif\n"
"endgenerate\n"
"endmodule",
// Test for +: and -: operators in declarations:
"module gen #(parameter width = 3) ();\n"
" wire [base +: width] x;\n"
" wire [base -: width] y;\n"
" wire [base : width] z;\n"
"endmodule",
"module gen #(parameter width = 3)\n"
" (out, in1, in2);\n"
" output [0 +: width] out;\n"
" input [2 -: width] in1, in2;\n"
"endmodule",
"module gen #(parameter width = 3) (\n"
" output [0 +: width] out,\n"
" input [2 -: width] in1, in2\n"
");\n"
"endmodule",
// begin-end blocks at module level are not LRM-valid,
// but are diagnosed by the linter:
"module foobar;\n"
" begin\n"
" end\n"
"endmodule",
"module foobar;\n"
" begin : block\n"
" end : block\n"
"endmodule",
"module foobar;\n"
" begin\n"
" wire crossed;\n"
" end\n"
"endmodule",
"module foobar;\n"
" begin begin\n"
" end end\n"
"endmodule",
};
static const ParserTestCaseArray kModuleInstanceTests = {
"module tryme;\n"
"logic lol;\n" // is a data_declaration
"wire money;\n" // is a net_declaration
"endmodule",
"module tryme;\n"
"foo a;\n" // looks like data_declaration
"endmodule",
"module tryme;\n"
"foo b();\n"
"endmodule",
"module tryme;\n"
"foo c(x, y, z);\n"
"endmodule",
"module tryme;\n"
"foo d(.x(x), .y(y), .w(z));\n"
"endmodule",
// multiple instances in one declaration, comma-separated
"module tryme;\n"
"foo b(),\n"
" c();\n"
"endmodule",
"module macro_as_type;\n"
"`foo b();\n"
"endmodule",
"module macro_as_instance;\n"
"foo `bar();\n"
"endmodule",
"module macro_as_instance;\n"
"foo `bar ();\n"
"endmodule",
"module macro_as_instance;\n"
"foo `bar (\n"
");\n"
"endmodule",
"module macro_as_instance;\n"
"foo `bar [1:0] ();\n"
"endmodule",
"module macro_as_instance;\n"
"foo `bar(x, y, z);\n" // positional ports as macro args
"endmodule",
"module macro_as_instance;\n"
"foo `bar(.x(x), .y(y), .z(z));\n" // named ports as macro args
"endmodule",
"module macro_as_instance;\n"
"foo `bar1(), `bar2();\n" // multiple macro instances
"endmodule",
};
static const ParserTestCaseArray kInterfaceTests = {
"interface Face;\n"
"endinterface",
"interface Face;\n"
"endinterface : Face",
"interface automatic Face;\n"
"endinterface",
"interface Bus;\n"
"logic [7:0] Addr, Data;\n"
"logic RWn;\n"
"endinterface",
"interface Bus;\n"
"input logic clk;\n"
"ref logic [7:0] Addr, Data;\n"
"ref logic RWn;\n"
"endinterface",
"interface foo_if;\n"
"logic [7:0] Addr, Data;\n"
"modport logic_if(output addr, output data);\n"
"modport test_if(input addr, input data);\n"
"endinterface",
"interface harness_if\n"
" #(string name = \"anon\");\n" // string parameter
"endinterface",
"interface blah_if(\n"
" input bit clk,\n"
" output bit run_clock,\n"
" edge_init = 0,\n" // initial value
" rst);\n"
"endinterface",
"interface state_if #(parameter W=2)\n"
" (input wire clk, inout wire state);\n"
"endinterface",
// modport declarations
"interface foo_if;\n"
" modport a(input x);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport a(input x);\n"
" modport b(output z);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport a(input x, y, z);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport a(input x), b(output y);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport a(input x, y, output w, z);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport b(clocking c);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport a(import x);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport a(import x, y);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport a(export x);\n"
"endinterface : foo_if",
"interface foo_if;\n"
" modport a(export x, y);\n"
"endinterface : foo_if",
R"(//second modport port is task
interface conduit_if;
logic something;
modport dut(output something, export task task1());
modport tb (input something, import task task1());
endinterface : conduit_if
)",
// TODO(b/115654078): module declarations with preprocessing directives
// clocking declarations
"interface state_if #(parameter W=2)\n"
" (input wire clk, inout wire state);\n"
"clocking mst @(posedge clk);\n"
" output state = ~foo;\n"
"endclocking\n"
"clocking pss @(posedge clk);\n"
" input state;\n"
"endclocking : pss\n"
"endinterface",
"interface state_if #(parameter W=2)\n"
" (input wire clk, inout wire state);\n"
"clocking @(posedge clk);\n" // anonymous clocking block
" output state = ~foo;\n"
"endclocking\n"
"clocking @(negedge clk);\n" // anonymous clocking block
" input state;\n"
"endclocking : pss\n"
"endinterface",
"interface state_if\n"
" (input wire clk, inout wire state);\n"
"clocking mst @clk;\n"
" output state;\n"
"endclocking\n"
"default clocking pss @(a, b, c);\n"
" input state;\n"
"endclocking\n"
"endinterface",
"interface state_if\n"
" (input wire clk, inout wire state);\n"
"clocking @clk;\n" // anonymous clocking block
" output state;\n"
"endclocking\n"
"default clocking @(a, b, c);\n" // anonymous clocking block
" input state;\n"
"endclocking\n"
"endinterface",
"interface state_if\n"
" (input wire clk, inout wire state);\n"
"global clocking mst @clk;\n"
"endclocking\n"
"default clocking pss @(edge ac);\n"
"endclocking\n"
"endinterface",
"interface state_if\n"
" (input wire clk, inout wire state);\n"
"global clocking @clk;\n" // anonymous clocking block
"endclocking\n"
"default clocking @(edge ac);\n" // anonymous clocking block
"endclocking\n"
"endinterface",
"interface clocker(input logic clk);\n"
"logic rst_n;\n"
"clocking tb @(posedge clk);\n"
" default input #1step output negedge;\n"
"endclocking\n"
"endinterface",
// interface port types
"interface blah_if(interface clk_if, data_if);\n"
"endinterface",
"interface blah_if(interface.foo clk_if, data_if);\n"
"endinterface",
};
static const ParserTestCaseArray kTypedefTests = {
"typedef i_am_a_type_really;",
"typedef reg[3:0] quartet;",
"typedef reg quartet[3:0];",
"typedef reg[1:0] quartet[1:0];",
"typedef enum { RED, GREEN, BLUE } colors;",
"typedef union { int i; bool b; } bint;",
"typedef struct { int i; bool b; } mystruct;",
"typedef struct { int i, j, k; bool b, c, d; } mystruct;",
"typedef some_other_type myalias;",
"typedef data_t my_array_t [k:0][j:0];",
"typedef data_t my_array_t [ * ];", // need spaces for now
"typedef data_t my_array_t [bit];",
"typedef data_t my_array_t [bit[31:0]];",
"typedef data_t my_ar_t [bit[31:0][k:0]][bit[j:0][l:0]];",
"typedef some_package::some_type myalias;",
"typedef struct packed {\n"
" [4:0] some_member;\n"
"} mystruct_t;",
"typedef struct packed {\n"
" logic [4:0] some_member;\n"
"} mystruct_t;",
"typedef struct packed {\n"
" apkg::type_member #(N, M) [P:0] some_member;\n"
"} mystruct_t;",
"typedef struct {\n"
" rand bit i;\n"
" randc integer b[k:0];\n"
"} randstruct;",
"typedef enum logic {\n"
" Global = 4'h2,\n"
" Local = 4'h3\n"
"} myenum_fwd;",
"typedef enum logic[3:0] {\n"
" Global = 4'h2,\n"
" Local = 4'h3\n"
"} myenum_fwd;",
"typedef enum bit[3:0][7:0] {\n"
" Global = 4'h2,\n"
" Local = 4'h3\n"
"} myenum_fwd;",
"typedef enum uvec8_t {\n"
" Global = 4'h2,\n"
" Local = 4'h3\n"
"} myenum_fwd;",
"typedef enum yourpkg::num_t {\n"
" Global = 4'h2,\n"
" Local = 4'h3\n"
"} myenum_fwd;",
"typedef struct {\n"
" int sample;\n"
" int tile;\n"
"} tuple_t;",
// typedef with preprocessor directives
"typedef struct packed {\n"
" reg [A-1:0] addr;\n"
" reg [D-1:0] data;\n"
"`ifndef FOO\n"
" reg [E-1:0] ecc;\n"
"`endif // `ifndef FOO\n"
" reg [M-1:0] mask;\n"
" reg parity;\n"
"} req_t;",
"typedef enum {\n"
"`ifdef TWO\n"
" Global = 4'h2,\n"
"`else\n"
" Global = 4'h1,\n"
"`endif\n"
" Local = 4'h3\n"
"} myenum_fwd;",
"typedef enum {\n"
" Global = 4'h2,\n"
"`ifdef TWO\n"
" Local = 4'h2\n"
"`else\n"
" Local = 4'h1\n"
"`endif\n"
"} myenum_fwd;",
};
// typedefs as forward declarations
static const ParserTestCaseArray kStructTests = {
"typedef struct mystruct_fwd;",
// anonymous structs:
"struct { int i; bit b; } foo;",
"struct packed { int i; bit b; } foo;",
"struct packed signed { int i; bit b; } foo;",
"struct packed unsigned { int i; bit b; } foo;",
};
static const ParserTestCaseArray kEnumTests = {
"typedef enum myenum_fwd;",
};
static const ParserTestCaseArray kUnionTests = {
"typedef union myunion_fwd;",
// anonymous unions:
"union { int i; bit b; } foo;",
"union packed { int i; bit b; } foo;",
"union packed signed { int i; bit b; } foo;",
"union packed unsigned { int i; bit b; } foo;",
"union tagged { int i; bit b; } foo;",
"union tagged packed { int i; bit b; } foo;",
"union tagged packed signed { int i; bit b; } foo;",
"union tagged packed unsigned { int i; bit b; } foo;",
};
// TODO(fangism): implement and test ENUM_CONSTANT
// packages
static const ParserTestCaseArray kPackageTests = {
"package mypkg;\n"
"endpackage",
"package automatic mypkg;\n"
"endpackage",
"package static mypkg;\n"
"endpackage",
"package mypkg;\n"
"parameter size = 4;\n"
"endpackage",
"package mypkg;\n"
"typedef class myclass;\n"
"endpackage",
"package mypkg;\n"
"task sleep;\n"
"endtask\n"
"endpackage",
"package mypkg;\n"
"class myclass;\n"
"endclass\n"
"endpackage",
"package semicolons_galore;\n"
";;;;;\n"
"endpackage",
// top-level parameters
"localparam real foo = 789.456;\n",
"localparam shortreal foo = 123.456;\n",
"localparam realtime foo = 123.456ns;\n",
"package foos;\n"
" localparam real foo = 789.456;\n"
" localparam shortreal foo = 123.456;\n"
" localparam realtime foo = 123.456ns;\n"
"endpackage : foos\n",
// `macro call
"`include \"stuff.svh\"\n"
"`expand_stuff()\n"
"`expand_with_semi(name);\n" // with semicolon
"`expand_more(name)\n"
"package macro_call_as_package_item;\n"
"endpackage",
// preprocessor
"package mypkg;\n"
"`undef FOBAR\n"
"endpackage",
// let declarations
"let War = Peace;\n"
"package mypkg;\n"
"endpackage",
"package mypkg;\n"
"let War = Peace;\n"
"endpackage",
"package mypkg;\n"
"let Three() = One + Two;\n"
"endpackage",
"package mypkg;\n"
"let Max(a,b) = (a > b) ? a : b;\n"
"endpackage",
"package mypkg;\n"
"let Max(a,b=1) = (a > b) ? a : b;\n"
"endpackage",
"package mypkg;\n"
"let Max(untyped a, bit b=1) = (a > b) ? a : b;\n"
"endpackage",
// global variables
"int foobar;\n"
"static electricity zap;\n" // variable lifetime
"automatic transmission vehicle;\n"
"package mypkg;\n"
"endpackage",
"virtual a_if b_if;\n", // global virtual interface declaration
"virtual a_if b_if, c_if;\n", // global virtual interface declaration
"package p;\n"
" virtual a_if b_if;\n" // global virtual interface declaration
"endpackage : p\n",
"package p;\n"
" virtual a_if b_if, d_if;\n"
"endpackage : p\n",
"package p;\n"
" uint [x:y] g = 2;\n" // user-defined type, packed dimensions
"endpackage\n",
"package p;\n"
" uint [x][y] g = 2;\n" // user-defined type, packed dimensions
"endpackage\n",
"package p;\n"
" uint [x:y] g[z] = 2;\n" // user-defined type, packed+unpacked dimensions
"endpackage\n",
// import directives
"package foo;\n"
"import $unit::skynet;\n"
"import $unit::*;\n"
"endpackage",
"package important;\n"
"import your_pkg::foo;\n"
"import her_pkg::*;\n"
"import secret_pkg::item1, secret_pkg::item2, spkg::bar;\n"
"endpackage",
"import \"DPI-C\" function void fizzbuzz (\n"
" input in val, output int nothing);\n"
"export \"DPI-C\" function twiddle;\n"
"package nothing_here;\n"
"endpackage",
// export directives
"package foo;\n"
"export bar::baz;\n"
"endpackage",
"package foo;\n"
"export bar::*;\n"
"endpackage",
"package foo;\n"
"export *::*;\n"
"endpackage",
"package foo;\n"
"export bar::xx, baz::yy, goo::*, zoo::zz;\n"
"endpackage",
"package foo;\n"
"import bar::*;\n"
"export bar::*;\n"
"endpackage",
// parameter declarations
"package foo;\n"
"parameter reg[BITS:0] MR0 = '0;\n"
"endpackage",
// bind directive tests (just piggy-backing on package tests)
"bind scope_x type_y z (.*);\n"
"package bindme;\nendpackage\n",
"bind scope_x type_y z1(.*), z2(.*);\n"
"package bindme;\nendpackage\n",
"bind module_scope : inst_x type_y inst_z(.*);\n"
"package bindme;\nendpackage\n",
"bind module_scope : inst_x type_y::a inst_z(.*);\n"
"package bindme;\nendpackage\n",
"bind module_scope : inst_x type_y::a#(4,3) inst_z(.*);\n"
"package bindme;\nendpackage\n",
"bind module_scope : inst_x1, inst_x2 type_y inst_z(.*);\n"
"package bindme;\nendpackage\n",
"bind module_scope : inst_x1.www, inst_x2.zz[0] type_y inst_z(.*);\n"
"package bindme;\nendpackage\n",
"bind module_scope : inst_x1.www, inst_x2.zz[0] type_y z1(.*), z2(.*);\n"
"package bindme;\nendpackage\n",
// preprocessor balanced package items
"package pp_pkg;\n"
"`ifdef DEBUGGER\n" // empty
"`endif\n"
"endpackage",
"package pp_pkg;\n"
"`ifdef DEBUGGER\n"
"`ifdef VERBOSE\n" // nested, empty
"`endif\n"
"`endif\n"
"endpackage",
"package pp_pkg;\n"
"`ifndef DEBUGGER\n" // `ifndef
"`endif\n"
"endpackage",
"package pp_pkg;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
"`endif\n"
" int router_size;\n"
"endpackage",
"package pp_pkg;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
" string source_name;\n" // single item
"`endif\n"
" int router_size;\n"
"endpackage",
"package pp_pkg;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
" string source_name;\n" // multiple items
" string dest_name;\n"
"`endif\n"
" int router_size;\n"
"endpackage",
"package pp_pkg;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
" string source_name;\n"
" string dest_name;\n"
"`else\n" // `else empty
"`endif\n"
" int router_size;\n"
"endpackage",
"package pp_pkg;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
" string source_name;\n"
" string dest_name;\n"
"`elsif LAZY\n" // `elsif empty
"`endif\n"
" int router_size;\n"
"endpackage",
"package pp_pkg;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
"`elsif LAZY\n" // `elsif with multiple items
" string source_name;\n"
" string dest_name;\n"
"`endif\n"
" int router_size;\n"
"endpackage",
"package pp_pkg;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
"`elsif BORED\n"
" string source_name;\n"
" string dest_name;\n"
"`elsif LAZY\n" // second `elsif
"`endif\n"
" int router_size;\n"
"endpackage",
"package pp_pkg;\n"
" int num_packets;\n"
"`ifdef DEBUGGER\n"
"`elsif BORED\n"
"`else\n" // `else with multiple items
" string source_name;\n"
" string dest_name;\n"
"`endif\n"
" int router_size;\n"
"endpackage",
// net_type_declarations
"nettype shortreal foo_wire;\n",
"nettype real foo_wire;\n",
"nettype real foo_wire with bar;\n",
"nettype real foo_wire with bar::baz;\n",
"nettype logic[3:0] foo_wire with bar;\n",
"package p;\n"
" nettype real foo_wire;\n"
"endpackage\n",
"package p;\n"
" nettype shortreal[2] foo_wire with fire;\n"
"endpackage\n",
"package p;\n"
" nettype foo_pkg::bar_t baz_wire;\n"
"endpackage\n",
"package p;\n"
" nettype foo#(x,y,z)::bar_t baz_wire;\n"
"endpackage\n",
"package p;\n"
" nettype foo#(x,y,z)::bar_t[2:0] baz_wire;\n"
"endpackage\n",
"package p;\n"
" nettype foo#(x,y,z)::bar_t baz_wire with quux;\n"
"endpackage\n",
};
static const ParserTestCaseArray kDescriptionTests = {
// preprocessor balanced top-level description items
"`ifdef DEBUGGER\n" // empty
"`endif\n",
"`ifdef DEBUGGER\n"
"`ifdef VERBOSE\n" // nested, empty
"`else\n"
"`endif\n"
"`endif\n",
"`ifndef DEBUGGER\n" // `ifndef
"`endif\n",
"`ifdef DEBUGGER\n"
"`else\n" // `else with multiple items
"`endif\n",
"`ifdef DEBUGGER\n"
"`elsif BORED\n"
"`else\n" // `else with multiple items
"`endif\n",
"`ifdef DEBUGGER\n"
"`elsif BORED\n"
"`elsif MORE_BORED\n"
"`else\n" // `else with multiple items
"`endif\n",
"`ifdef DEBUGGER\n" // module declaration (not a package item)
"module mymod;\n"
"endmodule\n"
"`endif\n",
"`ifdef DEBUGGER\n"
"module mymod;\n"
"endmodule\n"
"module mymod_different;\n" // multiple module declarations
"endmodule\n"
"`endif\n",
"`ifdef DEBUGGER\n" // package declaration (not a package item)
"package mypkg;\n"
"endpackage\n"
"`endif\n",
"`ifdef FPGA\n"
"`ifdef DEBUGGER\n" // nested `ifdef
"module mymod;\n"
"endmodule\n"
"`endif\n"
"`endif\n",
"`ifdef FPGA\n"
"`ifndef DEBUGGER\n" // `ifndef
"interface myinterface;\n"
"endinterface\n"
"`endif\n"
"`endif\n",
"`ifdef DEBUGGER\n"
"`MACRO(stuff, morestuff)\n"
"`endif\n",
"`ifdef DEBUGGER\n"
"`MACRO(stuff, morestuff)\n"
"`SCHMACRO()\n" // multiple macros
"`endif\n",
"package foo_pkg;\n"
"endpackage\n"
"`ifdef F00\n"
"`MACRO(stuff)\n"
"`endif\n",
"package foo_pkg;\n"
"endpackage\n"
"`ifdef F00\n"
"`MACRO(stuff)\n"
"`endif\n"
"module foo_mod;\n"
"endmodule\n",
"`ifdef ASIC\n"
"module module_asic;\n"
"endmodule\n"
"`else // ASIC\n"
"module module_fpga;\n"
"endmodule\n"
"`endif // ASIC\n",
"`ifdef ASIC\n"
"module module_asic;\n"
"endmodule\n"
"`elsif FPGA // ASIC\n"
"module module_fpga;\n"
"endmodule\n"
"`endif // ASIC\n",
"`ifdef ASIC_OR_FPGA\n"
"module module_asic;\n"
"endmodule\n"
"module module_fpga;\n"
"endmodule\n"
"`else\n"
"`endif\n",
"`ifndef ASIC_OR_FPGA\n"
"`else\n"
"module module_asic;\n"
"endmodule\n"
"module module_fpga;\n"
"endmodule\n"
"`endif\n",
};
static const ParserTestCaseArray kSequenceTests = {
"sequence myseq;\n"
" a != b\n"
"endsequence\n",
"sequence myseq;\n"
" a != b\n"
"endsequence : myseq\n", // end label
"sequence myseq;\n"
" a != b;\n" // semicolon
"endsequence\n",
"sequence myseq();\n" // empty port list
" a >= b\n"
"endsequence\n",
"sequence myseq(\n"
" type_a a,\n" // non-empty port list
" xpkg::type_g g,\n"
" sequence bb,\n"
" untyped cc[2:0],\n"
" int fgh = '1,\n"
" local type_b b,\n"
" local inout type_z z,\n"
" local input pkgf::type_y y,\n"
" local output pkgf::type_g#(H) gg\n"
");\n"
" a == b\n"
"endsequence\n",
"sequence myseq();\n"
" logic [3:0] idx;\n" // assertion variable declaration
" a >= b\n"
"endsequence\n",
"sequence myseq();\n"
" var logic [3:0] idx;\n" // assertion variable declaration
" a >= b\n"
"endsequence\n",
"sequence myseq();\n"
" logic idx = '0;\n" // with assignment
" a >= b\n"
"endsequence\n",
"sequence myseq();\n"
" logic idx = '0, bar = 1;\n" // with assignments
" a >= b\n"
"endsequence\n",
};
static const ParserTestCaseArray kPropertyTests = {
"property ready_follows_valid_bounded_P;\n"
" @(posedge clk) disable iff (reset)\n"
" valid |-> eventually [0:Bound] (ready);\n"
"endproperty",
"property myprop;\n"
"a < b\n"
"endproperty\n",
"property myprop;\n"
"a < b;\n"
"endproperty\n",
"property myprop;\n"
"a < b\n"
"endproperty : myprop\n",
"property myprop(\n"
" type_a a,\n"
" xpkg::type_g g,\n"
" sequence b,\n"
" untyped c,\n"
" property d\n"
");\n"
"a < b\n"
"endproperty\n",
"property myprop(int a);\n"
" valid |-> eventually [1:2] a (ready)\n"
"endproperty\n",
"property myprop(\n"
" local int a = foo,\n"
" local input bit b,\n"
" int c[2:0]\n"
");\n"
"a > b\n"
"endproperty\n",
"property myprop(\n"
" local type_a a = foo,\n"
" local input type_b b = 1,\n"
" type_c c[2:0]\n"
");\n"
"a > b\n"
"endproperty\n",
"property myprop(\n"
" foo_a a,\n"
" foo_b b\n"
");\n"
"var bool c;\n"
"var bool d, e;\n"
"var bool f=2, g=a+b;\n"
"a > b\n"
"endproperty\n",
"property myprop;\n"
"##1 selected |-> a != 0;\n"
"endproperty\n",
"property myprop;\n"
"##1 selected |-> $myfunc((a & ~b) != 0);\n"
"endproperty\n",
"property myprop;\n"
"##1 selected |-> a(j(k)) == b[c[d]];\n"
"endproperty\n",
"property myprop;\n"
"identifier[xyz] |-> a && b;\n"
"endproperty\n",
"property myprop;\n"
"identifier[xyz] |-> a[a(f, g, h)] && b;\n"
"endproperty\n",
"property myprop;\n"
"identifier[xyz] |-> a[a(f, g, h)] && b;\n"
"endproperty\n",
"property myprop;\n"
"(xx |=> !xx);\n" // extra parens
"endproperty\n",
"property myprop;\n"
"##1 $fell(s_idle) |-> $past($rose(sched_z));\n"
"endproperty\n",
"property myprop;\n"
"##1 xx |-> (yy || zz);\n"
"endproperty\n",
"property myprop;\n"
"(##1 xx |-> (yy || zz));\n" // extra parens
"endproperty\n",
"property myprop;\n"
"yy ##1 ww |-> $past(xx);\n"
"endproperty\n",
"property myprop;\n"
"##1 xx |-> (yy || zz)\n"
"and yy ##1 ww |-> $past(xx)\n"
"and xx |=> !xx;\n"
"endproperty\n",
"property myprop;\n"
" zp_s |-> s_cos == $past(z_cn) ##1 !zp_s;\n"
"endproperty\n",
"property myprop;\n"
" ssz |=> !ssz && !ssi && ssg ##1 !ssg;\n"
"endproperty\n",
"property myprop;\n"
" !zp |=> $stable(sch) && $stable(sco);"
"endproperty\n",
"property myprop;\n"
" ##2 g0 && !abr |-> $past(davs != 0, 2);\n"
"endproperty\n",
"property myprop;\n"
" logic [3:0] idx;\n"
" 1\n" // property_spec (expression) required
"endproperty\n",
"property myprop;\n"
" logic [3:0] idx;\n"
" z ##0 y |=> strong(a ##1 b);\n"
"endproperty\n",
"property myprop;\n"
" logic [3:0] idx;\n"
" X && (Y != 4)\n"
" ##0\n"
" (a & ~b) == 0\n"
" |=>\n"
" strong(f && g\n"
" ##1 !b && w[r] && $onehot(f)\n"
" ##0 p || q throughout g [->1]\n"
" ##1 g_x);\n"
"endproperty\n",
"property myprop;\n"
" if (w) y |=> strong(a ##1 b);\n"
"endproperty\n",
"property myprop;\n"
" if (w) y else qq;\n"
"endproperty\n",
"property myprop;\n"
" if (w) y else qq |=> j or k;\n"
"endproperty\n",
"property myprop_seq_match;\n"
" (a, b = c);\n"
"endproperty\n",
"property myprop_seq_match;\n"
" (a, b = c);\n"
"endproperty\n",
"property myprop_seq_match;\n"
" (a && d ##0 q == r, b = c[4:0]);\n"
"endproperty\n",
"property myprop_seq_match;\n"
" (a, b = c) |-> weak(j);\n"
"endproperty\n",
// Test for disambiguation of logical implication -> operator.
"property run_thing(start_seq, end_state);\n"
"start_seq\n"
"|->\n"
"(response_valid -> yyy)\n" // -> is logical implication
"##1\n"
"end_state;\n"
"endproperty",
"property p_P;\n"
" pkg::foo_t foo;\n" // without 'var'
" a - 1\n"
"endproperty\n",
"property p_P;\n"
" var pkg::foo_t foo;\n" // with 'var'
" a - 1\n"
"endproperty\n",
"property p_P;\n"
" pkg::foo_t foo = bar;\n" // with assignment
" a\n"
"endproperty\n",
"property p_P;\n"
" pkg::foo_t foo = bar, x = y;\n" // with assignments
" a\n"
"endproperty\n",
};
static const ParserTestCaseArray kModuleMemberTests = {
"module mymodule;\n"
"task subtask;\n"
"endtask\n"
"endmodule",
"module m();\n"
" task intf.task1();\n"
" endtask\n"
"endmodule",
"module mymodule;\n"
"function integer subroutine;\n"
" input a;\n"
" subroutine = a+42;\n"
"endfunction\n"
"endmodule",
"module mymodule;\n"
"function integer[j:k][k:l] subroutine;\n"
" input a;\n"
" subroutine = a+42;\n"
"endfunction\n"
"endmodule",
"module mymodule;\n"
"function automatic integer subroutine;\n"
" input a;\n"
" subroutine = a+42;\n"
"endfunction\n"
"endmodule",
"module mymodule;\n"
"function bclass::inttype #(16) subroutine;\n"
" input a;\n"
" subroutine = a+42;\n"
"endfunction\n"
"endmodule",
"module mymodule;\n"
"function automatic bclass::inttype #(16) subroutine;\n"
" input foo::bar #(N) a;\n"
" input b;\n"
" subroutine = a+41;\n"
"endfunction\n"
"endmodule",
"module mymodule;\n"
"class myclass;\n"
"endclass\n"
"endmodule",
"module mymodule;\n"
"module innermod;\n"
"endmodule\n"
"endmodule",
"module mymodule;\n"
"class myclass;\n"
"task subtask;\n"
"endtask\n"
"endclass\n"
"endmodule",
"module mymodule;\n"
"module innermod;\n"
"class myclass;\n"
"task subtask;\n"
"endtask\n"
"endclass\n"
"endmodule\n"
"endmodule",
"module mymodule;\n"
"property myprop;\n"
"##1 selected |-> a != 0;\n"
"endproperty\n"
"endmodule",
// covergroup tests
"module mymodule;\n"
"covergroup err;\n"
" fff : coverpoint xx;\n"
"endgroup\n"
"endmodule",
"module mymodule;\n"
"covergroup err @ (posedge clk);\n" // event control
" c_e : coverpoint ((a == b) && c);\n"
"endgroup\n"
"endmodule",
"module cover_this;\n"
"covergroup asdf;\n"
" c_e : coverpoint ccc;\n"
"endgroup : asdf\n" // with end label
"endmodule",
"module cover_this;\n"
"covergroup asdf;\n"
" c_e : coverpoint (a == b) && c;\n"
"endgroup\n"
"endmodule",
"module cover_this;\n"
"covergroup qweasdf;\n"
" option.name = \"foobar\";\n" // with option
" cp_e : coverpoint c.d;\n"
"endgroup\n"
"endmodule",
"module cover_this;\n"
"covergroup qweasdf;\n"
" option.name = $sformat(\"%s.world\", hello);\n" // with option
" cp_e : coverpoint c.d;\n"
"endgroup\n"
"endmodule",
"module cover_this;\n"
"covergroup qweasdf;\n"
"`ifdef BARFOO\n"
" option.name = \"foobar\";\n" // preprocessor directive
"`else\n"
" option.date = \"tomorrow\";\n"
"`endif\n"
" cp_e : coverpoint c.d;\n"
"endgroup\n"
"endmodule",
"module cover_this;\n"
"covergroup qweasdf;\n"
" option.name = \"foobar\";\n" // preprocessor directive
"`ifdef BARFOO\n"
" cp_d : coverpoint c.e;\n"
"`else\n"
" cp_e : coverpoint c.d;\n"
"`endif\n"
"endgroup\n"
"endmodule",
"module cover_this;\n"
"covergroup qweasdf @ (posedge (x && y.z));\n"
" l1 : coverpoint c.d[0] == ns::state1;\n"
" l2 : coverpoint c.d[0] == ns::state2;\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings @ (p_coverage);\n"
" coverpoint __disable;\n" // anonymous coverpoint
" bar : coverpoint __enable;\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" cross dbi, mask;\n" // cover_cross
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" _name : cross dbi, mask, mask2;\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" cross_c : cross a, b { }\n" // empty cross body
"endgroup\n"
"endmodule",
"class foo;\n"
"covergroup ram_cg;\n"
" e_d_c_cp : cross ec.r_inputs, ec.r_outputs\n" // hierarchical refs
" iff(ec.e_type != UNDEF_ERROR);\n"
" endgroup\n"
"endclass",
"module cover_that;\n"
"covergroup settings;\n"
" _name : cross dbi, mask {\n"
" bins garbage = binsof(foo);\n"
" ignore_bins g2 = binsof(other_stuff);\n"
" illegal_bins g3 = binsof(not_mine);\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" _name : cross dbi, mask {\n"
" bins garbage = binsof(foo) || binsof(bar) iff (a-b);\n"
" bins lottery = binsof(win) iff ((x));\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" _name : cross dbi, mask {\n"
" bins nodm = binsof(win) intersect {0};\n" // intersect range list
" }\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" _name : cross dbi, mask {\n"
" bins nodm = binsof(win) intersect {0} && binsof(zz) intersect {1};\n"
" bins nod2 = !binsof(win) intersect {1} || !binsof(zz) intersect {2};\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" _name : cross dbi, mask {\n"
" function int foo(int bar);\n" // function declaration
" return bar;\n"
" endfunction\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" coverpoint cfgpsr {\n"
" bins legal = {[0:12]};\n"
" illegal_bins illegal = {4,6};\n"
" illegal_bins illegal2 = default;\n" // default
" ignore_bins ignored = {4,6,8,[44:46]};\n"
" bins enabled = {[1:$]};\n"
" bins other[2] = {[3:6]};\n" // array decl
" bins another[] = {[2:7]};\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup settings;\n"
" coverpoint cfgpsr {\n"
" bins en = 4'b0000;\n"
" wildcard bins b0 = 4'b???1;\n" // wildcard
" wildcard bins b1 = 4'b??1?;\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup init_this @ (posedge clk);\n"
" coverpoint refresh iff (sync == 1'b1) {\n" // trailing iff
" bins nsr = {4'b0000};\n"
" wildcard bins nr1 = {4'b???1} iff (NR > K);\n" // trailing iff
" }\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup sample_me with function sample ();\n"
" coverpoint __disable;\n"
"endgroup\n"
"endmodule",
"module cover_that;\n"
"covergroup sample_me (bit x, bit y)\n"
" with function sample (bit w, bit z);\n"
" coverpoint __disable;\n"
"endgroup\n"
"endmodule",
"module module_with_property;\n"
"property myprop_seq_match;\n"
" (a, b = c) |-> weak(j);\n"
"endproperty\n"
"endmodule",
"module module_with_sequence;\n"
"sequence S_data_matches(valid, obs_data, exp_data);\n"
" 1 ##[1:$] valid && (obs_data == exp_data);\n"
"endsequence\n"
"endmodule",
// testing preprocessor-balanced coverpoint items (bins_or_options)
"module cover_that_pp;\n"
"covergroup settings;\n"
" cp : coverpoint cfgpsr {\n"
"`ifdef GOO\n"
"`endif\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that_pp;\n"
"covergroup settings;\n"
" cp : coverpoint cfgpsr {\n"
"`ifndef GOO\n"
"`endif\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that_pp;\n"
"covergroup settings;\n"
" cp : coverpoint cfgpsr {\n"
"`ifdef GOO\n"
"`else\n"
"`endif\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that_pp;\n"
"covergroup settings;\n"
" cp : coverpoint cfgpsr {\n"
"`ifdef GOO\n"
"`elsif TAR\n"
"`endif\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that_pp;\n"
"covergroup settings;\n"
" cp : coverpoint cfgpsr {\n"
"`ifdef GOO\n"
"`elsif TAR\n"
"`else\n"
"`endif\n"
" }\n"
"endgroup\n"
"endmodule",
"module cover_that_pp;\n"
"covergroup settings;\n"
" cp : coverpoint cfgpsr {\n"
"`ifdef GOO\n"
" wildcard bins b0 = {4'b???1};\n"
" wildcard bins b1 = {4'b??1?};\n"
"`elsif TAR\n"
" wildcard bins b0 = {4'b??11};\n"
" wildcard bins b1 = {4'b11??};\n"
"`else\n"
" wildcard bins b0 = {4'b??00};\n"
" wildcard bins b1 = {4'b00??};\n"
"`endif\n"
" }\n"
"endgroup\n"
"endmodule",
"covergroup cg() with function\n"
" sample(blah blah);\n"
" option.bar = 0;\n"
"endgroup",
"covergroup cg() with function\n"
" sample(blah blah);\n"
" `MACRO()\n" // macro as item
"endgroup",
"covergroup cg() with function\n"
" sample(blah blah);\n"
" `MACRO();\n" // macro as item
"endgroup",
"covergroup cg;\n"
" cp : coverpoint foo {\n"
" `MACRO();\n" // macro as item
" }\n"
"endgroup",
};
static const ParserTestCaseArray kClassMemberTests = {
// member tasks
"class myclass;\n"
"task subtask;\n"
"endtask\n"
"endclass",
"class c;\n"
" task intf.task1();\n"
" endtask\n"
"endclass",
"class myclass;\n"
"extern task subtask(arg_type arg);\n"
"endclass",
"class myclass;\n"
"extern task automatic subtask(arg_type arg);\n"
"endclass",
"class myclass;\n"
"extern virtual task subtask(arg_type arg);\n"
"endclass",
"class myclass;\n"
"pure virtual task pure_task1;\n"
"pure virtual task pure_task2(arg_type arg);\n"
"endclass",
"class myclass;\n"
"extern protected task subtask(arg_type arg);\n"
"endclass",
"class myclass;\n"
"extern virtual protected task subtask(arg_type arg);\n"
"endclass",
"class myclass;\n"
"extern protected virtual task subtask(arg_type arg);\n"
"endclass",
"class myclass;\n"
"extern local static task subtask(arg_type arg);\n"
"endclass",
// nested classes
"class outerclass;\n"
" class innerclass;\n"
" class reallyinnerclass;\n"
" task subtask;\n"
" endtask\n"
" endclass\n"
" endclass\n"
"endclass",
// field variables
"class myclass;\n"
" int buzz_count;\n"
"endclass",
"class semaphore;\n"
" local chandle p_handle;\n" // chandle type
"endclass",
"class protected_stuff;\n"
" protected int count;\n"
" protected const int countess = `SSS;\n"
" protected var int counter = 0;\n"
" protected const var int counted = 1;\n"
" protected const myclass::msg_t null_msg = {1'b1, 1'b0};\n"
"endclass",
"class c;\n"
" uint [x:y] g = 2;\n" // user-defined type, packed dimensions
"endclass\n",
"class c;\n"
" uint [x][y] g = 2;\n" // user-defined type, packed dimensions
"endclass\n",
"class c;\n"
" uint [x:y] g[y:g] = 2;\n" // user-defined type, packed+unpacked
// dimensions
"endclass\n",
"class c;\n"
" foo_pkg::uint [x:y] g = 2;\n" // user-defined type, packed dimensions
"endclass\n",
"class c;\n"
" bar#(foo)::uint [x:y] g = 2;\n" // user-defined type, packed dimensions
"endclass\n",
// member functions
"class myclass;\n"
"function integer subroutine;\n"
" input a;\n"
" subroutine = a+42;\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"extern function void subroutine;\n"
"endclass",
"class myclass;\n"
"extern function automatic void subroutine;\n"
"endclass",
"class myclass;\n"
"extern function yourpkg::classy::xtype #(p,q) subr;\n"
"endclass",
"class myclass;\n"
"extern function void subroutine(input bool x);\n"
"endclass",
"class myclass;\n"
"extern function void subr(bool x[N]);\n"
"endclass",
"class myclass;\n"
"extern function void subr(ducktype #(3) x);\n"
"endclass",
"class myclass;\n"
"extern function sometype #(N+1) subr(ducktype #(3) x);\n"
"endclass",
"class myclass;\n"
"extern function sometype #(N+1)[N:0]"
"subr(ducktype #(3) x);\n"
"endclass",
"class myclass;\n"
"extern function void subr(mypkg::foo y[M]);\n"
"endclass",
"class myclass;\n"
"extern function void subr(mypkg::foo #(4) x[N]);\n"
"endclass",
"class myclass;\n"
"extern virtual function integer subroutine;\n"
"endclass",
"class myclass;\n"
"pure virtual function integer subroutine;\n"
"pure virtual function integer compute(int a, bit b);\n"
"endclass",
"class myclass;\n"
"virtual function void starter(uvm_phase phase);\n"
" report_server new_server = new;\n" // initialized to class_new
"endfunction : starter\n"
"endclass",
"class myclass;\n"
"function void shifter;\n"
" for ( ; shft_idx < n_bits;\n"
" shft_idx++) begin\n" // no initializations
" end\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"function void shifter;\n"
" for ( ; shft_idx < n_bits; ) begin\n" // no for-step
" end\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"function void shifter;\n"
" for (shft_idx=0, c=1'b1; shft_idx < n_bits;\n"
" shft_idx++) begin\n" // multiple initializations
" dout = {dout} << 1;\n"
" end\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"function void shifter;\n"
" for (int shft_idx=0, bit c=1'b1; shft_idx < n_bits;\n"
" shft_idx++) begin\n" // multiple declarations
" dout = {dout} << 1;\n"
" end\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"function void shifter;\n"
" for (var int shft_idx=1, bit c=1'b0; shft_idx < n_bits;\n"
" shft_idx++) begin\n" // multiple declarations, with 'var'
" dout = {dout} << 1;\n"
" end\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"function void shifter;\n"
" for (int shft_idx=0; shft_idx < n_bits;\n"
" shft_idx++, data.width--) begin\n" // multiple step assignments
" dout = {dout} << 1;\n"
" end\n"
"endfunction\n"
"endclass",
// should 'virtual' be enclosed?
"class myclass;\n"
"virtual function integer subroutine;\n"
" input a;\n"
" subroutine = a+42;\n"
"endfunction\n"
"endclass",
// virtual interface return type
"class myclass;\n"
"function virtual cmd_array_if subroutine();\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"virtual function virtual cmd_array_if subroutine();\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"virtual function virtual interface\n"
" cmd_array_if subroutine();\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"virtual function virtual array_if.modport_x subroutine();\n"
"endfunction\n"
"endclass",
// constructor
"class constructible;\n"
"function new;\n"
"endfunction\n"
"endclass",
"class constructible;\n"
"function new ();\n"
"endfunction\n"
"endclass",
"class constructible;\n"
"function new ();\n"
"endfunction : new\n" // end label
"endclass",
"class constructible;\n"
"function new (string name, virtual time_if vif);\n"
" this.name = name;\n"
"endfunction\n"
"endclass",
"class constructible;\n"
"function new (foo::bar name,\n"
" virtual interface time_if vif,\n"
" baz#(M,N)::foo bar, bit [K:0] b);\n"
" this.name = name;\n"
"endfunction\n"
"endclass",
"class constructible;\n"
"extern function new;\n"
"endclass",
"class constructible;\n"
"extern function new();\n"
"endclass",
"class constructible;\n"
"extern function new(string name, int count);\n"
"endclass",
// typedef
"class fun_with_typedef_members;\n"
"typedef struct { int i; bool b; } mystruct;\n"
"typedef enum { RED, GREEN, BLUE } colors;\n"
"typedef virtual blah_if harness_if;\n"
"typedef virtual interface blah_if harness_if;\n"
"typedef virtual blah_if#(N) foo_if;\n"
"typedef virtual blah_if#(N).modport_id foo_if;\n"
"endclass",
// interface
"class myclass;\n"
"virtual splinterface grinterface;\n"
"virtual interface foo_if bar_if;\n"
"endclass",
"class myclass;\n"
"virtual splinterface grinterface, winterface;\n"
"virtual interface foo_if bar_if, baz_if;\n"
"endclass",
"class myclass;\n"
"virtual hinterface.some_mod_port winterface;\n"
"virtual interface foo_if #(J,K) bar_if, baz_if;\n"
"virtual disinterface#(.N(N)).some_mod_port blinterface;\n"
"endclass",
// foreach
"class myclass;\n"
"function void apply_all();\n"
" foreach (foo[i]) begin\n"
" y = apply_this(foo[i]);\n"
" end\n"
"endfunction\n"
"endclass",
"class myclass;\n"
"function apkg::num_t apply_all();\n"
" foreach (this.foo[i]) begin\n"
" y = {y, this.foo[i]};\n"
" z = {z, super.bar[i]};\n"
" end\n"
"endfunction\n"
"endclass",
// constraints
"class myclass extends uvm_object;\n"
"constraint size_c {\n"
" A + B <= C;\n"
"}\n"
"endclass",
"class myclass extends uvm_object;\n"
"constraint size_c {\n"
" A + B <= C;\n"
"};\n" // extra ';' here is interpreted as a null class_item
"endclass",
"class myclass extends uvm_object;\n"
"static constraint size_c {\n"
" soft A inside {[1:10]};\n"
" A + B <= C;\n"
"}\n"
"endclass",
"class myclass extends uvm_object;\n"
"constraint size_c {\n"
" soft A inside {[1:10]};\n"
" A dist { 1 := 10, [2:9] :/ 80, 10 := 10 };\n" // distribution
" A + B <= C;\n"
"}\n"
"endclass",
"class foo_class extends bar;\n"
"constraint gain_constraint {\n"
" A dist {1 := 90, 0 := 10 };\n"
" if (c_g[A:B] == 0) c_g[K:0] == 0;\n" // if
" if (c_g[A:B] == 1) { c_g[K:0] == 1; }\n" // if block
" c_g[A:B] != '1;\n"
"}\n"
"endclass",
"class myclass extends uvm_object;\n"
"constraint solve_this {\n"
" solve x before y;\n"
" solve x.z before y.x;\n"
" solve x.z, f, g before q, r, y.x;\n"
" solve x.z[2], f[1], g before q, r[4], y[3].x;\n"
"}\n"
"endclass",
// net_type_declarations
"class c;\n"
" nettype real foo_wire;\n"
"endclass\n",
"class c;\n"
" nettype shortreal[2] foo_wire with fire;\n"
"endclass\n",
"class c;\n"
" nettype foo_pkg::bar_t baz_wire;\n"
"endclass\n",
"class c;\n"
" nettype foo#(x,y,z)::bar_t baz_wire;\n"
"endclass\n",
"class c;\n"
" nettype foo#(x,y,z)::bar_t[2:0] baz_wire;\n"
"endclass\n",
"class c;\n"
" nettype foo#(x,y,z)::bar_t baz_wire with quux;\n"
"endclass\n",
};
static const ParserTestCaseArray kInterfaceClassTests = {
"interface class base_ic;\n"
"endclass",
"interface class base_ic;\n"
"endclass : base_ic", // end label
"interface class base_ic #(int N = 8, type T = string);\n"
"endclass",
"interface class base_ic extends basebase;\n" // inheritance
"endclass",
"interface class base_ic extends base1, base2, base3;\n" // multiple
"endclass",
"interface class base_ic #(int N = 8) extends pkg1::base1, "
"base2#(N);\n"
"endclass",
"interface class base_ic;\n"
"typedef int[3:0] quartet;\n"
"typedef string string_type;\n"
"endclass",
"interface class base_ic;\n"
"typedef struct { int i; bool b; } mystruct;\n"
"typedef enum { RED, GREEN, BLUE } colors;\n"
"typedef virtual blah_if harness_if;\n"
"typedef some_class#(3, 2, 1) car_type;\n"
"endclass",
"interface class base_ic;\n"
"parameter N = 2;\n"
"parameter type T = bit;\n"
"localparam M = f(bhg::arr[N]) -1;\n"
"endclass",
"interface class base_ic;\n"
"pure virtual task pure_task1;\n"
"pure virtual task pure_task2(arg_type arg);\n"
"endclass",
"interface class base_ic;\n"
"pure virtual function void pure_task1;\n"
"pure virtual function string concatenator(string arg);\n"
"endclass",
"interface class base_ic;\n"
"parameter N = 2;\n"
"typedef some_class#(N) car_type;\n"
"pure virtual task pure_task1;\n"
"pure virtual function void pure_task1;\n"
"endclass",
};
static const ParserTestCaseArray kConstraintTests = {
"constraint solve_this {\n"
" solve x.z before y.x;\n"
"}",
"constraint myclass::solve_this {\n" // out-of-line definition
" solve x.z before y.x;\n"
"}",
"constraint smooth_operator {\n"
" !(v0.op inside {[V_rt:V_rec]} &&\n" // inside has precedence over &&
" v1.op inside {[V_rt:V_rec]});\n"
"}",
"constraint solve_this {\n"
" !present <-> length == 0;\n" // <-> operator
"}",
"constraint equiv_this {\n"
" solve present before length;\n"
" length inside {[0:1024]};\n"
" !present <-> length == 0;\n"
"}",
"constraint order_c {\n"
" foreach (producer_h[i]) {\n" // foreach
" producer_h[i] != 0;\n"
" }\n"
"}",
"constraint order_c {\n"
" solve WTN_h before loop_nest.mem_size;\n"
" foreach (producer_h[i]) {\n" // foreach
" solve WTN_h before producer_h[i].syncFlagLocation;\n"
" }\n" // solve inside foreach is an extension
"}",
// constraint_blocks with preprocessor conditionals
"constraint solve_this {\n"
"`ifdef BOO\n"
"`endif\n"
"}",
"constraint solve_this {\n"
"`ifdef BOO\n"
" solve x.z before y.x;\n"
"`endif\n"
"}",
"constraint solve_that {\n"
"`ifdef BOO\n"
" solve z before y;\n"
" solve x before z;\n"
"`endif\n"
"}",
"constraint solve_that {\n"
"`ifdef BOO\n"
"`else\n"
" solve z before y;\n"
" solve x before z;\n"
"`endif\n"
"}",
"constraint solve_that {\n"
"`ifdef BOO\n"
" solve z before y;\n"
" solve x before z;\n"
"`else\n"
"`endif\n"
"}",
"constraint solve_that {\n"
"`ifndef BOO\n"
" solve z before y;\n"
"`elsif FAR\n"
"`elsif FAR\n"
"`elsif AWAY\n"
" solve x before z;\n"
"`endif\n"
"}",
/* TODO(fangism): allow empty constraint_set
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
" }\n" // empty constraint_set
"}",
*/
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
" foo[i] == 0;\n"
" }\n"
"}",
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
"`ifdef DEFY\n"
"`endif\n"
" }\n"
"}",
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
"`ifndef DEFY\n"
" foo[i].foo == 0;\n"
"`endif\n"
" }\n"
"}",
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
"`ifdef DEFY\n"
" foo[i] > 0;\n"
" foo[i] < 4;\n"
"`endif\n"
" }\n"
"}",
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
"`ifdef DEFY\n"
"`else\n"
" foo[i] > 0;\n"
" foo[i] < 4;\n"
"`endif\n"
" }\n"
"}",
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
"`ifdef DEFY\n"
" foo[i] > 0;\n"
" foo[i] < 4;\n"
"`else\n"
"`endif\n"
" }\n"
"}",
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
"`ifdef DEFY\n"
" foo[i] > 0;\n"
"`elsif DENY\n"
" foo[i] < 4;\n"
"`endif\n"
" }\n"
"}",
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
"`ifdef DEFY\n"
" foo[i] > 0;\n"
"`elsif DENY\n"
" foo[i] < 4;\n"
"`else\n"
" foo[i] == 2;\n"
"`endif\n"
" }\n"
"}",
"constraint solve_that {\n"
" foreach (foo[i]) {\n"
"`ifdef DEFY\n"
" foo[i] > 0;\n"
"`elsif DENY\n"
" foo[i] < 4;\n"
"`elsif DECRY\n"
" foo[i] < 3;\n"
"`else\n"
" foo[i] == 2;\n"
"`endif\n"
" }\n"
"}",
};
static const ParserTestCaseArray kConfigTests = {
"config cfg;\n"
" design foo.bar;\n" // library-qualified cell-id
"endconfig",
"config cfg;\n"
" design foo.bar;\n"
"endconfig : cfg", // with end label
"config cfg;\n"
" design foo bar;\n" // with multiple cell-ids
"endconfig",
"config cfg;\n"
" design baz foo.bar;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" default liblist larry moe curly;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" instance top.x.y liblist grouch zeppo;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" instance top.x.y use oscar;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" instance top.x.y use oscar : config;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" instance top.x.y use bert.ernie;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" cell y.zz liblist grouch zeppo;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" cell y.zz use red;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" cell y.zz use red.blue;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" cell y.zz use red.blue : config;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" instance top.x.y use bert.ernie;\n" // multiple config_rule_statement
" cell y.zz use red.blue : config;\n"
"endconfig",
// various use_clauses with parameters...
"config cfg;\n"
" design foo.bar baz;\n"
" cell y.zz use .red(blue) : config;\n" // named parameter
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" cell y.zz use .red(blue), .one(11) : config;\n" // named parameters
"endconfig",
/* TODO(b/124600414): cell-id followed by named parameters
"config cfg;\n"
" design foo.bar baz;\n"
" cell y.zz use yellow .red(blue) : config;\n" // named parameter
"endconfig",
*/
// preprocess-balanced config rule statements, empty clauses
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
"`else\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
"`else\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
"`elsif ZZZ\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
"`elsif ZZZ\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
"`elsif ZZZ\n"
"`else\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
"`elsif ZZZ\n"
"`else\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
"`elsif ZZZ\n"
"`elsif WWW\n"
"`else\n"
"`endif\n"
"endconfig",
// preprocess-balanced config rule statements, non-empty clauses
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
" instance top.x use a.b;\n"
" cell y.zz use red;\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`else\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`else\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
" instance top.x use a.b;\n"
" cell y.zz use red;\n"
"`elsif ZZZ\n"
" instance top.x use a.b;\n"
" cell y.zz use red;\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
" instance top.x use a.b;\n"
" cell y.zz use red;\n"
"`elsif ZZZ\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifdef YYY\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`elsif ZZZ\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`else\n"
" instance top.x use a.b;\n"
" cell y.zz use red;\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`elsif ZZZ\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`else\n"
" instance top.x use a.b;\n"
" cell y.zz use red;\n"
"`endif\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
"`ifndef YYY\n"
" instance top.x use a.b;\n"
" cell y.zz use red;\n"
"`elsif ZZZ\n"
" instance top.x use a.b;\n"
" cell y.zz use red;\n"
"`elsif WWW\n"
" cell y.zz use red;\n"
" instance top.x use a.b;\n"
"`else\n"
" cell y.zz use red;\n"
"`endif\n"
"endconfig",
};
static const ParserTestCaseArray kPrimitiveTests = {
"primitive ape (output out, input in1, input in2);\n"
" table\n"
" 0:0:0;\n" // sequential entry
" endtable\n"
"endprimitive",
"primitive ape (output out, input in1, input in2);\n"
" table\n"
"`ifdef QWERTY\n"
" 0:0:0;\n" // sequential entry
"`endif\n"
" endtable\n"
"endprimitive",
"primitive ape (out, in1, in2);\n"
" output out;\n"
" input in1;\n"
" input in2;\n"
" table\n"
" 0:0:0;\n"
" endtable\n"
"endprimitive",
"primitive ape (out, in1, in2);\n"
" output out;\n"
" input in1;\n"
" input in2;\n"
" table\n"
"`include \"prim1.v\"\n"
"`include \"prim2.v\"\n"
" endtable\n"
"endprimitive",
/* TODO(b/38347353): mis-lexed input value
"primitive ape (output out, input in1, input in2);\n"
" table\n"
" 101:X;\n" // combinational entry
" endtable\n"
"endprimitive",
*/
"primitive ape (output out, input in1, input in2);\n"
" table\n"
" 1 0 1:X;\n" // combinational entry
" endtable\n"
"endprimitive",
"primitive ape (output out, input in1, input in2);\n"
" table\n"
"`ifndef ASDF\n"
" 1 0 1:X;\n" // combinational entry
"`else\n"
" 1 0 1:1;\n" // combinational entry
"`endif\n"
" endtable\n"
"endprimitive",
"primitive ZZSRDFF1e(Q,D,CK,SET,RST);\n"
" input D,CK,SET,RST;\n"
" output Q;\n"
" reg Q;\n"
" table\n"
" // D CK SET RST : curr : Q\n"
" `ifdef TTTT\n"
" 0 r 0 0 : ? : 0 ;\n"
" 1 r 0 0 : ? : 1 ;\n"
" ? f 0 0 : ? : - ;\n"
" `else\n"
" 0 p 0 0 : ? : 0 ;\n"
" 1 p 0 0 : ? : 1 ;\n"
" ? n 0 0 : ? : - ;\n"
" `endif\n"
" * ? 0 0 : ? : - ;\n"
" ? ? 0 1 : ? : 0 ;\n"
" ? ? 1 0 : ? : 1 ;\n"
" endtable\n"
"endprimitive",
};
static const ParserTestCaseArray kDisciplineTests = {
"discipline d;\n"
"enddiscipline\n",
"discipline d \n" // no ';'
"enddiscipline\n",
"discipline d;\n"
" domain discrete;\n"
"enddiscipline\n",
"discipline d;\n"
" domain continuous;\n"
"enddiscipline\n",
"discipline d;\n"
" potential pot;\n"
"enddiscipline\n",
"discipline d;\n"
" flow joe;\n"
"enddiscipline\n",
};
static const ParserTestCaseArray kMultiBlockTests = {
// check for correct scope switching around timescale and module
"module modular_thing1;\n"
"endmodule\n"
"`timescale 10 ps / 10 ps\n" // with spaces before unit
"module modular_thing2;\n"
"endmodule",
"function void foo;\n"
"endfunction\n"
"task snoozer;\n"
"endtask\n"
"function void zoo;\n"
"endfunction\n"
"task floozer;\n"
"endtask\n",
"class foo;\n"
"endclass\n"
"module bar;\n"
"endmodule\n"
"class baz;\n"
"endclass\n"
"interface ick;\n"
"endinterface\n",
"module bar;\n"
" function void zoo;\n"
" endfunction\n"
"task loozer;\n"
" endtask\n"
"endmodule\n"
"class scar;\n"
" function void zoo;\n"
" endfunction\n"
"task loozer;\n"
" endtask\n"
"endclass\n"};
static const ParserTestCaseArray kRandSequenceTests = {
// randsequence inside initial block
"module foo();\n"
"initial begin\n"
" randsequence(main)\n"
" main: A;\n"
" A: {$display(\"1\");};\n"
" endsequence\n"
"end\n"
"endmodule\n",
// randsequence inside task
"task body();\n"
" randsequence(main)\n"
" main: A B;\n"
" A: {$display(\"1\");};\n"
" B: {$display(\"2\");};\n"
" endsequence\n"
"endtask\n",
// randsequence inside function
"function int body();\n"
" int [$] q;\n"
" randsequence(main)\n"
" main: A B;\n"
" endsequence\n"
"endfunction\n",
"task body();\n"
" randsequence(main)\n"
" main: A C | B;\n" // testing '|'
" A: {$display(\"1\");};\n"
" B: {$display(\"2\");};\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: A B;\n"
" A: {func_1();};\n" // different statement types
" B: {g = 4;};\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: rand join foo bar;\n" // rand join, without value
" foo: A B C;\n"
" bar: D E;\n"
" A: {task_0();};\n"
" B: {task_1();};\n"
" C: {task_2();};\n"
" D: {task_3();};\n"
" E: {task_4();};\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: rand join(0.0) foo bar;\n" // rand join with value
" foo: A B;\n"
" bar: D E;\n"
" A: {task_0();};\n"
" B: {task_1();};\n"
" D: {task_3();};\n"
" E: {task_4();};\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: rand join(1.0) foo bar;\n" // rand join with value
" foo: B C;\n"
" bar: E F;\n"
" B: {task_1();};\n"
" C: {task_2();};\n"
" E: {task_4();};\n"
" F: {task_5();};\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: foo bar := 3;\n" // production with random weight
" foo: {task_1();};\n"
" bar: {task_2();};\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: foo := 2 {}\n" // optional code block
" | bar := (1+4);\n" // production with random weights
" foo: {task_1();};\n"
" bar: {task_2();};\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: if (depth < 2) push;\n" // conditional
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: if (depth < 2) push else pop;\n" // conditional, with else
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence()\n"
" select: case (device & 7)\n" // case statement
" 0: NETWORK;\n"
" endcase;\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence()\n"
" select: case (device & 7)\n"
" 1,2: MEMORY;\n" // multiple case item expressions
" default: DISK;\n" // default item
" endcase;\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence()\n"
" select: case (device & 7)\n"
" 1: MEMORY;\n"
" 2: DISK;\n"
" default DISK;\n" // default item (no colon)
" endcase;\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: repeat ($urandom_range(2, 6)) push;\n" // loop, random
" push: repeat (3) fall;\n" // loop, constant
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: { if (depth > 2) break; else return; };\n" // break/return
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: gen(\"push\");\n" // parameterized production
" gen(string s = \"x\"): { $display(s); };\n"
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" void main: value op value;\n" // void type
" bit [3:0] value: { return $urandom(); };\n" // array type
" string op: add := 5 { return \"+\"; }\n" // string type
" | sub := 3 { return \"-\"; };\n"
" foobar [3:0] value: { };\n" // user-defined return type
" endsequence\n"
"endtask\n",
"task body();\n"
" randsequence(main)\n"
" main: gen(2);\n"
" int gen(int s): { return s + 1; };\n" // parameterized, with return
" endsequence\n"
"endtask\n",
};
static const ParserTestCaseArray kNetAliasTests = {
"module byte_swap (inout wire [31:0] A, inout wire [31:0] B);\n"
" alias {A[7:0],A[15:8],A[23:16],A[31:24]} = B;\n"
"endmodule\n",
"module byte_rip (inout wire [31:0] W, inout wire [7:0] LSB, MSB);\n"
" alias W[7:0] = LSB;\n"
" alias W[31:24] = MSB;\n"
"endmodule\n",
"module lib1_dff(Reset, Clk, Data, Q, Q_Bar);\n"
"endmodule\n"
"module lib2_dff(reset, clock, data, q, qbar);\n"
"endmodule\n"
"module lib3_dff(RST, CLK, D, Q, Q_);\n"
"endmodule\n"
"module my_dff(rst, clk, d, q, q_bar);\n"
" input rst, clk, d;\n"
" output q, q_bar;\n"
" alias rst = Reset = reset = RST;\n"
" alias clk = Clk = clock = CLK;\n"
" alias d = Data = data = D;\n"
" alias q = Q;\n"
" alias Q_ = q_bar = Q_Bar = qbar;\n"
"endmodule\n",
"module foo;\n"
" logic a, b, c, d, e, f, g, h;\n"
" alias a = b = c = d = e = f = g = h;\n"
"endmodule;\n",
};
// These tests target LRM Ch. 33
static const ParserTestCaseArray kLibraryTests = {
";\n",
"library foolib bar;\n",
"library foolib *.bar;\n",
"library foolib ?.bar;\n",
"library foolib /bar;\n",
"library foolib bar/;\n",
"library foolib ../bar;\n",
"library foolib ../bar/;\n",
"library foolib */bar;\n",
"library foolib b/a/r;\n",
"library foolib /b/a/r/;\n",
"library foolib b/a/r/*.v;\n",
"library foolib b/a/r/*.vg;\n",
"library foolib *.v,*.vg;\n",
"library foolib *.v , *.vg ; \n",
"library foolib foo/*.v -incdir bar; \n",
"library foolib foo/*.v -incdir bar, baz; \n",
"library foolib bar1;\n"
"library foolib bar2;\n",
"include foo/*.bar;\n",
"include /foo/*.bar;\n",
"include /foo/bar/;\n",
"include foo/*.bar;\n"
"include bar/*.foo;\n",
// most of config_declaration syntax already covered in kConfigTests
"config cfg;\n"
" design foo.bar;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" instance top.x.y use bert.ernie;\n"
"endconfig",
"config cfg;\n"
" design foo.bar baz;\n"
" cell y.zz liblist grouch zeppo;\n"
"endconfig",
// mixed, all valid library_description elements
"library foolib foo/lib/*.v;\n"
"include foo/inc/;\n"
"config cfg;\n"
" design foo.bar;\n"
"endconfig\n",
};
// In the positions where we specify a token via {enum, string} or single
// character like 'x', is where we expect an error to be found.
// All other string literals are only used for concatenating the test case's
// text to be analyzed.
static const std::initializer_list<ParserTestData> kInvalidCodeTests = {
{"function ",
{TK_module, "module"},
"\n"
"end\n"},
{"class ",
{TK_DecNumber, "123"},
";\n"
"endclass\n"},
{{TK_StringLiteral, "\"class\""}, " foo;\n"},
// cannot mix positional and named parameter arguments:
{"class foo;\n"
"fizz #(buzz, ",
'.', // expect error on '.'
"pop(1)) bar;\n"
"endclass\n"},
// cannot mix positional and named parameter arguments:
{"class foo;\n"
"fizz #(.buzz(\"bzz\"), ",
{TK_DecNumber, "1"},
") bar;\n"
"endclass\n"},
{"module foo;", // missing endmodule
{verible::TK_EOF, ""}},
{"module foo;\n", // missing endmodule
{verible::TK_EOF, ""}},
{"module foo(aaa, ",
')', // trailing comma, unexpected )
";\nendmodule\n"},
{"module foo(",
',', // unexpected ,
"bbb);\nendmodule\n"},
{"module foo #(int aaa=7, ",
')', // trailing comma, unexpected )
";\nendmodule\n"},
{"module foo #(",
',', // unexpected ,
" int bbb);\nendmodule\n"},
{"function void bar(",
',', // blank before comma
" int a);\nendfunction\n"},
{"function void bar(int a,",
')', // trailing comma, unexpected )
";\nendfunction\n"},
{"enum foo{bar,",
'}', // trailing comma, unexpected }
" baz;\n"},
{"enum foo{",
',', // blank before comma
" bar} baz;\n"},
// preprocessor imbalance
{"function void foobar;\n",
{PP_else, "`else"}, // no matching `ifdef/`ifndef
"\n"
" return 2;\n"
"endfunction\n"},
{"function void foobar;\n",
{PP_elsif, "`elsif"}, // no matching `ifdef/`ifndef
"\n"
" return 2;\n"
"endfunction\n"},
{"function void foobar;\n",
{PP_endif, "`endif"}, // no matching `ifdef/`ifndef
"\n"
" return 2;\n"
"endfunction\n"},
{"function void foobar;\n"
"`ifndef FOOBAR\n"
" return 0;\n"
"`endif\n",
{PP_endif, "`endif"}, // unbalanced `endif
"\n"
" return 2;\n"
"endfunction\n"},
{"module unbalanced(\n",
{PP_else, "`else"}, // no matching `ifdef/`ifndef
" // blah\n"
"input x)\n"
"endmodule\n"},
{"module unbalanced(\n",
{PP_elsif, "`elsif"}, // no matching `ifdef/`ifndef
" BLAH\n"
"input x)\n"
"endmodule\n"},
{"module unbalanced(\n"
"`ifdef SIM\n"
"input x",
')', // close ) before balanced `ifdef
"\n"
"`else\n"
"input y)\n"
"`endif\n"
";\n"
"endmodule\n"},
{"module unbalanced;\n"
"generate\n",
{PP_else, "`else"}, // no matching `ifdef/`ifndef
" // blah\n"
"endgenerate\n"
"endmodule\n"},
{"module unbalanced;\n"
"generate\n",
{PP_elsif, "`elsif"}, // no matching `ifdef/`ifndef
" BLAH\n"
"endgenerate\n"
"endmodule\n"},
{"module unbalanced;\n"
"generate\n",
{PP_endif, "`endif"}, // no matching `ifdef/`ifndef
"\n"
"endgenerate\n"
"endmodule\n"},
{"class imbalanced;\n"
"int foo;\n",
{PP_else, "`else"}, // unmatched `else
"\n"
"endclass"},
{"class imbalanced;\n"
"int foo;\n",
{PP_elsif, "`elsif"}, // unmatched `elsif
" FOO\n"
"endclass"},
{"class imbalanced;\n"
"int foo;\n",
{PP_endif, "`endif"},
"\n" // unmatched
"endclass"},
{"module unbalanced;\n",
{PP_elsif, "`elsif"}, // no matching `ifdef/`ifndef
" BLAH\n"
"endmodule\n"},
{"module unbalanced;\n",
{PP_else, "`else"}, // no matching `ifdef/`ifndef
" // blah\n"
"endmodule\n"},
{"module unbalanced;\n",
{PP_endif, "`endif"}, // no matching `ifdef/`ifndef
" // blah\n"
"endmodule\n"},
{"module unbalanced;\n",
{PP_endif, "`endif"}, // no matching `ifdef/`ifndef
" // blah\n"
"endmodule\n"},
{"class imbalanced;\n"
"int foo;\n",
{PP_else, "`else"}, // unmatched `else
"\n"
"endclass"},
{"class imbalanced;\n"
"int foo;\n",
{PP_elsif, "`elsif"},
" FOO\n" // unmatched
"endclass"},
{"class imbalanced;\n"
"int foo;\n",
{PP_endif, "`endif"}, // unmatched `endif
"\n"
"endclass"},
{"package imbalanced;\n"
"int foo;\n",
{PP_else, "`else"}, // unmatched `else
"\n"
"endpackage"},
{"package imbalanced;\n"
"int foo;\n",
{PP_elsif, "`elsif"}, // unmatched `elsif
" FOO\n"
"endpackage"},
{"package imbalanced;\n"
"int foo;\n",
{PP_endif, "`endif"}, // unmatched `endif
"\n"
"endpackage"},
{"task bar;\n"
"@e foo:\n"
"`baz\n",
{verible::TK_EOF, ""}}, // missing endtask before EOF
{"`define F", // missing newline
{verible::TK_EOF, ""}},
// invalid DPI import
{"import \"DPI-C\" foo", /* rejected */ ';'},
{"task t;\n"
"for (uint32_t fn",
/* = initializer expression required here */ ';',
" fn < a; fn++) begin\n"
"end\n"
"endtask\n"},
// unbalanced `endif
{{PP_endif, "`endif"}},
{{PP_endif, "`endif"}, "\n"},
// The following tests are valid library map syntax (LRM Ch. 33),
// but invalid for the rest of SystemVerilog:
{{TK_library, "library"}, " foo bar;\n"},
{{TK_include, "include"}, " foo/bar/*.v;\n"},
// fuzzer-discovered cases: (these may have crashed at one point in history)
{"`g((\\x\" `g(::\"\n"
"),",
{verible::TK_EOF, ""}},
// members may only be unqualified (unlike C++)
{"function int bad;\n"
" return x.y",
{TK_SCOPE_RES, "::"},
"z;\n"
"endfunction\n"},
{{TK_endprimitive, "endprimitive"}},
{"//www\n", {TK_endprimitive, "endprimitive"}},
{"module m;\n"
" foo()",
{';', ";"},
"\n"
"endmodule\n"},
{"module m;\n"
" if ((",
{')', ")"}, // empty paren is invalid expression
"foo());"
"\n"
"endmodule\n"},
{"[i()", // unexpected EOF
{verible::TK_EOF, ""}},
{"[i()'", // unexpected EOF
{verible::TK_EOF, ""}},
};
using verible::LeafTag;
// All enums in the following section refer to enum class NodeEnum.
#define NodeTag(tag) verible::NodeTag(NodeEnum::tag)
// These test cases check that error-recovery produces partially formed
// syntax trees that can still be analyzed.
static const verible::ErrorRecoveryTestCase kErrorRecoveryTests[] = {
// module_item error tests
{"module foo;\n"
"wire 123;\n" // rejects '123'
"endmodule\n",
{NodeTag(kModuleDeclaration)}},
{"module foo;\n"
"wire abc;\n"
"wire 123;\n" // rejects '123'
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kNetDeclaration)}},
{"module foo;\n"
"wire 123;\n" // rejects '123'
"wire abc;\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kNetDeclaration)}},
{"module foo;\n"
"wire wire;\n" // rejects second 'wire'
"initial begin\n"
" x <= y;\n"
"end\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kInitialStatement)}},
{"module foo;\n"
"`ifdef ERROR\n" // inside conditional block
"wire 123;\n" // rejects '123'
"`endif // ERROR\n"
"wire abc;\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kNetDeclaration)}},
// generate_item error tests
{"module foo;\n"
"generate\n"
" 123 foo;\n" // rejects '123'
"endgenerate\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kGenerateRegion), NodeTag(kGenerateItemList)}},
{"module foo;\n"
"generate\n"
" class class;\n" // rejects 'class'
"endgenerate\n"
"wire xx;\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kNetDeclaration)}},
{"module foo;\n"
"wire x;\n"
"generate\n"
"if (a & b) begin\n"
" 123 b(q);\n" // rejects '123'
"end\n"
"endgenerate\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kGenerateRegion), NodeTag(kGenerateItemList),
NodeTag(kConditionalGenerateConstruct), NodeTag(kGenerateIfClause),
NodeTag(kGenerateIfBody)}},
// function/task statement_item error tests
{"function void foobar(int a, int b);\n"
" 8 9;\n" // expression error
" return a -b;\n"
"endfunction\n",
{NodeTag(kFunctionDeclaration), NodeTag(kBlockItemStatementList),
NodeTag(kJumpStatement)}},
{"task automatic barfoo;\n"
" $display(\"moo\");;\n"
" 5+5;\n" // statement error
" c <= d;\n"
"endtask\n",
{NodeTag(kTaskDeclaration), NodeTag(kStatementList),
NodeTag(kNonblockingAssignmentStatement)}},
{"module bar;\n"
"task automatic barfoo;\n"
" $display(\"moo\");;\n"
" 5+4;\n" // statement error
" c <= d;\n"
"endtask\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kTaskDeclaration), NodeTag(kStatementList),
NodeTag(kNonblockingAssignmentStatement)}},
// class_item errors
{"class asdf;\n"
"wire foo;\n" // error on 'wire'
"task blah;\n"
"endtask\n"
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kTaskDeclaration)}},
{"class asdf;\n"
"foo var;\n" // error on 'var'
"function automatic void blah;\n"
"endfunction\n"
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kFunctionDeclaration)}},
{"class asdf;\n"
"`ifdef VARRRR\n" // error inside conditional block
"foo var;\n" // error on 'var'
"`endif\n"
"function automatic void blah;\n"
"endfunction\n"
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kFunctionDeclaration)}},
// package_item errors
{"package fedex;\n"
"11 22 33;\n"
"class qwer;\n"
"endclass\n"
"endpackage\n",
{NodeTag(kPackageDeclaration), NodeTag(kPackageItemList),
NodeTag(kClassDeclaration)}},
{"package fedex;\n"
"`ifndef FAIL_INSIDE\n"
"11 22 33;\n" // error inside conditional block
"`endif\n"
"class qwer;\n"
"endclass\n"
"endpackage\n",
{NodeTag(kPackageDeclaration), NodeTag(kPackageItemList),
NodeTag(kClassDeclaration)}},
{"11 22 33;\n"
"class qwer;\n"
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassHeader),
LeafTag(SymbolIdentifier)}},
{"task t;\n"
"if (;c());\n" // error on the first ';'
"endtask\n",
{NodeTag(kTaskDeclaration), NodeTag(kStatementList),
NodeTag(kConditionalStatement), NodeTag(kIfClause), NodeTag(kIfHeader)}},
{"module m;\n"
"if (a+);\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kConditionalGenerateConstruct), NodeTag(kGenerateIfClause),
NodeTag(kGenerateIfHeader)}},
{"class c;\n"
" `BAD function new();\n" // real problem here is the macro,
// but 'function' keyword gets rejected because it is only then that
// there is conclusively an error.
// From error-recovery, this entire function/constructor declaration will
// be dropped.
" endfunction\n"
// recovered from here onward
" int count;\n" // this data declaration will be recovered and saved
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kDataDeclaration)}},
{"class c;\n"
" `BAD task rabbit();\n" // real problem here is the macro,
// but 'task' keyword gets rejected because it is only then that
// there is conclusively an error.
// From error-recovery, this entire function/constructor declaration will
// be dropped.
" endtask\n"
// recovered from here onward
" int count;\n" // this data declaration will be recovered and saved
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kDataDeclaration)}},
{"class c;\n"
" `BAD task rabbit();\n" // real problem here is the macro
" endtask\n"
// recovered from here onward
" static function bit r();\n"
" if (m == null) m = new();\n"
" uvm_resource#(T)::m_set_converter(m_singleton);\n"
" endfunction\n"
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kFunctionDeclaration), NodeTag(kBlockItemStatementList),
NodeTag(kConditionalStatement), NodeTag(kIfClause)}},
{"class c;\n"
" `BAD covergroup cg;\n" // real problem here is the macro
" endgroup\n" // this covergroup will be lost
// recovered from here onward
" int count;\n" // this data declaration will be recovered and saved
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kDataDeclaration)}},
{"class c;\n"
" covergroup cg;\n"
" cp: coverpoint foo.bar {\n"
" 123;\n" // syntax error here
// recovered from here onward
" }\n"
" endgroup\n"
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kCovergroupDeclaration)}},
{"class c;\n"
" covergroup cg;\n"
" cp: coverpoint foo.bar {\n"
" --\n" // syntax error here
// recovered from here onward
" }\n"
" endgroup\n"
"endclass\n",
{NodeTag(kClassDeclaration), NodeTag(kClassItems),
NodeTag(kCovergroupDeclaration)}},
{"module m;\n"
" foo();\n" // invalid syntax, recover from here
" wire w;\n"
"endmodule\n",
{NodeTag(kModuleDeclaration), NodeTag(kModuleItemList),
NodeTag(kNetDeclaration)}},
};
#undef NodeTag
namespace {
// Tests that valid code is accepted.
static void TestVerilogParser(const ParserTestCaseArray& data) {
int i = 0;
for (const auto& code : data) {
verible::TestParserAcceptValid<VerilogAnalyzer>(code, i);
++i;
}
}
static void TestVerilogLibraryParser(const ParserTestCaseArray& data) {
int i = 0;
for (const auto& code : data) {
VLOG(1) << "test_data[" << i << "] = '" << code << "'\n";
// TODO(fangism): refactor TestParserAcceptValid to accept a lambda
const auto analyzer =
AnalyzeVerilogLibraryMap(code, "<<inline-test>>", kDefaultPreprocess);
const absl::Status status = ABSL_DIE_IF_NULL(analyzer)->ParseStatus();
if (!status.ok()) {
// Print more detailed error message.
const auto& rejected_tokens = analyzer->GetRejectedTokens();
if (!rejected_tokens.empty()) {
EXPECT_TRUE(status.ok())
<< "Rejected valid code:\n"
<< code << "\nRejected token: " << rejected_tokens[0].token_info;
} else {
EXPECT_TRUE(status.ok()) << "Rejected valid code:\n" << code;
}
}
EXPECT_TRUE(analyzer->SyntaxTree().get()) << "Missing tree on code:\n"
<< code;
++i;
}
}
// Tests that invalid code is rejected.
static void TestVerilogParserReject(
std::initializer_list<ParserTestData> data) {
int i = 0;
for (const auto& test_case : data) {
verible::TestParserRejectInvalid<VerilogAnalyzer>(test_case, i);
++i;
}
}
template <int N>
static void TestVerilogParserErrorRecovery(
const verible::ErrorRecoveryTestCase (&data)[N]) {
int i = 0;
for (const auto& test : data) {
verible::TestParserErrorRecovered<VerilogAnalyzer>(test, i);
++i;
}
}
static void TestVerilogParserMatchAll(const ParserTestCaseArray& data) {
int i = 0;
for (const auto& code : data) {
verible::TestParserAllMatched<VerilogAnalyzer>(code, i);
++i;
}
}
static void TestVerilogLibraryParserMatchAll(const ParserTestCaseArray& data) {
using verible::Symbol;
int i = 0;
for (const auto& code : data) {
VLOG(1) << "test_data[" << i << "] = '" << code << "'\n";
// TODO(fangism): refactor TestParserAllMatched to accept a lambda
const auto analyzer =
AnalyzeVerilogLibraryMap(code, "<<inline-test>>", kDefaultPreprocess);
const absl::Status status = ABSL_DIE_IF_NULL(analyzer)->ParseStatus();
EXPECT_TRUE(status.ok())
<< status.message()
<< "\nRejected: " << analyzer->GetRejectedTokens().front().token_info;
const Symbol* tree_ptr = analyzer->SyntaxTree().get();
EXPECT_NE(tree_ptr, nullptr) << "Missing syntax tree with input:\n" << code;
if (tree_ptr == nullptr) return; // Already failed, abort this test case.
const Symbol& root = *tree_ptr;
verible::ParserVerifier verifier(root,
analyzer->Data().GetTokenStreamView());
const auto unmatched = verifier.Verify();
EXPECT_EQ(unmatched.size(), 0)
<< "On code:\n"
<< code << "\nFirst unmatched token: " << unmatched.front();
++i;
}
}
// Tests on valid code.
TEST(VerilogParserTest, LexerFilter) { TestVerilogParser(kLexerFilterTests); }
TEST(VerilogParserTest, Empty) { TestVerilogParser(kEmptyTests); }
TEST(VerilogParserTest, Preprocessor) { TestVerilogParser(kPreprocessorTests); }
TEST(VerilogParserTest, Numbers) { TestVerilogParser(kNumberTests); }
TEST(VerilogParserTest, Classes) { TestVerilogParser(kClassTests); }
TEST(VerilogParserTest, Functions) { TestVerilogParser(kFunctionTests); }
TEST(VerilogParserTest, Tasks) { TestVerilogParser(kTaskTests); }
TEST(VerilogParserTest, Modules) { TestVerilogParser(kModuleTests); }
TEST(VerilogParserTest, ModuleInstances) {
TestVerilogParser(kModuleInstanceTests);
}
TEST(VerilogParserTest, Interfaces) { TestVerilogParser(kInterfaceTests); }
TEST(VerilogParserTest, Typedefs) { TestVerilogParser(kTypedefTests); }
TEST(VerilogParserTest, Structs) { TestVerilogParser(kStructTests); }
TEST(VerilogParserTest, Unions) { TestVerilogParser(kUnionTests); }
TEST(VerilogParserTest, Enums) { TestVerilogParser(kEnumTests); }
TEST(VerilogParserTest, Packages) { TestVerilogParser(kPackageTests); }
TEST(VerilogParserTest, Description) { TestVerilogParser(kDescriptionTests); }
TEST(VerilogParserTest, Constraints) { TestVerilogParser(kConstraintTests); }
TEST(VerilogParserTest, Properties) { TestVerilogParser(kPropertyTests); }
TEST(VerilogParserTest, Sequences) { TestVerilogParser(kSequenceTests); }
TEST(VerilogParserTest, ModuleMembers) {
TestVerilogParser(kModuleMemberTests);
}
TEST(VerilogParserTest, ClassMembers) { TestVerilogParser(kClassMemberTests); }
TEST(VerilogParserTest, InterfaceClass) {
TestVerilogParser(kInterfaceClassTests);
}
TEST(VerilogParserTest, Configs) { TestVerilogParser(kConfigTests); }
TEST(VerilogParserTest, Primitives) { TestVerilogParser(kPrimitiveTests); }
TEST(VerilogParserTest, Disciplines) { TestVerilogParser(kDisciplineTests); }
TEST(VerilogParserTest, MultiBlockTests) {
TestVerilogParser(kMultiBlockTests);
}
TEST(VerilogParserTest, RandSequenceTests) {
TestVerilogParser(kRandSequenceTests);
}
TEST(VerilogParserTest, Aliases) { TestVerilogParser(kNetAliasTests); }
TEST(VerilogParserTest, Library) { TestVerilogLibraryParser(kLibraryTests); }
// Tests on invalid code.
TEST(VerilogParserTest, InvalidCode) {
TestVerilogParserReject(kInvalidCodeTests);
}
// Tests on invalid code.
TEST(VerilogParserTest, InvalidCodePerformance) {
const char piece1[] = "bar\n";
const auto piece2 = absl::StrCat("//foo", std::string(500000, '\0'));
const std::initializer_list<ParserTestData> kLocalInvalidCodeTests = {
{piece1, {verible::TK_EOF, piece2}},
};
TestVerilogParserReject(kLocalInvalidCodeTests);
}
// Tests for parser recovery from syntax errors.
TEST(VerilogParserTest, ErrorRecovery) {
TestVerilogParserErrorRecovery(kErrorRecoveryTests);
}
// Test parser's internal stack reallocation.
TEST(VerilogParserTest, InternalStackRealloc) {
// Construct an input that will grow the symbol stack.
std::string code("module foo;\ninitial\n");
constexpr int depth = YYINITDEPTH * 8;
for (int i = 0; i < depth; ++i) {
code += "begin\n";
}
for (int i = 0; i < depth; ++i) {
code += "end\n";
}
code += "endmodule\n";
VerilogAnalyzer analyzer(code, "<<inline-text>>");
auto status = analyzer.Analyze();
EXPECT_TRUE(status.ok()) << "Unexpected failure on code: " << code;
const size_t max_stack_size = analyzer.MaxUsedStackSize();
EXPECT_LE(depth, max_stack_size);
}
// Tests that Tokenize() properly sets the range of the EOF token.
TEST(VerilogParserTest, TokenizeTerimnatesEOFRange) {
constexpr absl::string_view kCode[] = {
"", "\t", "\n", "\n\n",
"module", "module\n", "module foo;", "module foo;\n",
};
for (const auto code : kCode) {
VerilogAnalyzer analyzer(code, "<<inline-text>>");
auto status = analyzer.Tokenize();
EXPECT_TRUE(status.ok());
const auto& tokens = analyzer.Data().TokenStream();
ASSERT_FALSE(tokens.empty());
const auto& eof_token = tokens.back();
EXPECT_EQ(eof_token.token_enum(), verible::TK_EOF);
const auto eof_text = eof_token.text();
const auto& contents = analyzer.Data().Contents();
EXPECT_EQ(eof_text.begin(), contents.end());
EXPECT_EQ(eof_text.end(), contents.end());
}
}
// Tests to ensure valid code is completely parsed into tree
// Failing these tests mean that some tokens were dropped and not
// incorporated into the tree.
TEST(VerilogParserTestMatchAll, Empty) {
TestVerilogParserMatchAll(kEmptyTests);
}
TEST(VerilogParserTestMatchAll, Preprocessor) {
TestVerilogParserMatchAll(kPreprocessorTests);
}
TEST(VerilogParserTestMatchAll, LexerFilter) {
TestVerilogParserMatchAll(kLexerFilterTests);
}
TEST(VerilogParserTestMatchAll, Numbers) {
TestVerilogParserMatchAll(kNumberTests);
}
TEST(VerilogParserTestMatchAll, Classes) {
TestVerilogParserMatchAll(kClassTests);
}
TEST(VerilogParserTestMatchAll, Functions) {
TestVerilogParserMatchAll(kFunctionTests);
}
TEST(VerilogParserTestMatchAll, Tasks) {
TestVerilogParserMatchAll(kTaskTests);
}
TEST(VerilogParserTestMatchAll, Modules) {
TestVerilogParserMatchAll(kModuleTests);
}
TEST(VerilogParserTestMatchAll, Interfaces) {
TestVerilogParserMatchAll(kInterfaceTests);
}
TEST(VerilogParserTestMatchAll, Typedefs) {
TestVerilogParserMatchAll(kTypedefTests);
}
TEST(VerilogParserTestMatchAll, Structs) {
TestVerilogParserMatchAll(kStructTests);
}
TEST(VerilogParserTestMatchAll, Enums) {
TestVerilogParserMatchAll(kEnumTests);
}
TEST(VerilogParserTestMatchAll, Unions) {
TestVerilogParserMatchAll(kUnionTests);
}
TEST(VerilogParserTestMatchAll, Packages) {
TestVerilogParserMatchAll(kPackageTests);
}
TEST(VerilogParserTestMatchAll, Description) {
TestVerilogParserMatchAll(kDescriptionTests);
}
TEST(VerilogParserTestMatchAll, Sequences) {
TestVerilogParserMatchAll(kSequenceTests);
}
TEST(VerilogParserTestMatchAll, Property) {
TestVerilogParserMatchAll(kPropertyTests);
}
TEST(VerilogParserTestMatchAll, ModuleMembers) {
TestVerilogParserMatchAll(kModuleMemberTests);
}
TEST(VerilogParserTestMatchAll, ClassMembers) {
TestVerilogParserMatchAll(kClassMemberTests);
}
TEST(VerilogParserTestMatchAll, InterfaceClasses) {
TestVerilogParserMatchAll(kInterfaceClassTests);
}
TEST(VerilogParserTestMatchAll, Constraints) {
TestVerilogParserMatchAll(kConstraintTests);
}
TEST(VerilogParserTestMatchAll, Configs) {
TestVerilogParserMatchAll(kConfigTests);
}
TEST(VerilogParserTestMatchAll, Primitives) {
TestVerilogParserMatchAll(kPrimitiveTests);
}
TEST(VerilogParserTestMatchAll, Disciplines) {
TestVerilogParserMatchAll(kDisciplineTests);
}
TEST(VerilogParserTestMatchAll, MultiBlock) {
TestVerilogParserMatchAll(kMultiBlockTests);
}
TEST(VerilogParserTestMatchAll, RandSequence) {
TestVerilogParserMatchAll(kRandSequenceTests);
}
TEST(VerilogParserTestMatchAll, NetAlias) {
TestVerilogParserMatchAll(kNetAliasTests);
}
TEST(VerilogParserTestMatchAll, Library) {
TestVerilogLibraryParserMatchAll(kLibraryTests);
}
} // namespace
} // namespace verilog