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 {
|
||||
// Reference to a class
|
||||
// Children: PINs (for parameter settings)
|
||||
private:
|
||||
AstClass* m_classp; // data type pointed to, BELOW the AstTypedef
|
||||
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
|
||||
public:
|
||||
AstClassRefDType(FileLine* fl, AstClass* classp)
|
||||
AstClassRefDType(FileLine* fl, AstClass* classp, AstNode* paramsp)
|
||||
: ASTGEN_SUPER(fl)
|
||||
, m_classp{classp} {
|
||||
dtypep(this);
|
||||
addNOp4p(paramsp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ClassRefDType)
|
||||
// METHODS
|
||||
|
|
@ -1032,6 +1034,7 @@ public:
|
|||
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
||||
AstClass* classp() const { return m_classp; }
|
||||
void classp(AstClass* nodep) { m_classp = nodep; }
|
||||
AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
|
||||
};
|
||||
|
||||
class AstIfaceRefDType final : public AstNodeDType {
|
||||
|
|
|
|||
|
|
@ -457,6 +457,13 @@ private:
|
|||
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
|
||||
// Must do statements to support Generates, math though...
|
||||
virtual void visit(AstNodeMath*) override {}
|
||||
|
|
|
|||
|
|
@ -1941,11 +1941,13 @@ private:
|
|||
virtual void visit(AstCell* nodep) override {
|
||||
// Cell: Recurse inside or cleanup not founds
|
||||
checkNoDot(nodep);
|
||||
m_cellp = nodep;
|
||||
AstNode::user5ClearTree();
|
||||
UASSERT_OBJ(nodep->modp(), nodep,
|
||||
"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)) {
|
||||
// Prevent warnings about missing pin connects
|
||||
if (nodep->pinsp()) nodep->pinsp()->unlinkFrBackWithNext()->deleteTree();
|
||||
|
|
@ -1960,13 +1962,26 @@ private:
|
|||
// if (debug()) nodep->dumpTree(cout, "linkcell:");
|
||||
// if (debug()) nodep->modp()->dumpTree(cout, "linkcemd:");
|
||||
iterateChildren(nodep);
|
||||
m_pinSymp = nullptr;
|
||||
}
|
||||
}
|
||||
m_cellp = nullptr;
|
||||
// Parent module inherits child's publicity
|
||||
// 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 {
|
||||
// Pin: Link to submodule's port
|
||||
checkNoDot(nodep);
|
||||
|
|
@ -1976,7 +1991,8 @@ private:
|
|||
VSymEnt* foundp = m_pinSymp->findIdFlat(nodep->name());
|
||||
const char* whatp = nodep->param() ? "parameter pin" : "pin";
|
||||
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
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
|
|
@ -2540,7 +2556,7 @@ private:
|
|||
"Unsupported: " << AstNode::prettyNameQ(cpackagerefp->name()));
|
||||
}
|
||||
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");
|
||||
nodep->classOrPackagep(cpackagerefp->classOrPackagep());
|
||||
|
|
@ -2817,8 +2833,10 @@ private:
|
|||
cextp->v3error("Attempting to extend class "
|
||||
<< nodep->prettyNameQ() << " from itself");
|
||||
} else {
|
||||
AstClassRefDType* newp
|
||||
= new AstClassRefDType{nodep->fileline(), classp};
|
||||
AstNode* paramsp = cpackagerefp->paramsp();
|
||||
if (paramsp) paramsp = paramsp->cloneTree(true);
|
||||
const auto newp
|
||||
= new AstClassRefDType{nodep->fileline(), classp, paramsp};
|
||||
cextp->childDTypep(newp);
|
||||
classp->isExtended(true);
|
||||
nodep->isExtended(true);
|
||||
|
|
@ -2909,7 +2927,9 @@ private:
|
|||
nodep->refDTypep(defp);
|
||||
nodep->classOrPackagep(foundp->classOrPackagep());
|
||||
} 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());
|
||||
nodep->replaceWith(newp);
|
||||
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
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue