Internals: Pass class parameters through link.
This commit is contained in:
parent
cf2810db8b
commit
1299b70945
|
|
@ -988,14 +988,16 @@ public:
|
||||||
|
|
||||||
class AstClassRefDType final : public AstNodeDType {
|
class AstClassRefDType final : public AstNodeDType {
|
||||||
// Reference to a class
|
// Reference to a class
|
||||||
|
// Children: PINs (for parameter settings)
|
||||||
private:
|
private:
|
||||||
AstClass* m_classp; // data type pointed to, BELOW the AstTypedef
|
AstClass* m_classp; // data type pointed to, BELOW the AstTypedef
|
||||||
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
|
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
|
||||||
public:
|
public:
|
||||||
AstClassRefDType(FileLine* fl, AstClass* classp)
|
AstClassRefDType(FileLine* fl, AstClass* classp, AstNode* paramsp)
|
||||||
: ASTGEN_SUPER(fl)
|
: ASTGEN_SUPER(fl)
|
||||||
, m_classp{classp} {
|
, m_classp{classp} {
|
||||||
dtypep(this);
|
dtypep(this);
|
||||||
|
addNOp4p(paramsp);
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(ClassRefDType)
|
ASTNODE_NODE_FUNCS(ClassRefDType)
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
@ -1032,6 +1034,7 @@ public:
|
||||||
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
||||||
AstClass* classp() const { return m_classp; }
|
AstClass* classp() const { return m_classp; }
|
||||||
void classp(AstClass* nodep) { m_classp = nodep; }
|
void classp(AstClass* nodep) { m_classp = nodep; }
|
||||||
|
AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstIfaceRefDType final : public AstNodeDType {
|
class AstIfaceRefDType final : public AstNodeDType {
|
||||||
|
|
|
||||||
|
|
@ -457,6 +457,13 @@ private:
|
||||||
UINFO(4, " Link Cell done: " << nodep << endl);
|
UINFO(4, " Link Cell done: " << nodep << endl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstRefDType* nodep) override {
|
||||||
|
for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) {
|
||||||
|
pinp->param(true);
|
||||||
|
if (pinp->name() == "") pinp->name("__paramNumber" + cvtToStr(pinp->pinNum()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Accelerate the recursion
|
// Accelerate the recursion
|
||||||
// Must do statements to support Generates, math though...
|
// Must do statements to support Generates, math though...
|
||||||
virtual void visit(AstNodeMath*) override {}
|
virtual void visit(AstNodeMath*) override {}
|
||||||
|
|
|
||||||
|
|
@ -1941,11 +1941,13 @@ private:
|
||||||
virtual void visit(AstCell* nodep) override {
|
virtual void visit(AstCell* nodep) override {
|
||||||
// Cell: Recurse inside or cleanup not founds
|
// Cell: Recurse inside or cleanup not founds
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
m_cellp = nodep;
|
|
||||||
AstNode::user5ClearTree();
|
AstNode::user5ClearTree();
|
||||||
UASSERT_OBJ(nodep->modp(), nodep,
|
UASSERT_OBJ(nodep->modp(), nodep,
|
||||||
"Cell has unlinked module"); // V3LinkCell should have errored out
|
"Cell has unlinked module"); // V3LinkCell should have errored out
|
||||||
|
VL_RESTORER(m_cellp);
|
||||||
|
VL_RESTORER(m_pinSymp);
|
||||||
{
|
{
|
||||||
|
m_cellp = nodep;
|
||||||
if (VN_IS(nodep->modp(), NotFoundModule)) {
|
if (VN_IS(nodep->modp(), NotFoundModule)) {
|
||||||
// Prevent warnings about missing pin connects
|
// Prevent warnings about missing pin connects
|
||||||
if (nodep->pinsp()) nodep->pinsp()->unlinkFrBackWithNext()->deleteTree();
|
if (nodep->pinsp()) nodep->pinsp()->unlinkFrBackWithNext()->deleteTree();
|
||||||
|
|
@ -1960,13 +1962,26 @@ private:
|
||||||
// if (debug()) nodep->dumpTree(cout, "linkcell:");
|
// if (debug()) nodep->dumpTree(cout, "linkcell:");
|
||||||
// if (debug()) nodep->modp()->dumpTree(cout, "linkcemd:");
|
// if (debug()) nodep->modp()->dumpTree(cout, "linkcemd:");
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
m_pinSymp = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_cellp = nullptr;
|
|
||||||
// Parent module inherits child's publicity
|
// Parent module inherits child's publicity
|
||||||
// This is done bottom up in the LinkBotupVisitor stage
|
// This is done bottom up in the LinkBotupVisitor stage
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstClassRefDType* nodep) override {
|
||||||
|
// Cell: Recurse inside or cleanup not founds
|
||||||
|
checkNoDot(nodep);
|
||||||
|
AstNode::user5ClearTree();
|
||||||
|
UASSERT_OBJ(nodep->classp(), nodep, "ClassRef has unlinked class");
|
||||||
|
VL_RESTORER(m_pinSymp);
|
||||||
|
{
|
||||||
|
// ClassRef's have pins, so track
|
||||||
|
m_pinSymp = m_statep->getNodeSym(nodep->classp());
|
||||||
|
UINFO(4, "(Backto) Link ClassRefDType: " << nodep << endl);
|
||||||
|
// if (debug()) nodep->dumpTree(cout, "linkcell:");
|
||||||
|
// if (debug()) nodep->modp()->dumpTree(cout, "linkcemd:");
|
||||||
|
iterateChildren(nodep);
|
||||||
|
}
|
||||||
|
}
|
||||||
virtual void visit(AstPin* nodep) override {
|
virtual void visit(AstPin* nodep) override {
|
||||||
// Pin: Link to submodule's port
|
// Pin: Link to submodule's port
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
|
|
@ -1976,7 +1991,8 @@ private:
|
||||||
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
|
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
|
||||||
const char* whatp = nodep->param() ? "parameter pin" : "pin";
|
const char* whatp = nodep->param() ? "parameter pin" : "pin";
|
||||||
if (!foundp) {
|
if (!foundp) {
|
||||||
if (nodep->name() == "__paramNumber1" && VN_IS(m_cellp->modp(), Primitive)) {
|
if (nodep->name() == "__paramNumber1" && m_cellp
|
||||||
|
&& VN_IS(m_cellp->modp(), Primitive)) {
|
||||||
// Primitive parameter is really a delay we can just ignore
|
// Primitive parameter is really a delay we can just ignore
|
||||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||||
return;
|
return;
|
||||||
|
|
@ -2540,7 +2556,7 @@ private:
|
||||||
"Unsupported: " << AstNode::prettyNameQ(cpackagerefp->name()));
|
"Unsupported: " << AstNode::prettyNameQ(cpackagerefp->name()));
|
||||||
}
|
}
|
||||||
if (cpackagerefp->paramsp()) {
|
if (cpackagerefp->paramsp()) {
|
||||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages");
|
nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages for task calls");
|
||||||
}
|
}
|
||||||
UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link");
|
UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link");
|
||||||
nodep->classOrPackagep(cpackagerefp->classOrPackagep());
|
nodep->classOrPackagep(cpackagerefp->classOrPackagep());
|
||||||
|
|
@ -2817,8 +2833,10 @@ private:
|
||||||
cextp->v3error("Attempting to extend class "
|
cextp->v3error("Attempting to extend class "
|
||||||
<< nodep->prettyNameQ() << " from itself");
|
<< nodep->prettyNameQ() << " from itself");
|
||||||
} else {
|
} else {
|
||||||
AstClassRefDType* newp
|
AstNode* paramsp = cpackagerefp->paramsp();
|
||||||
= new AstClassRefDType{nodep->fileline(), classp};
|
if (paramsp) paramsp = paramsp->cloneTree(true);
|
||||||
|
const auto newp
|
||||||
|
= new AstClassRefDType{nodep->fileline(), classp, paramsp};
|
||||||
cextp->childDTypep(newp);
|
cextp->childDTypep(newp);
|
||||||
classp->isExtended(true);
|
classp->isExtended(true);
|
||||||
nodep->isExtended(true);
|
nodep->isExtended(true);
|
||||||
|
|
@ -2909,7 +2927,9 @@ private:
|
||||||
nodep->refDTypep(defp);
|
nodep->refDTypep(defp);
|
||||||
nodep->classOrPackagep(foundp->classOrPackagep());
|
nodep->classOrPackagep(foundp->classOrPackagep());
|
||||||
} else if (AstClass* defp = foundp ? VN_CAST(foundp->nodep(), Class) : nullptr) {
|
} else if (AstClass* defp = foundp ? VN_CAST(foundp->nodep(), Class) : nullptr) {
|
||||||
AstClassRefDType* newp = new AstClassRefDType(nodep->fileline(), defp);
|
AstNode* paramsp = nodep->paramsp();
|
||||||
|
if (paramsp) paramsp->unlinkFrBackWithNext();
|
||||||
|
AstClassRefDType* newp = new AstClassRefDType{nodep->fileline(), defp, paramsp};
|
||||||
newp->classOrPackagep(foundp->classOrPackagep());
|
newp->classOrPackagep(foundp->classOrPackagep());
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
%Error-UNSUPPORTED: t/t_class_param_bad.v:12:4: Unsupported: parameterized packages
|
||||||
|
12 | Cls #(.PARAMBAD(1)) c;
|
||||||
|
| ^~~
|
||||||
|
%Error: t/t_class_param_bad.v:12:11: Parameter pin not found: 'PARAMBAD'
|
||||||
|
: ... Suggested alternative: 'PARAMB'
|
||||||
|
12 | Cls #(.PARAMBAD(1)) c;
|
||||||
|
| ^~~~~~~~
|
||||||
|
%Error-UNSUPPORTED: t/t_class_param_bad.v:13:4: Unsupported: parameterized packages
|
||||||
|
13 | Cls #(13, 1) cd;
|
||||||
|
| ^~~
|
||||||
|
%Error: t/t_class_param_bad.v:13:14: Parameter pin not found: '__paramNumber2'
|
||||||
|
13 | Cls #(13, 1) cd;
|
||||||
|
| ^
|
||||||
|
%Error-UNSUPPORTED: t/t_class_param_bad.v:7:23: Unsupported: class parameter
|
||||||
|
7 | class Cls #(parameter PARAMB = 12);
|
||||||
|
| ^~~~~~
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2020 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
scenarios(linter => 1);
|
||||||
|
|
||||||
|
lint(
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
class Cls #(parameter PARAMB = 12);
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
Cls #(.PARAMBAD(1)) c; // Bad param name
|
||||||
|
Cls #(13, 1) cd; // Bad param number
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
%Error-UNSUPPORTED: t/t_class_vparam.v:13:40: Unsupported: parameterized packages
|
%Error-UNSUPPORTED: t/t_class_vparam.v:13:40: Unsupported: parameterized packages
|
||||||
13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v);
|
13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v);
|
||||||
| ^~~~~~~~~~~~~~~
|
| ^~~~~~~~~~~~~~~
|
||||||
|
%Error: t/t_class_vparam.v:13:58: Parameter pin not found: '__paramNumber1'
|
||||||
|
13 | pure virtual function void funcname(paramed_class_t #(CTYPE_t) v);
|
||||||
|
| ^~~~~~~
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue