diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 25b99a86c..2d4299c4b 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -5742,6 +5742,7 @@ class AstVarXRef final : public AstNodeVarRef { string m_name; string m_dotted; // Dotted part of scope the name()'ed reference is under or "" string m_inlinedDots; // Dotted hierarchy flattened out + bool m_containsGenBlock = false; // Contains gen block reference public: AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access) : ASTGEN_SUPER_VarXRef(fl, nullptr, access) @@ -5757,6 +5758,8 @@ public: void dotted(const string& dotted) { m_dotted = dotted; } string inlinedDots() const { return m_inlinedDots; } void inlinedDots(const string& flag) { m_inlinedDots = flag; } + bool containsGenBlock() const { return m_containsGenBlock; } + void containsGenBlock(const bool flag) { m_containsGenBlock = flag; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 16f50636d..2ccf9fbe6 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2509,6 +2509,7 @@ AstNodeVarRef* AstNodeVarRef::varRefLValueRecurse(AstNode* nodep) { void AstVarXRef::dump(std::ostream& str) const { this->AstNodeVarRef::dump(str); + if (containsGenBlock()) str << " [GENBLK]"; str << ".=" << dotted() << " "; if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - "; if (varScopep()) { @@ -2520,6 +2521,7 @@ void AstVarXRef::dump(std::ostream& str) const { } } void AstVarXRef::dumpJson(std::ostream& str) const { + dumpJsonBoolFunc(str, containsGenBlock); dumpJsonStrFunc(str, dotted); dumpJsonStrFunc(str, inlinedDots); dumpJsonGen(str); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index acd2fa9b2..6383f0e72 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2266,6 +2266,7 @@ class LinkDotResolveVisitor final : public VNVisitor { bool m_super; // Starts with super reference bool m_unresolvedCell; // Unresolved cell, needs help from V3Param bool m_unresolvedClass; // Unresolved class reference, needs help from V3Param + bool m_genBlk; // Contains gen block reference AstNode* m_unlinkedScopep; // Unresolved scope, needs corresponding VarXRef bool m_dotErr; // Error found in dotted resolution, ignore upwards string m_dotText; // String of dotted names found in below parseref @@ -2280,6 +2281,7 @@ class LinkDotResolveVisitor final : public VNVisitor { m_dotText = ""; m_unresolvedCell = false; m_unresolvedClass = false; + m_genBlk = false; m_unlinkedScopep = nullptr; } string ascii() const { @@ -2295,6 +2297,7 @@ class LinkDotResolveVisitor final : public VNVisitor { if (m_super) sstr << " [super]"; if (m_unresolvedCell) sstr << " [unrCell]"; if (m_unresolvedClass) sstr << " [unrClass]"; + if (m_genBlk) sstr << " [genBlk]"; sstr << " txt=" << m_dotText; return sstr.str(); } @@ -3075,6 +3078,9 @@ class LinkDotResolveVisitor final : public VNVisitor { m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name()); m_ds.m_dotSymp = foundp; m_ds.m_dotPos = DP_SCOPE; + if (const AstBegin* const beginp = VN_CAST(foundp->nodep(), Begin)) { + if (beginp->generate()) m_ds.m_genBlk = true; + } // Upper AstDot visitor will handle it from here } else if (VN_IS(foundp->nodep(), Cell) && allowVar) { AstCell* const cellp = VN_AS(foundp->nodep(), Cell); @@ -3135,6 +3141,7 @@ class LinkDotResolveVisitor final : public VNVisitor { = new AstVarXRef{nodep->fileline(), nodep->name(), m_ds.m_dotText, VAccess::READ}; // lvalue'ness computed later refp->varp(varp); + refp->containsGenBlock(m_ds.m_genBlk); if (varp->attrSplitVar()) { refp->v3warn( SPLITVAR, diff --git a/src/V3Param.cpp b/src/V3Param.cpp index e5cf86c39..09092af24 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -1292,7 +1292,10 @@ class ParamVisitor final : public VNVisitor { } } } - nodep->varp(nullptr); // Needs relink, as may remove pointed-to var + if (nodep->containsGenBlock()) { + // Needs relink, as may remove pointed-to var + nodep->varp(nullptr); + } } void visit(AstDot* nodep) override { diff --git a/test_regress/t/t_interface_param_acc_bits.py b/test_regress/t/t_interface_param_acc_bits.py index ac60e9122..d4f986441 100755 --- a/test_regress/t/t_interface_param_acc_bits.py +++ b/test_regress/t/t_interface_param_acc_bits.py @@ -11,8 +11,8 @@ import vltest_bootstrap test.scenarios('simulator') -test.compile( - fails=test.vlt_all, # Unsupported bug1523 - expect_filename=test.golden_filename) +test.compile() + +test.execute() test.passes() diff --git a/test_regress/t/t_interface_param_acc_bits.v b/test_regress/t/t_interface_param_acc_bits.v index b89767876..014359636 100644 --- a/test_regress/t/t_interface_param_acc_bits.v +++ b/test_regress/t/t_interface_param_acc_bits.v @@ -4,17 +4,26 @@ // without warranty, 2017 by Johan Bjork. // SPDX-License-Identifier: CC0-1.0 -// bug1593 - interface simple_bus #(PARAMETER = 0); + typedef struct packed { + logic [31:0] data; + logic [3:0] mask; + } payload_t; + parameter [6:0] dummy = 22; + payload_t payload; + logic [1:0] x; endinterface module t (); simple_bus sb_intf(); + localparam LP = $bits(sb_intf.payload.data); simple_bus #(.PARAMETER($bits(sb_intf.dummy))) simple(); + simple_bus #(.PARAMETER($bits(sb_intf.x))) simple2(); initial begin + if (LP != 32) $stop; if (simple.PARAMETER != 7) $stop; + if (simple2.PARAMETER != 2) $stop; $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_interface_param_another_bad.out b/test_regress/t/t_interface_param_another_bad.out index f63612458..70ac4c7d2 100644 --- a/test_regress/t/t_interface_param_another_bad.out +++ b/test_regress/t/t_interface_param_another_bad.out @@ -1,5 +1,9 @@ -%Error: t/t_interface_param_another_bad.v:9:42: Parameter-resolved constants must not use dotted references: 'dummy' +%Error: t/t_interface_param_another_bad.v:9:36: Expecting expression to be constant, but variable isn't const: 'dummy' : ... note: In instance 't' - 9 | simple_bus #(.PARAMETER($bits(sb_intf.dummy))) simple(); - | ^~~~~ + 9 | simple_bus #(.PARAMETER(sb_intf.dummy)) simple(); + | ^~~~~ +%Error: t/t_interface_param_another_bad.v:9:18: Can't convert defparam value to constant: Param 'PARAMETER' of 'simple' + : ... note: In instance 't' + 9 | simple_bus #(.PARAMETER(sb_intf.dummy)) simple(); + | ^~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_interface_param_another_bad.v b/test_regress/t/t_interface_param_another_bad.v index b5278fbc2..15dea9764 100644 --- a/test_regress/t/t_interface_param_another_bad.v +++ b/test_regress/t/t_interface_param_another_bad.v @@ -6,7 +6,7 @@ module t (); simple_bus sb_intf(); - simple_bus #(.PARAMETER($bits(sb_intf.dummy))) simple(); + simple_bus #(.PARAMETER(sb_intf.dummy)) simple(); initial begin $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_json_only_tag.out b/test_regress/t/t_json_only_tag.out index cb8fbdc5d..0c74a6e71 100644 --- a/test_regress/t/t_json_only_tag.out +++ b/test_regress/t/t_json_only_tag.out @@ -12,7 +12,7 @@ {"type":"VAR","name":"dotted","addr":"(R)","loc":"d,33:16,33:22","dtypep":"(S)","origName":"dotted","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"WIRE","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"ignorePostWrite":false,"ignoreSchedWrite":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"ASSIGNW","name":"","addr":"(T)","loc":"d,33:23,33:24","dtypep":"(S)", "rhsp": [ - {"type":"VARXREF","name":"value","addr":"(U)","loc":"d,33:30,33:35","dtypep":"(V)","dotted":"itop","inlinedDots":"","access":"RD","varp":"(W)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARXREF","name":"value","addr":"(U)","loc":"d,33:30,33:35","dtypep":"(V)","containsGenBlock":false,"dotted":"itop","inlinedDots":"","access":"RD","varp":"(W)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ], "lhsp": [ {"type":"VARREF","name":"dotted","addr":"(X)","loc":"d,33:16,33:22","dtypep":"(S)","access":"WR","varp":"(R)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"}