Fix parameters referencing interface fields (#1593) (#5910)

This commit is contained in:
Ryszard Rozak 2025-04-02 15:43:12 +02:00 committed by GitHub
parent 6d1e82b908
commit 353a4b7b4a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 39 additions and 11 deletions

View File

@ -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; }

View File

@ -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);

View File

@ -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,

View File

@ -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 {

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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"}