From fabff5ef5fc5d2a93f6cbbc3cac0afb46973fad9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Mar 2022 15:03:53 +0100 Subject: [PATCH 1/2] Restrict enum compatibility to the same scope An enum data type declared in a module is not compatible between different instances of the module. The type is unique in each hierarchical instance scope. The type can for example depend on module parameters which would result in conflicting definitions. This is defined in section 6.22 ("Type compatibility") of the LRM (1800-2017). At the moment enum compatibility is checked by comparing the enum_type_t. But the enum_type_t is shared among the netenum_t that are created for each module instance and gives the wrong result. Since there is exactly one netenum_t created for each enum and each instantiated scope use this to check if the data type of two enum type signals is compatible. Signed-off-by: Lars-Peter Clausen --- elab_scope.cc | 3 +-- netenum.cc | 10 ++++------ netenum.h | 5 +---- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/elab_scope.cc b/elab_scope.cc index aacedcc63..fe39506e9 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -186,8 +186,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, netenum_t*use_enum = new netenum_t(enum_type->base_type, enum_type->signed_flag, enum_type->integer_flag, range, - enum_type->names->size(), - enum_type); + enum_type->names->size()); use_enum->set_line(*enum_type); scope->add_enumeration_set(enum_type, use_enum); diff --git a/netenum.cc b/netenum.cc index bb53088bc..7ff455926 100644 --- a/netenum.cc +++ b/netenum.cc @@ -24,11 +24,9 @@ using namespace std; netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag, - bool integer_flag, const netrange_t &range, size_t name_count, - enum_type_t*enum_type) -: base_type_(btype), enum_type_(enum_type), signed_flag_(signed_flag), - integer_flag_(integer_flag), range_(range), - names_(name_count), bits_(name_count) + bool integer_flag, const netrange_t &range, size_t name_count) +: base_type_(btype), signed_flag_(signed_flag), integer_flag_(integer_flag), + range_(range), names_(name_count), bits_(name_count) { } @@ -159,5 +157,5 @@ perm_string netenum_t::bits_at(size_t idx) const bool netenum_t::matches(const netenum_t*other) const { - return enum_type_ == other->enum_type_; + return this == other; } diff --git a/netenum.h b/netenum.h index b05675cfe..94f7cd8cd 100644 --- a/netenum.h +++ b/netenum.h @@ -29,14 +29,12 @@ class NetScope; -struct enum_type_t; - class netenum_t : public LineInfo, public ivl_type_s { public: explicit netenum_t(ivl_variable_type_t base_type, bool signed_flag, bool isint_flag, const netrange_t &range, - size_t name_count, enum_type_t*enum_type); + size_t name_count); ~netenum_t(); virtual ivl_variable_type_t base_type() const; @@ -74,7 +72,6 @@ class netenum_t : public LineInfo, public ivl_type_s { private: ivl_variable_type_t base_type_; - enum_type_t*enum_type_; bool signed_flag_; bool integer_flag_; netrange_t range_; From 83da384df36753a5d3cea59ec3c32777973b0088 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Mar 2022 16:46:03 +0100 Subject: [PATCH 2/2] Add regression test for enum compatibility across module boundaries Check that the compatibility of signals of enum data type across module boundaries. If the enum data type is declared at a higher level scope or imported from a package the signals are compatible between different module instances. If the enum data type is declared within the module itself though the signals are not compatible. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/enum_compatibility1.v | 25 +++++++++++++++++++ ivtest/ivltests/enum_compatibility2.v | 30 +++++++++++++++++++++++ ivtest/ivltests/enum_compatibility3.v | 30 +++++++++++++++++++++++ ivtest/ivltests/enum_compatibility_fail.v | 21 ++++++++++++++++ ivtest/regress-sv.list | 4 +++ 5 files changed, 110 insertions(+) create mode 100644 ivtest/ivltests/enum_compatibility1.v create mode 100644 ivtest/ivltests/enum_compatibility2.v create mode 100644 ivtest/ivltests/enum_compatibility3.v create mode 100644 ivtest/ivltests/enum_compatibility_fail.v diff --git a/ivtest/ivltests/enum_compatibility1.v b/ivtest/ivltests/enum_compatibility1.v new file mode 100644 index 000000000..25beb89f9 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility1.v @@ -0,0 +1,25 @@ +// Check that enum types declared in a higher level scope are compatible between +// different instances of a module. + +typedef enum integer { + A +} T; + +module M; + T e; +endmodule + +module test; + M m1(); + M m2(); + + initial begin + m1.e = A; + m2.e = m1.e; + if (m2.e === A) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end +endmodule diff --git a/ivtest/ivltests/enum_compatibility2.v b/ivtest/ivltests/enum_compatibility2.v new file mode 100644 index 000000000..f98a35489 --- /dev/null +++ b/ivtest/ivltests/enum_compatibility2.v @@ -0,0 +1,30 @@ +// Check that enum types explicitly imported from a package are compatible +// between different instances of a module. + +package P; + typedef enum integer { + A + } T; +endpackage + +module M; + import P::T; + T e; +endmodule + +module test; + import P::A; + + M m1(); + M m2(); + + initial begin + m1.e = A; + m2.e = m1.e; + if (m2.e === A) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end +endmodule diff --git a/ivtest/ivltests/enum_compatibility3.v b/ivtest/ivltests/enum_compatibility3.v new file mode 100644 index 000000000..6395009ad --- /dev/null +++ b/ivtest/ivltests/enum_compatibility3.v @@ -0,0 +1,30 @@ +// Check that enum types implicitly imported from a package are compatible +// between different instances of a module. + +package P; + typedef enum integer { + A + } T; +endpackage + +module M; + import P::*; + T e; +endmodule + +module test; + import P::*; + + M m1(); + M m2(); + + initial begin + m1.e = A; + m2.e = m1.e; + if (m2.e === A) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end +endmodule diff --git a/ivtest/ivltests/enum_compatibility_fail.v b/ivtest/ivltests/enum_compatibility_fail.v new file mode 100644 index 000000000..169c1263d --- /dev/null +++ b/ivtest/ivltests/enum_compatibility_fail.v @@ -0,0 +1,21 @@ +// Check that enums declared within a module are not compatible between +// different instances of a module + +module M; + + enum integer { + A + } e; + +endmodule + +module test; + M m1(); + M m2(); + + initial begin + // These are different types and not compatible + m1.e = m2.e; + $display("FAILED"); + end +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 278d6a3fa..5fd1b798a 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -232,6 +232,10 @@ disable_fork_cmd normal,-g2009 ivltests display_bug normal,-g2009 ivltests gold=display_bug.gold edge normal,-g2009 ivltests enum_base_range normal,-g2005-sv ivltests +enum_compatibility1 normal,-g2005-sv ivltests +enum_compatibility2 normal,-g2005-sv ivltests +enum_compatibility3 normal,-g2005-sv ivltests +enum_compatibility_fail CE,-g2005-sv ivltests enum_elem_ranges normal,-g2005-sv ivltests enum_dims_invalid CE,-g2005-sv ivltests enum_in_struct normal,-g2005-sv ivltests