From bf4a844f2b8ac0d76016f6b70725a861805aae16 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Fri, 30 Dec 2022 12:05:01 +0100 Subject: [PATCH] Fix self references when param class instantiated (#3833) --- src/V3Param.cpp | 15 +++++++++++++++ test_regress/t/t_class_param.v | 22 ++++++++++++++++++++++ test_regress/t/t_class_param_mod.v | 22 ++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/V3Param.cpp b/src/V3Param.cpp index b433dc768..f79ed9bef 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -542,12 +542,27 @@ class ParamProcessor final { hash.insert(V3Os::trueRandom(64)); } } + void replaceRefsRecurse(AstNode* const nodep, const AstClass* const oldClassp, + AstClass* const newClassp) { + if (AstClassRefDType* const classRefp = VN_CAST(nodep, ClassRefDType)) { + if (classRefp->classp() == oldClassp) classRefp->classp(newClassp); + } + if (nodep->op1p()) replaceRefsRecurse(nodep->op1p(), oldClassp, newClassp); + if (nodep->op2p()) replaceRefsRecurse(nodep->op2p(), oldClassp, newClassp); + if (nodep->op3p()) replaceRefsRecurse(nodep->op3p(), oldClassp, newClassp); + if (nodep->op4p()) replaceRefsRecurse(nodep->op4p(), oldClassp, newClassp); + if (nodep->nextp()) replaceRefsRecurse(nodep->nextp(), oldClassp, newClassp); + } void deepCloneModule(AstNodeModule* srcModp, AstNode* cellp, AstPin* paramsp, const string& newname, const IfaceRefRefs& ifaceRefRefs) { // Deep clone of new module // Note all module internal variables will be re-linked to the new modules by clone // However links outside the module (like on the upper cells) will not. AstNodeModule* const newmodp = srcModp->cloneTree(false); + if (VN_IS(srcModp, Class)) { + replaceRefsRecurse(newmodp->stmtsp(), VN_AS(newmodp, Class), VN_AS(srcModp, Class)); + } + newmodp->name(newname); newmodp->user5(false); // We need to re-recurse this module once changed newmodp->recursive(false); diff --git a/test_regress/t/t_class_param.v b/test_regress/t/t_class_param.v index 99740abb7..5dfa4ee20 100644 --- a/test_regress/t/t_class_param.v +++ b/test_regress/t/t_class_param.v @@ -45,6 +45,15 @@ endclass typedef Cls#(8) Cls8_t; +class SelfRefClassTypeParam #(type T=logic); + typedef SelfRefClassTypeParam #(int) self_int_t; + T field; +endclass + +class SelfRefClassIntParam #(int P=1); + typedef SelfRefClassIntParam #(10) self_int_t; +endclass + module t (/*AUTOARG*/); Cls c12; @@ -52,12 +61,20 @@ module t (/*AUTOARG*/); Cls8_t c8; Wrap #(.P(16)) w16; Wrap2 #(.P(32)) w32; + SelfRefClassTypeParam src_logic; + SelfRefClassTypeParam::self_int_t src_int; + SelfRefClassIntParam src1; + SelfRefClassIntParam::self_int_t src10; initial begin c12 = new; c4 = new; c8 = new; w16 = new; w32 = new; + src_int = new; + src_logic = new; + src1 = new; + src10 = new; if (Cls#()::PBASE != 12) $stop; if (Cls#(4)::PBASE != 4) $stop; if (Cls8_t::PBASE != 8) $stop; @@ -92,6 +109,11 @@ module t (/*AUTOARG*/); `checks($sformatf("%p", c12), "'{member:'haaa}"); `checks($sformatf("%p", c4), "'{member:'ha}"); + if ($bits(src_logic.field) != 1) $stop; + if ($bits(src_int.field) != 32) $stop; + if (src1.P != 1) $stop; + if (src10.P != 10) $stop; + $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_class_param_mod.v b/test_regress/t/t_class_param_mod.v index a57ba7316..e117fa2ec 100644 --- a/test_regress/t/t_class_param_mod.v +++ b/test_regress/t/t_class_param_mod.v @@ -45,17 +45,34 @@ endclass typedef Cls#(8) Cls8_t; +class SelfRefClassTypeParam #(type T=logic); + typedef SelfRefClassTypeParam #(int) self_int_t; + T field; +endclass + +class SelfRefClassIntParam #(int P=1); + typedef SelfRefClassIntParam #(10) self_int_t; +endclass + Cls c12; Cls #(.PBASE(4)) c4; Cls8_t c8; Wrap #(.P(16)) w16; Wrap2 #(.P(32)) w32; + SelfRefClassTypeParam src_logic; + SelfRefClassTypeParam::self_int_t src_int; + SelfRefClassIntParam src1; + SelfRefClassIntParam::self_int_t src10; initial begin c12 = new; c4 = new; c8 = new; w16 = new; w32 = new; + src_int = new; + src_logic = new; + src1 = new; + src10 = new; if (Cls#()::PBASE != 12) $stop; if (Cls#(4)::PBASE != 4) $stop; if (Cls8_t::PBASE != 8) $stop; @@ -90,6 +107,11 @@ endclass `checks($sformatf("%p", c12), "'{member:'haaa}"); `checks($sformatf("%p", c4), "'{member:'ha}"); + if ($bits(src_logic.field) != 1) $stop; + if ($bits(src_int.field) != 32) $stop; + if (src1.P != 1) $stop; + if (src10.P != 10) $stop; + $write("*-* All Finished *-*\n"); $finish; end