Support package export, bug1217.

This commit is contained in:
Wilson Snyder 2017-09-20 21:04:59 -04:00
parent 331fcb633e
commit 89c8449ec0
10 changed files with 179 additions and 30 deletions

View File

@ -6,6 +6,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
*** Support or/and/xor array intrinsic methods, bug1210. [Mike Popoloski]
*** Support package export, bug1217. [Usuario Eda]
*** Fix ordering of arrayed cell wide connections, bug1202 partial. [Mike Popoloski]
**** Support module port parameters without defaults, bug 1213. [Mike Popoloski]

View File

@ -891,6 +891,10 @@ void AstNodeModule::dump(ostream& str) {
if (inLibrary()) str<<" [LIB]";
if (dead()) str<<" [DEAD]";
}
void AstPackageExport::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> "<<packagep();
}
void AstPackageImport::dump(ostream& str) {
this->AstNode::dump(str);
str<<" -> "<<packagep();

View File

@ -1508,6 +1508,31 @@ public:
virtual string verilogKwd() const { return "primitive"; }
};
class AstPackageExportStarStar : public AstNode {
// A package export *::* declaration
public:
AstPackageExportStarStar(FileLine* fl)
: AstNode (fl) {}
ASTNODE_NODE_FUNCS(PackageExportStarStar)
};
class AstPackageExport : public AstNode {
private:
// A package export declaration
string m_name;
AstPackage* m_packagep; // Package hierarchy
public:
AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name)
: AstNode (fl), m_name(name), m_packagep(packagep) {}
ASTNODE_NODE_FUNCS(PackageExport)
virtual const char* broken() const { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); return NULL; }
virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); }
virtual void dump(ostream& str);
virtual string name() const { return m_name; }
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
};
class AstPackageImport : public AstNode {
private:
// A package import declaration

View File

@ -1017,6 +1017,24 @@ class LinkDotFindVisitor : public AstNVisitor {
UINFO(9," Link Done: "<<nodep<<endl);
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstPackageExport* nodep) {
UINFO(9," Link: "<<nodep<<endl);
VSymEnt* srcp = m_statep->getNodeSym(nodep->packagep());
if (nodep->name()!="*") {
VSymEnt* impp = srcp->findIdFlat(nodep->name());
if (!impp) {
nodep->v3error("Export object not found: "<<nodep->packagep()->prettyName()<<"::"<<nodep->prettyName());
}
}
m_curSymp->exportFromPackage(m_statep->symsp(), srcp, nodep->name());
UINFO(9," Link Done: "<<nodep<<endl);
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstPackageExportStarStar* nodep) {
UINFO(2," Link: "<<nodep<<endl);
m_curSymp->exportStarStar(m_statep->symsp());
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstNode* nodep) {
// Default: Just iterate
@ -2216,6 +2234,16 @@ private:
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
virtual void visit(AstPackageExport* nodep) {
// No longer needed
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
virtual void visit(AstPackageExportStarStar* nodep) {
// No longer needed
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
virtual void visit(AstCellRef* nodep) {
UINFO(5," AstCellRef: "<<nodep<<" "<<m_ds.ascii()<<endl);
nodep->iterateChildren(*this);

View File

@ -122,7 +122,7 @@ public:
if (foundp) return foundp->nodep();
else return NULL;
}
void import(AstNode* packagep, const string& id_or_star) {
void importItem(AstNode* packagep, const string& id_or_star) {
// Import from package::id_or_star to this
VSymEnt* symp = getTable(packagep);
if (!symp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE
@ -133,6 +133,19 @@ public:
// We let V3LinkDot report the error instead of us
symCurrentp()->importFromPackage(&m_syms, symp, id_or_star);
}
void exportItem(AstNode* packagep, const string& id_or_star) {
// Export from this the remote package::id_or_star
VSymEnt* symp = getTable(packagep);
if (!symp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE
packagep->v3fatalSrc("Export package not found");
return;
}
symCurrentp()->exportFromPackage(&m_syms, symp, id_or_star);
}
void exportStarStar(AstNode* packagep) {
// Export *::* from remote packages
symCurrentp()->exportStarStar(&m_syms);
}
public:
// CREATORS
explicit V3ParseSym(AstNetlist* rootp)

View File

@ -41,6 +41,7 @@ class VSymEnt;
// Symbol table
typedef set<VSymEnt*> VSymMap;
typedef set<const VSymEnt*> VSymConstMap;
class VSymEnt {
// Symbol table that can have a "superior" table for resolving upper references
@ -65,7 +66,7 @@ private:
static inline int debug() { return 0; } // NOT runtime, too hot of a function
#endif
public:
void dumpIterate(ostream& os, VSymMap& doneSymsr, const string& indent, int numLevels, const string& searchName) {
void dumpIterate(ostream& os, VSymConstMap& doneSymsr, const string& indent, int numLevels, const string& searchName) const {
os<<indent<<"+ "<<left<<setw(30)<<(searchName==""?"\"\"":searchName)<<setw(0)<<right;
os<<" se"<<(void*)(this)<<setw(0);
os<<" fallb=se"<<(void*)(m_fallbackp);
@ -82,8 +83,8 @@ public:
}
}
}
void dump(ostream& os, const string& indent="", int numLevels=1) {
VSymMap doneSyms;
void dump(ostream& os, const string& indent="", int numLevels=1) const {
VSymConstMap doneSyms;
dumpIterate(os, doneSyms, indent, numLevels, "TOP");
}
@ -153,35 +154,55 @@ public:
return NULL;
}
private:
bool importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) {
void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) {
if (srcp->exported()
&& !findIdFlat(name)) { // Don't insert over existing entry
VSymEnt* symp = new VSymEnt(graphp, srcp);
symp->exported(false); // Can't reimport an import without an export
symp->imported(true);
reinsert(name, symp);
return true;
} else {
return false;
}
}
void exportOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) {
if (srcp->exported()) {
if (VSymEnt* symp = findIdFlat(name)) { // Should already exist in current table
if (!symp->exported()) symp->exported(true);
}
}
}
public:
bool importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
// Import tokens from source symbol table into this symbol table
// Returns true if successful
bool any = false;
if (id_or_star != "*") {
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
if (it != m_idNameMap.end()) {
if (it != srcp->m_idNameMap.end()) {
importOneSymbol(graphp, it->first, it->second);
}
any = true; // Legal, though perhaps lint questionable to import nothing
} else {
for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) {
if (importOneSymbol(graphp, it->first, it->second)) any = true;
importOneSymbol(graphp, it->first, it->second);
}
}
return any;
}
void exportFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
// Export tokens from source symbol table into this symbol table
if (id_or_star != "*") {
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
if (it != srcp->m_idNameMap.end()) {
exportOneSymbol(graphp, it->first, it->second);
}
} else {
for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) {
exportOneSymbol(graphp, it->first, it->second);
}
}
}
void exportStarStar(VSymGraph* graphp) {
// Export *:*: Export all tokens from imported packages
for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
VSymEnt* symp = it->second;
if (!symp->exported()) symp->exported(true);
}
}
void importFromIface(VSymGraph* graphp, const VSymEnt* srcp, bool onlyUnmodportable = false) {
// Import interface tokens from source symbol table into this symbol table, recursively
@ -239,7 +260,7 @@ public:
VSymEnt* rootp() const { return m_symRootp; }
// Debug
void dump(ostream& os, const string& indent="") {
VSymMap doneSyms;
VSymConstMap doneSyms;
os<<"SymEnt Dump:\n";
m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root");
bool first = true;

View File

@ -707,7 +707,7 @@ package_itemList<nodep>: // IEEE: { package_item }
package_item<nodep>: // ==IEEE: package_item
package_or_generate_item_declaration { $$ = $1; }
//UNSUP anonymous_program { $$ = $1; }
//UNSUP package_export_declaration { $$ = $1; }
| package_export_declaration { $$ = $1; }
| timeunits_declaration { $$ = $1; }
;
@ -746,7 +746,7 @@ package_import_itemList<nodep>:
package_import_item<nodep>: // ==IEEE: package_import_item
yaID__aPACKAGE yP_COLONCOLON package_import_itemObj
{ $$ = new AstPackageImport($<fl>1, $<scp>1->castPackage(), *$3);
SYMP->import($<scp>1,*$3); }
SYMP->importItem($<scp>1,*$3); }
;
package_import_itemObj<strp>: // IEEE: part of package_import_item
@ -754,6 +754,22 @@ package_import_itemObj<strp>: // IEEE: part of package_import_item
| '*' { $<fl>$=$<fl>1; static string star="*"; $$=&star; }
;
package_export_declaration<nodep>: // IEEE: package_export_declaration
yEXPORT '*' yP_COLONCOLON '*' ';' { $$ = new AstPackageExportStarStar($<fl>1); SYMP->exportStarStar($<scp>1); }
| yEXPORT package_export_itemList ';' { $$ = $2; }
;
package_export_itemList<nodep>:
package_export_item { $$ = $1; }
| package_export_itemList ',' package_export_item { $$ = $1->addNextNull($3); }
;
package_export_item<nodep>: // ==IEEE: package_export_item
yaID__aPACKAGE yP_COLONCOLON package_import_itemObj
{ $$ = new AstPackageExport($<fl>1, $<scp>1->castPackage(), *$3);
SYMP->exportItem($<scp>1,*$3); }
;
//**********************************************************************
// Module headers

View File

@ -7,7 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug592");
$Self->{vcs} and $Self->unsupported("VCS unsupported");
compile (

View File

@ -5,17 +5,46 @@
// see bug 591
package pkg2;
parameter PARAM2 = 16;
endpackage // pkg2
package pkg1;
import pkg2::*;
parameter PARAM2 = 16;
parameter PARAM3 = 16;
endpackage : pkg1
package pkg10;
import pkg1::*;
import pkg1::*; // Ignore if already
`ifdef T_PACKAGE_EXPORT
export pkg2::*; // Not supported on all simulators
export *::*; // Not supported on all simulators
`endif
parameter PARAM1 = 8;
endpackage // pkg1
endpackage
package pkg11;
import pkg10::*;
endpackage
package pkg20;
import pkg1::*;
`ifdef T_PACKAGE_EXPORT
export pkg1::*;
`endif
parameter PARAM1 = 8;
endpackage
package pkg21;
import pkg20::*;
endpackage
package pkg30;
import pkg1::*;
`ifdef T_PACKAGE_EXPORT
export pkg1::PARAM2;
export pkg1::PARAM3;
`endif
parameter PARAM1 = 8;
endpackage
package pkg31;
import pkg30::*;
endpackage
module t (/*AUTOARG*/
// Inputs
@ -23,10 +52,17 @@ module t (/*AUTOARG*/
);
input clk;
import pkg1::*;
reg [pkg11::PARAM1 : 0] bus11;
reg [pkg11::PARAM2 : 0] bus12;
reg [pkg11::PARAM3 : 0] bus13;
reg [PARAM1:0] bus1;
reg [PARAM2:0] bus2;
reg [pkg21::PARAM1 : 0] bus21;
reg [pkg21::PARAM2 : 0] bus22;
reg [pkg21::PARAM3 : 0] bus23;
reg [pkg31::PARAM1 : 0] bus31;
reg [pkg31::PARAM2 : 0] bus32;
reg [pkg31::PARAM3 : 0] bus33;
initial begin
$write("*-* All Finished *-*\n");

View File

@ -16,7 +16,12 @@ compile (
make_top_shell => 0,
make_main => 0,
expect=>
'%Error: t/t_package_export.v:\d+: Can\'t find definition of variable: PARAM2
'%Error: t/t_package_export.v:\d+: Can\'t find definition of scope/variable: PARAM2
%Error: t/t_package_export.v:\d+: Can\'t find definition of scope/variable: PARAM3
%Error: t/t_package_export.v:\d+: Can\'t find definition of scope/variable: PARAM2
%Error: t/t_package_export.v:\d+: Can\'t find definition of scope/variable: PARAM3
%Error: t/t_package_export.v:\d+: Can\'t find definition of scope/variable: PARAM2
%Error: t/t_package_export.v:\d+: Can\'t find definition of scope/variable: PARAM3
%Error: Exiting due to.*',
);