From 46c0526dab35c177c9395bc0bf3c82b31b3a84d3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 16 May 2026 16:13:19 -0700 Subject: [PATCH 1/2] Add support for restricted type parameters SystemVerilog 2023 allows type parameters to be restricted to a specific kind of type, e.g. `parameter type struct T = T0`. This is very similar to the type restrictions that can be applied to forward typedefs. Factor the support code from the typedefs into a standalone helper and reuse it for both. Signed-off-by: Lars-Peter Clausen --- PScope.h | 4 +++- elab_type.cc | 22 +--------------------- net_design.cc | 10 ++++++++++ net_scope.cc | 1 + netlist.h | 2 ++ parse.y | 43 ++++++++++++++++++++++++++++++------------ pform.cc | 4 +++- pform.h | 3 ++- pform_types.cc | 51 ++++++++++++++++++++++++++++++++++++++------------ pform_types.h | 36 ++++++++++++++++++++++------------- 10 files changed, 115 insertions(+), 61 deletions(-) diff --git a/PScope.h b/PScope.h index 5f8a6caf4..2d7a7b9d7 100644 --- a/PScope.h +++ b/PScope.h @@ -1,7 +1,7 @@ #ifndef IVL_PScope_H #define IVL_PScope_H /* - * Copyright (c) 2008-2025 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -121,6 +121,8 @@ class LexicalScope { bool overridable; // Whether the parameter is a type parameter bool type_flag = false; + // Type restriction for a type parameter + type_restrict_t type_restrict; // The lexical position of the declaration unsigned lexical_pos = 0; diff --git a/elab_type.cc b/elab_type.cc index d52af2d25..c905791e1 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -452,27 +452,7 @@ ivl_type_t typedef_t::elaborate_type(Design *des, NetScope *scope) if (!elab_type) return netvector_t::integer_type(); - bool type_ok = true; - switch (basic_type) { - case ENUM: - type_ok = dynamic_cast(elab_type); - break; - case STRUCT: { - const netstruct_t *struct_type = dynamic_cast(elab_type); - type_ok = struct_type && !struct_type->union_flag(); - break; - } - case UNION: { - const netstruct_t *struct_type = dynamic_cast(elab_type); - type_ok = struct_type && struct_type->union_flag(); - break; - } - case CLASS: - type_ok = dynamic_cast(elab_type); - break; - default: - break; - } + bool type_ok = basic_type.matches(elab_type); if (!type_ok) { cerr << data_type->get_fileline() << " error: " diff --git a/net_design.cc b/net_design.cc index ab1002323..0491457b9 100644 --- a/net_design.cc +++ b/net_design.cc @@ -838,6 +838,16 @@ void NetScope::evaluate_type_parameter_(Design *des, param_ref_t cur) data_type_t *ptype = type_expr->get_type(); NetScope *type_scope = cur->second.val_scope; cur->second.ivl_type = ptype->elaborate_type(des, type_scope); + if (!cur->second.ivl_type) + return; + + if (!cur->second.type_restrict.matches(cur->second.ivl_type)) { + cerr << type_expr->get_fileline() << ": error: " + << "Type parameter `" << cur->first << "` expects a `" + << cur->second.type_restrict << "` type, got `" + << *cur->second.ivl_type << "`." << endl; + des->errors++; + } } void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) diff --git a/net_scope.cc b/net_scope.cc index ec9d6f912..bd019f93d 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -281,6 +281,7 @@ void NetScope::set_parameter(perm_string key, bool is_annotatable, ref.local_flag = param.local_flag; ref.overridable = param.overridable; ref.type_flag = param.type_flag; + ref.type_restrict = param.type_restrict; ref.lexical_pos = param.lexical_pos; ivl_assert(param, !ref.range); ref.range = range_list; diff --git a/netlist.h b/netlist.h index cfaeba861..a3880604b 100644 --- a/netlist.h +++ b/netlist.h @@ -1279,6 +1279,8 @@ class NetScope : public Definitions, public Attrib { bool overridable = false; // Is it a type parameter bool type_flag = false; + // Type restriction for a type parameter + type_restrict_t type_restrict; // The lexical position of the declaration unsigned lexical_pos = 0; // range constraints diff --git a/parse.y b/parse.y index 69187377d..54a7d2be4 100644 --- a/parse.y +++ b/parse.y @@ -45,6 +45,7 @@ extern void lex_end_table(); static data_type_t* param_data_type = 0; static bool param_is_local = false; static bool param_is_type = false; +static type_restrict_t param_type_restrict; static bool in_gen_region = false; static std::list* specparam_active_range = 0; @@ -598,7 +599,7 @@ Module::port_t *module_declare_interface_port(const YYLTYPE&loc, char *type, LexicalScope::lifetime_t lifetime; - enum typedef_t::basic_type typedef_basic_type; + enum type_restrict_t::type_t type_restrict; }; %token IDENTIFIER INTERFACE_IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL @@ -858,7 +859,7 @@ Module::port_t *module_declare_interface_port(const YYLTYPE&loc, char *type, %type compressed_operator -%type typedef_basic_type +%type forward_type forward_type_without_enum %token K_TAND %nonassoc K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ @@ -2882,11 +2883,16 @@ block_item_decls_opt * `typedef enum ` can either be the start of a enum forward * declaration or a enum type declaration with a type identifier as its base * type. And this abmiguity can not be resolved if we reduce the K_enum to - * typedef_basic_type. */ -typedef_basic_type - : K_struct { $$ = typedef_t::STRUCT; } - | K_union { $$ = typedef_t::UNION; } - | K_class { $$ = typedef_t::CLASS; } + * forward_type_without_enum. */ +forward_type_without_enum + : K_struct { $$ = type_restrict_t::STRUCT; } + | K_union { $$ = type_restrict_t::UNION; } + | K_class { $$ = type_restrict_t::CLASS; } + ; + +forward_type + : K_enum { $$ = type_restrict_t::ENUM; } + | forward_type_without_enum ; /* Type declarations are parsed here. The rule actions call pform @@ -2902,17 +2908,17 @@ type_declaration | K_typedef identifier_name ';' { perm_string name = lex_strings.make($2); - pform_forward_typedef(@2, name, typedef_t::ANY); + pform_forward_typedef(@2, name, type_restrict_t::ANY); delete[]$2; } - | K_typedef typedef_basic_type identifier_name ';' + | K_typedef forward_type_without_enum identifier_name ';' { perm_string name = lex_strings.make($3); pform_forward_typedef(@3, name, $2); delete[]$3; } | K_typedef K_enum identifier_name ';' { perm_string name = lex_strings.make($3); - pform_forward_typedef(@3, name, typedef_t::ENUM); + pform_forward_typedef(@3, name, type_restrict_t::ENUM); delete[]$3; } | K_typedef error ';' @@ -4924,7 +4930,16 @@ module_parameter_port_list_opt ; type_param - : K_type { param_is_type = true; } + : K_type + { param_is_type = true; + param_type_restrict = {}; + } + | K_type forward_type + { if (generation_flag < GN_VER2023) + yyerror(@1, "error: Restricted type parameters require SystemVerilog 2023 or later."); + param_is_type = true; + param_type_restrict = $2; + } ; module_parameter @@ -4940,6 +4955,7 @@ module_parameter_port_list { param_data_type = $1; param_is_local = false; param_is_type = false; + param_type_restrict = {}; } parameter_assign { pform_requires_sv(@3, "Omitting initial `parameter` in parameter port " @@ -4955,6 +4971,7 @@ module_parameter_port_list "data type in parameter port list"); param_data_type = $3; param_is_type = false; + param_type_restrict = {}; } } parameter_assign @@ -5598,6 +5615,7 @@ param_type : data_type_or_implicit { param_is_type = false; param_data_type = $1; + param_type_restrict = {}; } | type_param @@ -5632,7 +5650,8 @@ parameter_assign_list parameter_assign : IDENTIFIER dimensions_opt initializer_opt parameter_value_ranges_opt { pform_set_parameter(@1, lex_strings.make($1), param_is_local, - param_is_type, param_data_type, $2, $3, $4); + param_is_type, param_type_restrict, + param_data_type, $2, $3, $4); delete[]$1; } ; diff --git a/pform.cc b/pform.cc index 0ef02563f..17a6bdbac 100644 --- a/pform.cc +++ b/pform.cc @@ -841,7 +841,7 @@ static typedef_t *pform_get_typedef(const struct vlltype&loc, perm_string name) } void pform_forward_typedef(const struct vlltype&loc, perm_string name, - enum typedef_t::basic_type basic_type) + type_restrict_t basic_type) { typedef_t *td = pform_get_typedef(loc, name); @@ -2948,6 +2948,7 @@ static void pform_set_type_parameter(const struct vlltype&loc, perm_string name, void pform_set_parameter(const struct vlltype&loc, perm_string name, bool is_local, bool is_type, + type_restrict_t type_restrict, data_type_t*data_type, const list*udims, PExpr*expr, LexicalScope::range_t*value_range) { @@ -3020,6 +3021,7 @@ void pform_set_parameter(const struct vlltype&loc, parm->local_flag = is_local; parm->overridable = overridable; parm->type_flag = is_type; + parm->type_restrict = type_restrict; parm->lexical_pos = loc.lexical_pos; scope->parameters[name] = parm; diff --git a/pform.h b/pform.h index 95d60d458..781743258 100644 --- a/pform.h +++ b/pform.h @@ -323,7 +323,7 @@ extern void pform_set_typedef(const struct vlltype&loc, perm_string name, data_type_t*data_type, std::list*unp_ranges = nullptr); extern void pform_forward_typedef(const struct vlltype&loc, perm_string name, - enum typedef_t::basic_type basic_type); + type_restrict_t basic_type); extern void pform_set_type_referenced(const struct vlltype&loc, const char*name); @@ -412,6 +412,7 @@ extern LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag, extern void pform_set_parameter(const struct vlltype&loc, perm_string name, bool is_local, bool is_type, + type_restrict_t type_restrict, data_type_t*data_type, const std::list*udims, PExpr*expr, LexicalScope::range_t*value_range); extern void pform_set_specparam(const struct vlltype&loc, diff --git a/pform_types.cc b/pform_types.cc index f69c5d908..f9af4f1fe 100644 --- a/pform_types.cc +++ b/pform_types.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2019 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2026 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -19,6 +19,8 @@ # include "pform_types.h" +# include "netclass.h" +# include "netenum.h" data_type_t::~data_type_t() { @@ -55,34 +57,59 @@ bool typedef_t::set_data_type(data_type_t *t) return true; } -bool typedef_t::set_basic_type(enum basic_type bt) +bool typedef_t::set_basic_type(type_restrict_t type) { - if (bt == ANY) + return basic_type.merge(type); +} + +bool type_restrict_t::merge(type_restrict_t other) +{ + if (other.type == ANY) return true; - if (basic_type != ANY && bt != basic_type) + if (this->type != ANY && other.type != this->type) return false; - basic_type = bt; + this->type = other.type; return true; } -std::ostream& operator<< (std::ostream&out, enum typedef_t::basic_type bt) +bool type_restrict_t::matches(ivl_type_t ivl_type) const { - switch (bt) { - case typedef_t::ANY: + switch (this->type) { + case ENUM: + return dynamic_cast(ivl_type); + case STRUCT: { + const netstruct_t *struct_type = dynamic_cast(ivl_type); + return struct_type && !struct_type->union_flag(); + } + case UNION: { + const netstruct_t *struct_type = dynamic_cast(ivl_type); + return struct_type && struct_type->union_flag(); + } + case CLASS: + return dynamic_cast(ivl_type); + default: + return true; + } +} + +std::ostream& operator<< (std::ostream&out, const type_restrict_t& type) +{ + switch (type.type) { + case type_restrict_t::ANY: out << "any"; break; - case typedef_t::ENUM: + case type_restrict_t::ENUM: out << "enum"; break; - case typedef_t::STRUCT: + case type_restrict_t::STRUCT: out << "struct"; break; - case typedef_t::UNION: + case type_restrict_t::UNION: out << "union"; break; - case typedef_t::CLASS: + case type_restrict_t::CLASS: out << "class"; break; } diff --git a/pform_types.h b/pform_types.h index 2ed4e7469..29fedb693 100644 --- a/pform_types.h +++ b/pform_types.h @@ -49,6 +49,24 @@ class netclass_t; class netenum_t; typedef named named_pexpr_t; +struct type_restrict_t { + enum type_t { + ANY, + ENUM, + STRUCT, + UNION, + CLASS + }; + + type_restrict_t() = default; + type_restrict_t(type_t kind) : type(kind) { } + + bool merge(type_restrict_t other); + bool matches(ivl_type_t type) const; + + enum type_t type = ANY; +}; + /* * The pform_ident_t holds the identifier name and its lexical position * (the lexical_pos supplied by the scanner). @@ -180,26 +198,18 @@ class data_type_t : public PNamedItem { }; struct typedef_t : public PNamedItem { - explicit typedef_t(perm_string n) : basic_type(ANY), name(n) { }; + explicit typedef_t(perm_string n) : name(n) { }; ivl_type_t elaborate_type(Design*des, NetScope*scope); - enum basic_type { - ANY, - ENUM, - STRUCT, - UNION, - CLASS - }; - bool set_data_type(data_type_t *t); const data_type_t *get_data_type() const { return data_type.get(); } - bool set_basic_type(basic_type bt); - enum basic_type get_basic_type() const { return basic_type; } + bool set_basic_type(type_restrict_t type); + type_restrict_t get_basic_type() const { return basic_type; } protected: - enum basic_type basic_type; + type_restrict_t basic_type; std::unique_ptr data_type; public: perm_string name; @@ -498,6 +508,6 @@ extern std::ostream& operator<< (std::ostream&out, const pform_name_t&); extern std::ostream& operator<< (std::ostream&out, const pform_scoped_name_t&); extern std::ostream& operator<< (std::ostream&out, const name_component_t&that); extern std::ostream& operator<< (std::ostream&out, const index_component_t&that); -extern std::ostream& operator<< (std::ostream&out, enum typedef_t::basic_type bt); +extern std::ostream& operator<< (std::ostream&out, const type_restrict_t& type); #endif /* IVL_pform_types_H */ From 08479888b1880093e2fe050afa514755c4d0fe7a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 16 May 2026 16:13:44 -0700 Subject: [PATCH 2/2] Add regression tests for restricted type parameters Check that enum, struct, union and class restricted type parameters are accepted. Check that mismatched default values and overrides are rejected. Signed-off-by: Lars-Peter Clausen --- .../ivltests/sv_type_param_restrict_class1.v | 35 ++++++++++++++++ .../ivltests/sv_type_param_restrict_class2.v | 41 +++++++++++++++++++ .../sv_type_param_restrict_class_fail1.v | 11 +++++ .../sv_type_param_restrict_class_fail2.v | 21 ++++++++++ .../ivltests/sv_type_param_restrict_enum1.v | 33 +++++++++++++++ .../ivltests/sv_type_param_restrict_enum2.v | 39 ++++++++++++++++++ .../sv_type_param_restrict_enum_fail1.v | 11 +++++ .../sv_type_param_restrict_enum_fail2.v | 22 ++++++++++ .../ivltests/sv_type_param_restrict_struct1.v | 33 +++++++++++++++ .../ivltests/sv_type_param_restrict_struct2.v | 39 ++++++++++++++++++ .../sv_type_param_restrict_struct_fail1.v | 16 ++++++++ .../sv_type_param_restrict_struct_fail2.v | 27 ++++++++++++ .../ivltests/sv_type_param_restrict_union1.v | 34 +++++++++++++++ .../ivltests/sv_type_param_restrict_union2.v | 41 +++++++++++++++++++ .../sv_type_param_restrict_union_fail1.v | 15 +++++++ .../sv_type_param_restrict_union_fail2.v | 27 ++++++++++++ ivtest/regress-vvp.list | 16 ++++++++ .../sv_type_param_restrict_class1.json | 9 ++++ .../sv_type_param_restrict_class2.json | 9 ++++ .../sv_type_param_restrict_class_fail1.json | 5 +++ .../sv_type_param_restrict_class_fail2.json | 5 +++ .../sv_type_param_restrict_enum1.json | 5 +++ .../sv_type_param_restrict_enum2.json | 5 +++ .../sv_type_param_restrict_enum_fail1.json | 5 +++ .../sv_type_param_restrict_enum_fail2.json | 5 +++ .../sv_type_param_restrict_struct1.json | 5 +++ .../sv_type_param_restrict_struct2.json | 5 +++ .../sv_type_param_restrict_struct_fail1.json | 5 +++ .../sv_type_param_restrict_struct_fail2.json | 5 +++ .../sv_type_param_restrict_union1.json | 5 +++ .../sv_type_param_restrict_union2.json | 5 +++ .../sv_type_param_restrict_union_fail1.json | 5 +++ .../sv_type_param_restrict_union_fail2.json | 5 +++ 33 files changed, 549 insertions(+) create mode 100644 ivtest/ivltests/sv_type_param_restrict_class1.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_class2.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_class_fail1.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_class_fail2.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_enum1.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_enum2.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_enum_fail1.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_enum_fail2.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_struct1.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_struct2.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_struct_fail1.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_struct_fail2.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_union1.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_union2.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_union_fail1.v create mode 100644 ivtest/ivltests/sv_type_param_restrict_union_fail2.v create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_class1.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_class2.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_class_fail1.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_class_fail2.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_enum1.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_enum2.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_enum_fail1.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_enum_fail2.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_struct1.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_struct2.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_struct_fail1.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_struct_fail2.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_union1.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_union2.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_union_fail1.json create mode 100644 ivtest/vvp_tests/sv_type_param_restrict_union_fail2.json diff --git a/ivtest/ivltests/sv_type_param_restrict_class1.v b/ivtest/ivltests/sv_type_param_restrict_class1.v new file mode 100644 index 000000000..9488edcc6 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_class1.v @@ -0,0 +1,35 @@ +// Check that restricted class type parameter defaults are supported. + +class C0; + bit [7:0] value; +endclass + +module M #( + parameter type class T = C0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M i_m(); + + initial begin + i_m.x = new; + + `check($bits(i_m.x.value), 8) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_class2.v b/ivtest/ivltests/sv_type_param_restrict_class2.v new file mode 100644 index 000000000..adcc6a626 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_class2.v @@ -0,0 +1,41 @@ +// Check that restricted class type parameter overrides are supported. + +class C0; + bit [7:0] value; +endclass + +class C1; + bit [15:0] value; +endclass + +module M #( + parameter type class T = C0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M #( + .T(C1) + ) i_m(); + + initial begin + i_m.x = new; + + `check($bits(i_m.x.value), 16) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_class_fail1.v b/ivtest/ivltests/sv_type_param_restrict_class_fail1.v new file mode 100644 index 000000000..d769159a9 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_class_fail1.v @@ -0,0 +1,11 @@ +// Check that a class restricted type parameter rejects non-class defaults. + +module test #( + parameter type class T = int +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_class_fail2.v b/ivtest/ivltests/sv_type_param_restrict_class_fail2.v new file mode 100644 index 000000000..0c6781015 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_class_fail2.v @@ -0,0 +1,21 @@ +// Check that a class restricted type parameter rejects non-class overrides. + +class class_t; +endclass + +module M #( + parameter type class T = class_t +); +endmodule + +module test; + + M #( + .T(int) + ) i_m(); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_enum1.v b/ivtest/ivltests/sv_type_param_restrict_enum1.v new file mode 100644 index 000000000..60d920724 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_enum1.v @@ -0,0 +1,33 @@ +// Check that restricted enum type parameter defaults are supported. + +typedef enum bit [2:0] { + A0, B0 +} T0; + +module M #( + parameter type enum T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M i_m(); + + initial begin + `check($bits(i_m.x), $bits(T0)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_enum2.v b/ivtest/ivltests/sv_type_param_restrict_enum2.v new file mode 100644 index 000000000..028e8eec6 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_enum2.v @@ -0,0 +1,39 @@ +// Check that restricted enum type parameter overrides are supported. + +typedef enum bit [2:0] { + A0, B0 +} T0; + +typedef enum bit [3:0] { + A1, B1 +} T1; + +module M #( + parameter type enum T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M #( + .T(T1) + ) i_m(); + + initial begin + `check($bits(i_m.x), $bits(T1)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_enum_fail1.v b/ivtest/ivltests/sv_type_param_restrict_enum_fail1.v new file mode 100644 index 000000000..a36c1e8c7 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_enum_fail1.v @@ -0,0 +1,11 @@ +// Check that an enum restricted type parameter rejects non-enum defaults. + +module test #( + parameter type enum T = int +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_enum_fail2.v b/ivtest/ivltests/sv_type_param_restrict_enum_fail2.v new file mode 100644 index 000000000..1e1f564ae --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_enum_fail2.v @@ -0,0 +1,22 @@ +// Check that an enum restricted type parameter rejects non-enum overrides. + +typedef enum bit { + ENUM_VALUE +} enum_t; + +module M #( + parameter type enum T = enum_t +); +endmodule + +module test; + + M #( + .T(int) + ) i_m(); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_struct1.v b/ivtest/ivltests/sv_type_param_restrict_struct1.v new file mode 100644 index 000000000..a127b117e --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_struct1.v @@ -0,0 +1,33 @@ +// Check that restricted struct type parameter defaults are supported. + +typedef struct packed { + logic [3:0] x; +} T0; + +module M #( + parameter type struct T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M i_m(); + + initial begin + `check($bits(i_m.x), $bits(T0)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_struct2.v b/ivtest/ivltests/sv_type_param_restrict_struct2.v new file mode 100644 index 000000000..c3b30f58b --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_struct2.v @@ -0,0 +1,39 @@ +// Check that restricted struct type parameter overrides are supported. + +typedef struct packed { + logic [3:0] x; +} T0; + +typedef struct packed { + logic [7:0] x; +} T1; + +module M #( + parameter type struct T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M #( + .T(T1) + ) i_m(); + + initial begin + `check($bits(i_m.x), $bits(T1)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_struct_fail1.v b/ivtest/ivltests/sv_type_param_restrict_struct_fail1.v new file mode 100644 index 000000000..ff707bdf7 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_struct_fail1.v @@ -0,0 +1,16 @@ +// Check that a struct restricted type parameter rejects non-struct defaults. + +typedef union packed { + logic [3:0] value; + logic [3:0] other; +} union_t; + +module test #( + parameter type struct T = union_t +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_struct_fail2.v b/ivtest/ivltests/sv_type_param_restrict_struct_fail2.v new file mode 100644 index 000000000..bd78897a7 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_struct_fail2.v @@ -0,0 +1,27 @@ +// Check that a struct restricted type parameter rejects non-struct overrides. + +typedef struct packed { + logic [3:0] value; +} struct_t; + +typedef union packed { + logic [3:0] value; + logic [3:0] other; +} union_t; + +module M #( + parameter type struct T = struct_t +); +endmodule + +module test; + + M #( + .T(union_t) + ) i_m(); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_union1.v b/ivtest/ivltests/sv_type_param_restrict_union1.v new file mode 100644 index 000000000..df337c21e --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_union1.v @@ -0,0 +1,34 @@ +// Check that restricted union type parameter defaults are supported. + +typedef union packed { + logic [3:0] x; + logic [3:0] y; +} T0; + +module M #( + parameter type union T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M i_m(); + + initial begin + `check($bits(i_m.x), $bits(T0)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_union2.v b/ivtest/ivltests/sv_type_param_restrict_union2.v new file mode 100644 index 000000000..588a245b2 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_union2.v @@ -0,0 +1,41 @@ +// Check that restricted union type parameter overrides are supported. + +typedef union packed { + logic [3:0] x; + logic [3:0] y; +} T0; + +typedef union packed { + logic [7:0] x; + logic [7:0] y; +} T1; + +module M #( + parameter type union T = T0 +); + T x; +endmodule + +module test; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ + failed = 1'b1; \ + end + + bit failed = 1'b0; + + M #( + .T(T1) + ) i_m(); + + initial begin + `check($bits(i_m.x), $bits(T1)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_union_fail1.v b/ivtest/ivltests/sv_type_param_restrict_union_fail1.v new file mode 100644 index 000000000..1d581e36c --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_union_fail1.v @@ -0,0 +1,15 @@ +// Check that a union restricted type parameter rejects non-union defaults. + +typedef struct packed { + logic [3:0] value; +} struct_t; + +module test #( + parameter type union T = struct_t +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_type_param_restrict_union_fail2.v b/ivtest/ivltests/sv_type_param_restrict_union_fail2.v new file mode 100644 index 000000000..b49552c17 --- /dev/null +++ b/ivtest/ivltests/sv_type_param_restrict_union_fail2.v @@ -0,0 +1,27 @@ +// Check that a union restricted type parameter rejects non-union overrides. + +typedef struct packed { + logic [3:0] value; +} struct_t; + +typedef union packed { + logic [3:0] value; + logic [3:0] other; +} union_t; + +module M #( + parameter type union T = union_t +); +endmodule + +module test; + + M #( + .T(struct_t) + ) i_m(); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 9ffa708db..7831ff27f 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -342,6 +342,22 @@ sv_queue_assign_op vvp_tests/sv_queue_assign_op.json sv_soft_packed_union vvp_tests/sv_soft_packed_union.json sv_soft_packed_union_fail1 vvp_tests/sv_soft_packed_union_fail1.json sv_super_member_fail vvp_tests/sv_super_member_fail.json +sv_type_param_restrict_class1 vvp_tests/sv_type_param_restrict_class1.json +sv_type_param_restrict_class2 vvp_tests/sv_type_param_restrict_class2.json +sv_type_param_restrict_class_fail1 vvp_tests/sv_type_param_restrict_class_fail1.json +sv_type_param_restrict_class_fail2 vvp_tests/sv_type_param_restrict_class_fail2.json +sv_type_param_restrict_enum1 vvp_tests/sv_type_param_restrict_enum1.json +sv_type_param_restrict_enum2 vvp_tests/sv_type_param_restrict_enum2.json +sv_type_param_restrict_enum_fail1 vvp_tests/sv_type_param_restrict_enum_fail1.json +sv_type_param_restrict_enum_fail2 vvp_tests/sv_type_param_restrict_enum_fail2.json +sv_type_param_restrict_struct1 vvp_tests/sv_type_param_restrict_struct1.json +sv_type_param_restrict_struct2 vvp_tests/sv_type_param_restrict_struct2.json +sv_type_param_restrict_struct_fail1 vvp_tests/sv_type_param_restrict_struct_fail1.json +sv_type_param_restrict_struct_fail2 vvp_tests/sv_type_param_restrict_struct_fail2.json +sv_type_param_restrict_union1 vvp_tests/sv_type_param_restrict_union1.json +sv_type_param_restrict_union2 vvp_tests/sv_type_param_restrict_union2.json +sv_type_param_restrict_union_fail1 vvp_tests/sv_type_param_restrict_union_fail1.json +sv_type_param_restrict_union_fail2 vvp_tests/sv_type_param_restrict_union_fail2.json sv_wildcard_import8 vvp_tests/sv_wildcard_import8.json sdf_header vvp_tests/sdf_header.json task_return1 vvp_tests/task_return1.json diff --git a/ivtest/vvp_tests/sv_type_param_restrict_class1.json b/ivtest/vvp_tests/sv_type_param_restrict_class1.json new file mode 100644 index 000000000..333ccba29 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_class1.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_class1.v", + "iverilog-args" : [ "-g2023" ], + "vlog95" : { + "__comment" : "Classes are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_class2.json b/ivtest/vvp_tests/sv_type_param_restrict_class2.json new file mode 100644 index 000000000..f9e01d0f3 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_class2.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_class2.v", + "iverilog-args" : [ "-g2023" ], + "vlog95" : { + "__comment" : "Classes are not supported", + "type" : "CE" + } +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_class_fail1.json b/ivtest/vvp_tests/sv_type_param_restrict_class_fail1.json new file mode 100644 index 000000000..37ad86428 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_class_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_class_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_class_fail2.json b/ivtest/vvp_tests/sv_type_param_restrict_class_fail2.json new file mode 100644 index 000000000..3777c906f --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_class_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_class_fail2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_enum1.json b/ivtest/vvp_tests/sv_type_param_restrict_enum1.json new file mode 100644 index 000000000..f06dd96db --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_enum1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_enum1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_enum2.json b/ivtest/vvp_tests/sv_type_param_restrict_enum2.json new file mode 100644 index 000000000..cefdc3f87 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_enum2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_enum2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_enum_fail1.json b/ivtest/vvp_tests/sv_type_param_restrict_enum_fail1.json new file mode 100644 index 000000000..1f65e7c27 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_enum_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_enum_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_enum_fail2.json b/ivtest/vvp_tests/sv_type_param_restrict_enum_fail2.json new file mode 100644 index 000000000..419f415d5 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_enum_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_enum_fail2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_struct1.json b/ivtest/vvp_tests/sv_type_param_restrict_struct1.json new file mode 100644 index 000000000..fc0aa3d09 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_struct1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_struct1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_struct2.json b/ivtest/vvp_tests/sv_type_param_restrict_struct2.json new file mode 100644 index 000000000..adb31537f --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_struct2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_struct2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_struct_fail1.json b/ivtest/vvp_tests/sv_type_param_restrict_struct_fail1.json new file mode 100644 index 000000000..f8cd7c732 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_struct_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_struct_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_struct_fail2.json b/ivtest/vvp_tests/sv_type_param_restrict_struct_fail2.json new file mode 100644 index 000000000..4bc7cae76 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_struct_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_struct_fail2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_union1.json b/ivtest/vvp_tests/sv_type_param_restrict_union1.json new file mode 100644 index 000000000..642b76ba5 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_union1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_union1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_union2.json b/ivtest/vvp_tests/sv_type_param_restrict_union2.json new file mode 100644 index 000000000..b804064d0 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_union2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_param_restrict_union2.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_union_fail1.json b/ivtest/vvp_tests/sv_type_param_restrict_union_fail1.json new file mode 100644 index 000000000..bb2ea1054 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_union_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_union_fail1.v", + "iverilog-args" : [ "-g2023" ] +} diff --git a/ivtest/vvp_tests/sv_type_param_restrict_union_fail2.json b/ivtest/vvp_tests/sv_type_param_restrict_union_fail2.json new file mode 100644 index 000000000..49cc68e0b --- /dev/null +++ b/ivtest/vvp_tests/sv_type_param_restrict_union_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_type_param_restrict_union_fail2.v", + "iverilog-args" : [ "-g2023" ] +}