Change package import/export to link post-parsing, prep for later commit.
This commit is contained in:
parent
5c923d6629
commit
d0ec6092b3
|
|
@ -1339,19 +1339,32 @@ class AstPackageExport final : public AstNode {
|
||||||
// A package export declaration
|
// A package export declaration
|
||||||
//
|
//
|
||||||
// @astgen ptr := m_packagep : Optional[AstPackage] // Package hierarchy
|
// @astgen ptr := m_packagep : Optional[AstPackage] // Package hierarchy
|
||||||
string m_name;
|
string m_name; // What imported e.g. "*"
|
||||||
|
string m_pkgName; // Module the cell instances
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name)
|
AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name)
|
||||||
: ASTGEN_SUPER_PackageExport(fl)
|
: ASTGEN_SUPER_PackageExport(fl)
|
||||||
, m_name{name}
|
, m_name{name}
|
||||||
, m_packagep{packagep} {}
|
, m_packagep{packagep} {
|
||||||
|
pkgNameFrom();
|
||||||
|
}
|
||||||
|
AstPackageExport(FileLine* fl, const string& pkgName, const string& name)
|
||||||
|
: ASTGEN_SUPER_PackageExport(fl)
|
||||||
|
, m_name{name}
|
||||||
|
, m_pkgName{pkgName}
|
||||||
|
, m_packagep{nullptr} {}
|
||||||
ASTGEN_MEMBERS_AstPackageExport;
|
ASTGEN_MEMBERS_AstPackageExport;
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
void dumpJson(std::ostream& str) const override;
|
void dumpJson(std::ostream& str) const override;
|
||||||
string name() const override VL_MT_STABLE { return m_name; }
|
string name() const override VL_MT_STABLE { return m_name; }
|
||||||
|
string pkgName() const VL_MT_STABLE { return m_pkgName; }
|
||||||
|
string prettyPkgNameQ() const { return "'" + prettyName(pkgName()) + "'"; }
|
||||||
AstPackage* packagep() const { return m_packagep; }
|
AstPackage* packagep() const { return m_packagep; }
|
||||||
void packagep(AstPackage* nodep) { m_packagep = nodep; }
|
void packagep(AstPackage* nodep) { m_packagep = nodep; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void pkgNameFrom();
|
||||||
};
|
};
|
||||||
class AstPackageExportStarStar final : public AstNode {
|
class AstPackageExportStarStar final : public AstNode {
|
||||||
// A package export *::* declaration
|
// A package export *::* declaration
|
||||||
|
|
@ -1365,19 +1378,32 @@ class AstPackageImport final : public AstNode {
|
||||||
// A package import declaration
|
// A package import declaration
|
||||||
//
|
//
|
||||||
// @astgen ptr := m_packagep : Optional[AstPackage] // Package hierarchy
|
// @astgen ptr := m_packagep : Optional[AstPackage] // Package hierarchy
|
||||||
string m_name;
|
string m_name; // What imported e.g. "*"
|
||||||
|
string m_pkgName; // Module the cell instances
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name)
|
AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name)
|
||||||
: ASTGEN_SUPER_PackageImport(fl)
|
: ASTGEN_SUPER_PackageImport(fl)
|
||||||
, m_name{name}
|
, m_name{name}
|
||||||
, m_packagep{packagep} {}
|
, m_packagep{packagep} {
|
||||||
|
pkgNameFrom();
|
||||||
|
}
|
||||||
|
AstPackageImport(FileLine* fl, const string& pkgName, const string& name)
|
||||||
|
: ASTGEN_SUPER_PackageImport(fl)
|
||||||
|
, m_name{name}
|
||||||
|
, m_pkgName{pkgName}
|
||||||
|
, m_packagep{nullptr} {}
|
||||||
ASTGEN_MEMBERS_AstPackageImport;
|
ASTGEN_MEMBERS_AstPackageImport;
|
||||||
void dump(std::ostream& str) const override;
|
void dump(std::ostream& str) const override;
|
||||||
void dumpJson(std::ostream& str) const override;
|
void dumpJson(std::ostream& str) const override;
|
||||||
string name() const override VL_MT_STABLE { return m_name; }
|
string name() const override VL_MT_STABLE { return m_name; }
|
||||||
|
string pkgName() const VL_MT_STABLE { return m_pkgName; }
|
||||||
|
string prettyPkgNameQ() const { return "'" + prettyName(pkgName()) + "'"; }
|
||||||
AstPackage* packagep() const { return m_packagep; }
|
AstPackage* packagep() const { return m_packagep; }
|
||||||
void packagep(AstPackage* nodep) { m_packagep = nodep; }
|
void packagep(AstPackage* nodep) { m_packagep = nodep; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void pkgNameFrom();
|
||||||
};
|
};
|
||||||
class AstPin final : public AstNode {
|
class AstPin final : public AstNode {
|
||||||
// A port or parameter assignment on an instantiation
|
// A port or parameter assignment on an instantiation
|
||||||
|
|
|
||||||
|
|
@ -2196,14 +2196,28 @@ void AstNodeModule::dumpJson(std::ostream& str) const {
|
||||||
}
|
}
|
||||||
void AstPackageExport::dump(std::ostream& str) const {
|
void AstPackageExport::dump(std::ostream& str) const {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
|
if (packagep()) {
|
||||||
str << " -> " << packagep();
|
str << " -> " << packagep();
|
||||||
|
} else {
|
||||||
|
str << " ->UNLINKED:" << pkgName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void AstPackageExport::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
void AstPackageExport::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
||||||
|
void AstPackageExport::pkgNameFrom() {
|
||||||
|
if (packagep()) m_pkgName = packagep()->name();
|
||||||
|
}
|
||||||
void AstPackageImport::dump(std::ostream& str) const {
|
void AstPackageImport::dump(std::ostream& str) const {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
|
if (packagep()) {
|
||||||
str << " -> " << packagep();
|
str << " -> " << packagep();
|
||||||
|
} else {
|
||||||
|
str << " ->UNLINKED:" << pkgName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void AstPackageImport::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
void AstPackageImport::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
||||||
|
void AstPackageImport::pkgNameFrom() {
|
||||||
|
if (packagep()) m_pkgName = packagep()->name();
|
||||||
|
}
|
||||||
void AstPatMember::dump(std::ostream& str) const {
|
void AstPatMember::dump(std::ostream& str) const {
|
||||||
this->AstNodeExpr::dump(str);
|
this->AstNodeExpr::dump(str);
|
||||||
if (isDefault()) str << " [DEFAULT]";
|
if (isDefault()) str << " [DEFAULT]";
|
||||||
|
|
|
||||||
|
|
@ -247,10 +247,30 @@ class LinkCellsVisitor final : public VNVisitor {
|
||||||
// Note cannot do modport resolution here; modports are allowed underneath generates
|
// Note cannot do modport resolution here; modports are allowed underneath generates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visit(AstPackageExport* nodep) override {
|
||||||
|
// Package Import: We need to do the package before the use of a package
|
||||||
|
iterateChildren(nodep);
|
||||||
|
if (!nodep->packagep()) {
|
||||||
|
AstNodeModule* const modp = resolveModule(nodep, nodep->pkgName());
|
||||||
|
if (AstPackage* const pkgp = VN_CAST(modp, Package)) nodep->packagep(pkgp);
|
||||||
|
if (!nodep->packagep()) {
|
||||||
|
nodep->v3error("Export package not found: " << nodep->prettyPkgNameQ());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
void visit(AstPackageImport* nodep) override {
|
void visit(AstPackageImport* nodep) override {
|
||||||
// Package Import: We need to do the package before the use of a package
|
// Package Import: We need to do the package before the use of a package
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
UASSERT_OBJ(nodep->packagep(), nodep, "Unlinked package"); // Parser should set packagep
|
if (!nodep->packagep()) {
|
||||||
|
AstNodeModule* const modp = resolveModule(nodep, nodep->pkgName());
|
||||||
|
if (AstPackage* const pkgp = VN_CAST(modp, Package)) nodep->packagep(pkgp);
|
||||||
|
// If not found, V3LinkDot will report errors
|
||||||
|
if (!nodep->packagep()) {
|
||||||
|
nodep->v3error("Import package not found: " << nodep->prettyPkgNameQ());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
new V3GraphEdge{&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false};
|
new V3GraphEdge{&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1496,6 +1496,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
void visit(AstPackageImport* nodep) override {
|
void visit(AstPackageImport* nodep) override {
|
||||||
UINFO(4, " Link: " << nodep << endl);
|
UINFO(4, " Link: " << nodep << endl);
|
||||||
|
if (!nodep->packagep()) return; // Errored in V3LinkCells
|
||||||
VSymEnt* const srcp = m_statep->getNodeSym(nodep->packagep());
|
VSymEnt* const srcp = m_statep->getNodeSym(nodep->packagep());
|
||||||
if (nodep->name() == "*") {
|
if (nodep->name() == "*") {
|
||||||
if (nodep->packagep() != v3Global.rootp()->stdPackagep()) {
|
if (nodep->packagep() != v3Global.rootp()->stdPackagep()) {
|
||||||
|
|
@ -1506,10 +1507,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VSymEnt* const impp = srcp->findIdFlat(nodep->name());
|
VSymEnt* const impp = srcp->findIdFlat(nodep->name());
|
||||||
if (!impp) {
|
if (!impp) { nodep->v3error("Import object not found: " << nodep->prettyPkgNameQ()); }
|
||||||
nodep->v3error("Import object not found: '" << nodep->packagep()->prettyName()
|
|
||||||
<< "::" << nodep->prettyName() << "'");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_curSymp->importFromPackage(m_statep->symsp(), srcp, nodep->name());
|
m_curSymp->importFromPackage(m_statep->symsp(), srcp, nodep->name());
|
||||||
UINFO(9, " Link Done: " << nodep << endl);
|
UINFO(9, " Link Done: " << nodep << endl);
|
||||||
|
|
@ -1517,6 +1515,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
void visit(AstPackageExport* nodep) override {
|
void visit(AstPackageExport* nodep) override {
|
||||||
UINFO(9, " Link: " << nodep << endl);
|
UINFO(9, " Link: " << nodep << endl);
|
||||||
|
if (!nodep->packagep()) return; // Errored in V3LinkCells
|
||||||
VSymEnt* const srcp = m_statep->getNodeSym(nodep->packagep());
|
VSymEnt* const srcp = m_statep->getNodeSym(nodep->packagep());
|
||||||
if (nodep->name() != "*") {
|
if (nodep->name() != "*") {
|
||||||
VSymEnt* const impp = srcp->findIdFlat(nodep->name());
|
VSymEnt* const impp = srcp->findIdFlat(nodep->name());
|
||||||
|
|
|
||||||
|
|
@ -1325,7 +1325,7 @@ package_import_item<nodep>: // ==IEEE: package_import_item
|
||||||
$$ = nullptr;
|
$$ = nullptr;
|
||||||
$<fl>1->v3error("Importing from missing package '" << *$<strp>1 << "'");
|
$<fl>1->v3error("Importing from missing package '" << *$<strp>1 << "'");
|
||||||
} else {
|
} else {
|
||||||
$$ = new AstPackageImport{$<fl>2, VN_CAST($<scp>1, Package), *$3};
|
$$ = new AstPackageImport{$<fl>2, *$<strp>1, *$3};
|
||||||
SYMP->importItem($<scp>1, *$3);
|
SYMP->importItem($<scp>1, *$3);
|
||||||
} }
|
} }
|
||||||
;
|
;
|
||||||
|
|
@ -1348,7 +1348,7 @@ package_export_itemList<nodep>:
|
||||||
|
|
||||||
package_export_item<nodep>: // ==IEEE: package_export_item
|
package_export_item<nodep>: // ==IEEE: package_export_item
|
||||||
idCC yP_COLONCOLON package_import_itemObj
|
idCC yP_COLONCOLON package_import_itemObj
|
||||||
{ $$ = new AstPackageExport{$<fl>3, VN_CAST($<scp>1, Package), *$3};
|
{ $$ = new AstPackageExport{$<fl>3, *$<strp>1, *$3};
|
||||||
if ($<scp>1) SYMP->exportItem($<scp>1, *$3); }
|
if ($<scp>1) SYMP->exportItem($<scp>1, *$3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ for s in [
|
||||||
'EOF in unterminated string', # Instead get normal unterminated
|
'EOF in unterminated string', # Instead get normal unterminated
|
||||||
'Enum names without values only allowed on numeric types', # Hard to hit
|
'Enum names without values only allowed on numeric types', # Hard to hit
|
||||||
'Enum ranges must be integral, per spec', # Hard to hit
|
'Enum ranges must be integral, per spec', # Hard to hit
|
||||||
|
'Import package not found: ', # Errors earlier, until future parser released
|
||||||
'Return with return value isn\'t underneath a function', # Hard to hit, get other bad return messages
|
'Return with return value isn\'t underneath a function', # Hard to hit, get other bad return messages
|
||||||
'Syntax error: Range \':\', \'+:\' etc are not allowed in the instance ', # Instead get syntax error
|
'Syntax error: Range \':\', \'+:\' etc are not allowed in the instance ', # Instead get syntax error
|
||||||
'Syntax error parsing real: \'', # Instead can't lex the number
|
'Syntax error parsing real: \'', # Instead can't lex the number
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%Error: t/t_lint_import_name_bad.v:11:12: Import object not found: 'defs::sigs'
|
%Error: t/t_lint_import_name_bad.v:11:12: Import object not found: 'defs'
|
||||||
11 | import defs::sigs;
|
11 | import defs::sigs;
|
||||||
| ^~
|
| ^~
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
%Error: t/t_package_export_bad2.v:12:18: Export package not found: 'Pkg1b'
|
||||||
|
12 | export Pkg1b::*;
|
||||||
|
| ^
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('linter')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2024 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
package Pkg1;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package Pkg10;
|
||||||
|
// verilator lint_off PKGNODECL
|
||||||
|
export Pkg1b::*; // BAD - typo in package name
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
%Error: t/t_package_import_bad2.v:12:11: Importing from missing package 'Pkg1b'
|
||||||
|
12 | import Pkg1b::*;
|
||||||
|
| ^~~~~
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('linter')
|
||||||
|
|
||||||
|
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2024 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
package Pkg1;
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
package Pkg10;
|
||||||
|
// verilator lint_off PKGNODECL
|
||||||
|
import Pkg1b::*; // BAD - typo in package name
|
||||||
|
endpackage
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue