diff --git a/Changes b/Changes index de7add07a..d9cc3535f 100644 --- a/Changes +++ b/Changes @@ -16,7 +16,7 @@ indicates the contributor was also the author of the fix; Thanks! *** Support "program". -*** Support "package" and $unit. +*** Support "package", "import" and $unit. *** Support typedef. [Donal Casey] diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index a9499ed6c..bdf4af68d 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -403,6 +403,10 @@ void AstNodeModule::dump(ostream& str) { if (modPublic()) str<<" [P]"; if (inLibrary()) str<<" [LIB]"; } +void AstPackageImport::dump(ostream& str) { + this->AstNode::dump(str); + str<<" -> "<AstNode::dump(str); if (isCircular()) str<<" [CIRC]"; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index ab32f2874..6ce0a0af8 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -775,6 +775,23 @@ struct AstPackage : public AstNodeModule { bool isDollarUnit() const { return name() == dollarUnitName(); } }; +struct AstPackageImport : public AstNode { +private: + // A package import declaration + string m_name; + AstPackage* m_packagep; // Package hierarchy +public: + AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name) + : AstNode (fl), m_name(name), m_packagep(packagep) {} + ASTNODE_NODE_FUNCS(PackageImport, PACKAGEIMPORT) + virtual bool broken() const { return (!m_packagep || !m_packagep->brokeExists()); } + virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep()->castPackage(); } + 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; } +}; + struct AstCell : public AstNode { // A instantiation cell or interface call (don't know which until link) private: diff --git a/src/V3Link.cpp b/src/V3Link.cpp index 4ce8d4740..503edd285 100644 --- a/src/V3Link.cpp +++ b/src/V3Link.cpp @@ -555,6 +555,20 @@ private: } } + virtual void visit(AstPackageImport* nodep, AstNUser*) { + UINFO(2," Link: "<packagep()); + if (nodep->name()!="*") { + AstNode* impp = srcp->findIdFlat(nodep->name()); + if (!impp) { + nodep->v3error("Import object not found: "<packagep()->prettyName()<<"::"<prettyName()); + } + } + m_curVarsp->import(srcp, nodep->name()); + // No longer needed + nodep->unlinkFrBack()->deleteTree(); nodep=NULL; + } + virtual void visit(AstNode* nodep, AstNUser*) { // Default: Just iterate nodep->iterateChildren(*this); diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index a77dda8a6..f11bfbcf5 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -171,15 +171,16 @@ public: // Lookup the given string as an identifier, return type of the id, scanning upward return symCurrentp()->findIdUpward(name); } - void import(AstNode* nodep, const string& pkg, const string& id_or_star) { + void import(AstNode* packagep, const string& id_or_star) { // Import from package::id_or_star to this - AstNode* entp = findEntUpward(pkg); - if (!entp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE - nodep->v3fatalSrc("Import package not found: "+pkg); + V3SymTable* symp = getTable(packagep); + if (!symp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE + packagep->v3fatalSrc("Import package not found"); return; } // Walk old sym table and reinsert into current table - nodep->v3fatalSrc("Unimplemented: import"); + // We let V3Link report the error instead of us + symCurrentp()->import(symp, id_or_star); } public: // CREATORS diff --git a/src/V3SymTable.h b/src/V3SymTable.h index bbdfed22e..bf3d8ab5d 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -87,6 +87,24 @@ class V3SymTable : public AstNUser { if (m_upperp) return m_upperp->findIdUpward(name); return NULL; } + bool import(const V3SymTable* 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()) { + reinsert(it->first, it->second); + any = true; + } + } else { + for (IdNameMap::const_iterator it=srcp->m_idNameMap.begin(); it!=srcp->m_idNameMap.end(); ++it) { + reinsert(it->first, it->second); + any = true; + } + } + return any; + } void dump(ostream& os, const string& indent="", bool user4p_is_table=false) const { if (user4p_is_table) { AstUser4InUse::check(); } for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) { diff --git a/src/verilog.l b/src/verilog.l index 0bcd33dcd..c9ff806e7 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -371,6 +371,7 @@ escid \\[^ \t\f\r\n]+ "endproperty" { FL; return yENDPROPERTY; } "final" { FL; return yFINAL; } "iff" { FL; return yIFF; } + "import" { FL; return yIMPORT; } "int" { FL; return yINT; } "logic" { FL; return yLOGIC; } "longint" { FL; return yLONGINT; } @@ -416,7 +417,6 @@ escid \\[^ \t\f\r\n]+ "forkjoin" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "ignore_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "illegal_bins" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } - "import" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "inside" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "interface" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } "intersect" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); } diff --git a/src/verilog.y b/src/verilog.y index 4b682ef3a..a69d720e5 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -272,6 +272,7 @@ class AstSenTree; %token yGENVAR "genvar" %token yIF "if" %token yIFF "iff" +%token yIMPORT "import" %token yINITIAL "initial" %token yINOUT "inout" %token yINPUT "input" @@ -593,6 +594,26 @@ package_or_generate_item_declaration: // ==IEEE: package_or_generate_item | ';' { $$ = NULL; } ; +package_import_declaration: // ==IEEE: package_import_declaration + yIMPORT package_import_itemList ';' { $$ = $2; } + ; + +package_import_itemList: + package_import_item { $$ = $1; } + | package_import_itemList ',' package_import_item { $$ = $1->addNextNull($3); } + ; + +package_import_item: // ==IEEE: package_import_item + yaID__aPACKAGE yP_COLONCOLON package_import_itemObj + { $$ = new AstPackageImport($1, $1->castPackage(), *$3); + SYMP->import($1,*$3); } + ; + +package_import_itemObj: // IEEE: part of package_import_item + idAny { $$=$1; $$=$1; } + | '*' { $$=$1; static string star="*"; $$=☆ } + ; + //********************************************************************** // Module headers @@ -1079,7 +1100,7 @@ data_declaration: // ==IEEE: data_declaration // // VARRESET can't be called here - conflicts data_declarationVar { $$ = $1; } | type_declaration { $$ = $1; } - //UNSUP package_import_declaration { $$ = $1; } + | package_import_declaration { $$ = $1; } // // IEEE: virtual_interface_declaration // // "yVIRTUAL yID yID" looks just like a data_declaration // // Therefore the virtual_interface_declaration term isn't used diff --git a/test_regress/t/t_package.v b/test_regress/t/t_package.v index 2f4f531d8..f99db5e01 100644 --- a/test_regress/t/t_package.v +++ b/test_regress/t/t_package.v @@ -16,6 +16,13 @@ package p; endfunction endpackage +package p2; + typedef int package2_type_t; + function [3:0] plustwo(input [3:0] i); + plustwo = i+2; + endfunction +endpackage + module t (/*AUTOARG*/ // Inputs clk @@ -25,6 +32,8 @@ module t (/*AUTOARG*/ $unit::unit_type_t vdu; p::package_type_t vp; + t2 t2 (); + initial begin if (unit_plusone(1) !== 2) $stop; if ($unit::unit_plusone(1) !== 2) $stop; @@ -34,3 +43,15 @@ module t (/*AUTOARG*/ $finish; end endmodule + +module t2; + import p::*; + import p2::plustwo; + import p2::package2_type_t; + package_type_t vp; + package2_type_t vp2; + initial begin + if (plusone(1) !== 2) $stop; + if (plustwo(1) !== 3) $stop; + end +endmodule