diff --git a/PPackage.h b/PPackage.h index f828384ae..ff0e0f96c 100644 --- a/PPackage.h +++ b/PPackage.h @@ -22,6 +22,7 @@ # include "PScope.h" # include "LineInfo.h" # include "StringHeap.h" +# include /* * SystemVerilog supports class declarations with their own lexical @@ -35,6 +36,7 @@ class PPackage : public PScopeExtra, public LineInfo { explicit PPackage (perm_string name, LexicalScope*parent); ~PPackage(); + void pform_dump(std::ostream&out) const; }; #endif diff --git a/main.cc b/main.cc index be73a3bd6..091c084a2 100644 --- a/main.cc +++ b/main.cc @@ -987,6 +987,12 @@ int main(int argc, char*argv[]) ; cur != disciplines.end() ; ++ cur ) { pform_dump(out, (*cur).second); } + out << "PFORM DUMP PACKAGES:" << endl; + for (map::iterator pac = pform_packages.begin() + ; pac != pform_packages.end() ; ++ pac) { + pform_dump(out, pac->second); + } + out << "PFORM DUMP MODULES:" << endl; for (map::iterator mod = pform_modules.begin() ; mod != pform_modules.end() ; ++ mod ) { diff --git a/parse.y b/parse.y index 9403c3338..b6532c31d 100644 --- a/parse.y +++ b/parse.y @@ -1354,13 +1354,19 @@ package_declaration /* IEEE1800-2005 A.1.2 */ package_import_declaration /* IEEE1800-2005 A.2.1.3 */ : K_import package_import_item_list ';' - { yyerror(@1, "sorry: Package import declarations not supported."); - } + { } ; package_import_item : IDENTIFIER K_SCOPE_RES IDENTIFIER + { pform_package_import(@2, $1, $3); + delete[]$1; + delete[]$3; + } | IDENTIFIER K_SCOPE_RES '*' + { pform_package_import(@2, $1, 0); + delete[]$1; + } ; package_import_item_list @@ -1370,6 +1376,7 @@ package_import_item_list package_item /* IEEE1800-2005 A.1.10 */ : timeunits_declaration + | K_parameter param_type parameter_assign_list ';' | K_localparam param_type localparam_assign_list ';' | type_declaration | function_declaration diff --git a/parse_api.h b/parse_api.h index 91b80e3d5..e3526f348 100644 --- a/parse_api.h +++ b/parse_api.h @@ -22,9 +22,11 @@ # include # include "StringHeap.h" # include +# include # include class Module; +class PPackage; class PUdp; /* @@ -32,8 +34,11 @@ class PUdp; * Verilog source into pform for elaboration. The parser adds modules * to these maps as it compiles modules in the Verilog source. */ -extern map pform_modules; -extern map pform_primitives; +extern std::map pform_modules; +extern std::map pform_primitives; + +extern std::map pform_packages; +extern void pform_dump(std::ostream&out, const PPackage*pac); /* * This code actually invokes the parser to make modules. The first diff --git a/pform.cc b/pform.cc index aacaf0bbf..57379d8ca 100644 --- a/pform.cc +++ b/pform.cc @@ -294,6 +294,12 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope) return scopex; } +LexicalScope* pform_peek_scope(void) +{ + assert(lexical_scope); + return lexical_scope; +} + PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name) { PClass*class_scope = new PClass(name, lexical_scope); diff --git a/pform.h b/pform.h index 6a76664b1..488fda62d 100644 --- a/pform.h +++ b/pform.h @@ -187,10 +187,6 @@ extern void pform_class_property(const struct vlltype&loc, std::list*decls); extern void pform_end_class_declaration(void); -extern void pform_start_package_declaration(const struct vlltype&loc, - const char*type); -extern void pform_end_package_declaration(const struct vlltype&loc); - extern void pform_make_udp(perm_string name, list*parms, svector*decl, list*table, Statement*init, @@ -202,6 +198,14 @@ extern void pform_make_udp(perm_string name, list*parms, list*table, const char*file, unsigned lineno); +/* + * Package related functions. + */ +extern void pform_start_package_declaration(const struct vlltype&loc, + const char*type); +extern void pform_end_package_declaration(const struct vlltype&loc); +extern void pform_package_import(const struct vlltype&loc, + const char*pkg_name, const char*ident); /* * Enter/exit name scopes. The push_scope function pushes the scope @@ -210,6 +214,11 @@ extern void pform_make_udp(perm_string name, */ extern void pform_pop_scope(); +/* + * Peek at the current (most recently active) scope. + */ +extern LexicalScope* pform_peek_scope(); + extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name); extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name); extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name, diff --git a/pform_dump.cc b/pform_dump.cc index 6d54e3a01..c7b302592 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -29,6 +29,7 @@ # include "PClass.h" # include "PEvent.h" # include "PGenerate.h" +# include "PPackage.h" # include "PSpec.h" # include "discipline.h" # include "ivl_target_priv.h" @@ -1496,3 +1497,16 @@ void pform_dump(std::ostream&out, const ivl_discipline_s*dis) out << " flow " << tmp->name() << ";" << endl; out << "enddiscipline" << endl; } + +void pform_dump(std::ostream&out, const PPackage*pac) +{ + pac->pform_dump(out); +} + +void PPackage::pform_dump(std::ostream&out) const +{ + out << "package " << pscope_name() << endl; + dump_localparams_(out, 4); + dump_parameters_(out, 4); + out << "endpackage" << endl; +} diff --git a/pform_package.cc b/pform_package.cc index e760c578e..c0fadd05e 100644 --- a/pform_package.cc +++ b/pform_package.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * Copyright CERN 2013 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -20,23 +21,76 @@ # include "pform.h" # include "PPackage.h" # include "parse_misc.h" +# include "parse_api.h" +# include +# include # include "ivl_assert.h" +using namespace std; + +/* + * This is a map of packages that have been defined. + */ +map pform_packages; + static PPackage*pform_cur_package = 0; void pform_start_package_declaration(const struct vlltype&loc, const char*name) { - VLerror(loc, "sorry: Package declarations not supported."); ivl_assert(loc, pform_cur_package == 0); perm_string use_name = lex_strings.make(name); PPackage*pkg_scope = pform_push_package_scope(loc, use_name); + FILE_NAME(pkg_scope, loc); pform_cur_package = pkg_scope; } void pform_end_package_declaration(const struct vlltype&loc) { ivl_assert(loc, pform_cur_package); + perm_string use_name = pform_cur_package->pscope_name(); + + map::const_iterator test = pform_packages.find(use_name); + if (test != pform_packages.end()) { + ostringstream msg; + msg << "Package " << use_name << " was already declared here: " + << test->second->get_fileline() << ends; + VLerror(msg.str().c_str()); + } else { + pform_packages[use_name] = pform_cur_package; + } + + + pform_packages[use_name] = pform_cur_package; pform_cur_package = 0; pform_pop_scope(); } + +/* + * Do the import early, during processing. This requires that the + * package is declared in pform ahead of time (it is) and that we can + * simply transfer definitions to the current scope (we can). + */ +void pform_package_import(const struct vlltype&, const char*pkg_name, const char*ident) +{ + perm_string use_name = lex_strings.make(pkg_name); + map::const_iterator pcur = pform_packages.find(use_name); + if (pcur == pform_packages.end()) { + ostringstream msg; + msg << "Package " << pkg_name << " not found." << ends; + VLerror(msg.str().c_str()); + return; + } + + perm_string use_ident; + if (ident) use_ident = lex_strings.make(ident); + + PPackage*pkg = pcur->second; + LexicalScope*scope = pform_peek_scope(); + + for (map::const_iterator cur = pkg->parameters.begin() + ; cur != pkg->parameters.end() ; ++cur) { + + scope->parameters[cur->first] = cur->second; + } +}