diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 1acd086d3..9b66893d4 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -3118,8 +3118,14 @@ public: virtual string name() const override { return m_name; } // * = Var name AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; } void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; } - AstNodeModule* classOrPackagep() const { return VN_AS(m_classOrPackageNodep, NodeModule); } - AstPackage* packagep() const { return VN_AS(classOrPackageNodep(), Package); } + AstNodeModule* classOrPackagep() const { + AstNode* foundp = m_classOrPackageNodep; + while (auto* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep(); + while (auto* const anodep = VN_CAST(foundp, ClassRefDType)) + foundp = anodep->classOrPackagep(); + return VN_CAST(foundp, NodeModule); + } + AstPackage* packagep() const { return VN_CAST(classOrPackageNodep(), Package); } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackageNodep = nodep; } AstPin* paramsp() const { return VN_AS(op4p(), Pin); } }; diff --git a/test_regress/t/t_class_param.out b/test_regress/t/t_class_param.out index f1badbdd8..442cfc01e 100644 --- a/test_regress/t/t_class_param.out +++ b/test_regress/t/t_class_param.out @@ -1,30 +1,30 @@ -%Error-UNSUPPORTED: t/t_class_param.v:32:11: Unsupported: parameterized classes +%Error-UNSUPPORTED: t/t_class_param.v:40:11: Unsupported: parameterized classes : ... In instance t - 32 | Cls #(.P(4)) c4; - | ^ + 40 | Cls #(.PBASE(4)) c4; + | ^~~~~ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error-UNSUPPORTED: t/t_class_param.v:34:12: Unsupported: parameterized classes +%Error-UNSUPPORTED: t/t_class_param.v:42:12: Unsupported: parameterized classes : ... In instance t - 34 | Wrap #(.PMINUS1(15)) w16; - | ^~~~~~~ -%Error-UNSUPPORTED: t/t_class_param.v:7:23: Unsupported: class parameters - : ... In instance t - 7 | class Cls #(parameter P = 12); - | ^ -%Error-UNSUPPORTED: t/t_class_param.v:17:24: Unsupported: class parameters + 42 | Wrap #(.P(16)) w16; + | ^ +%Error-UNSUPPORTED: t/t_class_param.v:13:24: Unsupported: class parameters : ... In instance t - 17 | class Wrap #(parameter PMINUS1 = 3); - | ^~~~~~~ -%Error-UNSUPPORTED: t/t_class_param.v:18:15: Unsupported: class parameters + 13 | class Wrap #(parameter P = 13); + | ^ +%Error-UNSUPPORTED: t/t_class_param.v:21:15: Unsupported: class parameters : ... In instance t - 18 | localparam P = PMINUS1 + 1; - | ^ -%Error-UNSUPPORTED: t/t_class_param.v:19:9: Unsupported: parameterized classes - : ... In instance t - 19 | Cls#(P) c1; - | ^ -%Error-UNSUPPORTED: t/t_class_param.v:25:14: Unsupported: parameterized classes + 21 | localparam PMINUS1 = P - 1; + | ^~~~~~~ +%Error-UNSUPPORTED: t/t_class_param.v:20:17: Unsupported: parameterized classes : ... In instance t - 25 | typedef Cls#(5) Cls5_t; + 20 | Cls#(PMINUS1 + 1) c1; + | ^ +%Error-UNSUPPORTED: t/t_class_param.v:24:23: Unsupported: class parameters + : ... In instance t + 24 | class Cls #(parameter PBASE = 12); + | ^~~~~ +%Error-UNSUPPORTED: t/t_class_param.v:35:14: Unsupported: parameterized classes + : ... In instance t + 35 | typedef Cls#(8) Cls8_t; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_class_param.v b/test_regress/t/t_class_param.v index bb1dd29b3..0fc61cb76 100644 --- a/test_regress/t/t_class_param.v +++ b/test_regress/t/t_class_param.v @@ -4,58 +4,79 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 -class Cls #(parameter P = 12); - bit [P-1:0] member; - function bit [P-1:0] get_member; - return member; - endfunction - function int get_p; - return P; - endfunction -endclass +`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); -class Wrap #(parameter PMINUS1 = 3); - localparam P = PMINUS1 + 1; - Cls#(P) c1; +// See also t_class_param_mod.v + +typedef class Cls; + +class Wrap #(parameter P = 13); function int get_p; return c1.get_p(); endfunction + function new; + c1 = new; + endfunction + Cls#(PMINUS1 + 1) c1; + localparam PMINUS1 = P - 1; // Checking works when last endclass -typedef Cls#(5) Cls5_t; +class Cls #(parameter PBASE = 12); + bit [PBASE-1:0] member; + function bit [PBASE-1:0] get_member; + return member; + endfunction + static function int get_p; + return PBASE; + endfunction + typedef enum { E_PBASE = PBASE } enum_t; +endclass -// See also t_class_param_mod.v +typedef Cls#(8) Cls8_t; module t (/*AUTOARG*/); Cls c12; - Cls #(.P(4)) c4; - Cls5_t c5; - Wrap #(.PMINUS1(15)) w16; - + Cls #(.PBASE(4)) c4; + Cls8_t c8; + Wrap #(.P(16)) w16; initial begin c12 = new; c4 = new; - c5 = new; + c8 = new; w16 = new; - if (c12.P != 12) $stop; - if (c4.P != 4) $stop; - if (c5.P != 5) $stop; + if (Cls#()::PBASE != 12) $stop; + if (Cls#(4)::PBASE != 4) $stop; + if (Cls8_t::PBASE != 8) $stop; + + if (Cls#()::E_PBASE != 12) $stop; + if (Cls#(4)::E_PBASE != 4) $stop; + if (Cls8_t::E_PBASE != 8) $stop; + + if (c12.PBASE != 12) $stop; + if (c4.PBASE != 4) $stop; + if (c8.PBASE != 8) $stop; + + if (Cls#()::get_p() != 12) $stop; + if (Cls#(4)::get_p() != 4) $stop; + if (Cls8_t::get_p() != 8) $stop; + if (c12.get_p() != 12) $stop; if (c4.get_p() != 4) $stop; - if (c5.get_p() != 5) $stop; + if (c8.get_p() != 8) $stop; if (w16.get_p() != 16) $stop; + // verilator lint_off WIDTH c12.member = 32'haaaaaaaa; c4.member = 32'haaaaaaaa; - c5.member = 32'haaaaaaaa; + c8.member = 32'haaaaaaaa; // verilator lint_on WIDTH if (c12.member != 12'haaa) $stop; if (c4.member != 4'ha) $stop; if (c12.get_member() != 12'haaa) $stop; if (c4.get_member() != 4'ha) $stop; - if ($sformatf("%p", c12) != "'{member:'haaa}") $stop; - if ($sformatf("%p", c4) != "'{member:'ha}") $stop; + `checks($sformatf("%p", c12), "'{member:'haaa}"); + `checks($sformatf("%p", c4), "'{member:'ha}"); $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_class_param_mod.v b/test_regress/t/t_class_param_mod.v index 1ab090625..67065e2d7 100644 --- a/test_regress/t/t_class_param_mod.v +++ b/test_regress/t/t_class_param_mod.v @@ -4,58 +4,77 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); + // See also t_class_param.v module t (/*AUTOARG*/); -class Cls #(parameter P = 12); - bit [P-1:0] member; - function bit [P-1:0] get_member; +class Cls #(parameter PBASE = 12); + bit [PBASE-1:0] member; + function bit [PBASE-1:0] get_member; return member; endfunction - function int get_p; - return P; + static function int get_p; + return PBASE; endfunction + typedef enum { E_PBASE = PBASE } enum_t; endclass -class Wrap #(parameter PMINUS1 = 3); - localparam P = PMINUS1 + 1; - Cls#(P) c1; +class Wrap #(parameter P = 13); function int get_p; return c1.get_p(); endfunction + function new; + c1 = new; + endfunction + Cls#(PMINUS1 + 1) c1; + localparam PMINUS1 = P - 1; // Checking works when last endclass - typedef Cls#(5) Cls5_t; + typedef Cls#(8) Cls8_t; Cls c12; - Cls #(.P(4)) c4; - Cls5_t c5; - Wrap #(.PMINUS1(15)) w16; - + Cls #(.PBASE(4)) c4; + Cls8_t c8; + Wrap #(.P(16)) w16; initial begin c12 = new; c4 = new; - c5 = new; + c8 = new; w16 = new; - if (c12.P != 12) $stop; - if (c4.P != 4) $stop; - if (c5.P != 5) $stop; + if (Cls#()::PBASE != 12) $stop; + if (Cls#(4)::PBASE != 4) $stop; + if (Cls8_t::PBASE != 8) $stop; + + if (Cls#()::E_PBASE != 12) $stop; + if (Cls#(4)::E_PBASE != 4) $stop; + if (Cls8_t::E_PBASE != 8) $stop; + + if (c12.PBASE != 12) $stop; + if (c4.PBASE != 4) $stop; + if (c8.PBASE != 8) $stop; + + if (Cls#()::get_p() != 12) $stop; + if (Cls#(4)::get_p() != 4) $stop; + if (Cls8_t::get_p() != 8) $stop; + if (c12.get_p() != 12) $stop; if (c4.get_p() != 4) $stop; - if (c5.get_p() != 5) $stop; + if (c8.get_p() != 8) $stop; if (w16.get_p() != 16) $stop; + // verilator lint_off WIDTH c12.member = 32'haaaaaaaa; c4.member = 32'haaaaaaaa; - c5.member = 32'haaaaaaaa; + c8.member = 32'haaaaaaaa; // verilator lint_on WIDTH if (c12.member != 12'haaa) $stop; if (c4.member != 4'ha) $stop; if (c12.get_member() != 12'haaa) $stop; if (c4.get_member() != 4'ha) $stop; - if ($sformatf("%p", c12) != "'{member:'haaa}") $stop; - if ($sformatf("%p", c4) != "'{member:'ha}") $stop; + `checks($sformatf("%p", c12), "'{member:'haaa}"); + `checks($sformatf("%p", c4), "'{member:'ha}"); $write("*-* All Finished *-*\n"); $finish;