From d4c5cfc58403838c25589529d0ac461ce3462e48 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 13 Apr 2011 18:30:00 -0700 Subject: [PATCH] Add packages and component declarations within those packages. This creates the Package class to represent packages, and the Scope class to represent scopes in general. The library functions are worked up to support scanning scopes for declarations that are imported by "use" clauses. --- vhdlpp/Makefile.in | 4 +- vhdlpp/architec.cc | 12 +---- vhdlpp/architec.h | 6 +-- vhdlpp/debug.cc | 19 +++++--- vhdlpp/library.cc | 105 +++++++++++++++++++++++++++++++++++++++++++ vhdlpp/package.cc | 29 ++++++++++++ vhdlpp/package.h | 37 +++++++++++++++ vhdlpp/parse.y | 41 +++++++++++++++-- vhdlpp/parse_misc.cc | 34 -------------- vhdlpp/parse_misc.h | 14 +++++- vhdlpp/scope.cc | 40 +++++++++++++++++ vhdlpp/scope.h | 45 +++++++++++++++++++ 12 files changed, 323 insertions(+), 63 deletions(-) create mode 100644 vhdlpp/library.cc create mode 100644 vhdlpp/package.cc create mode 100644 vhdlpp/package.h create mode 100644 vhdlpp/scope.cc create mode 100644 vhdlpp/scope.h diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index 1cacd3e45..97b429340 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -60,9 +60,9 @@ LIBS = @LIBS@ @EXTRALIBS@ M = StringHeap.o LineInfo.o O = main.o architec.o architec_elaborate.o compiler.o entity.o entity_elaborate.o \ - expression.o vsignal.o vtype.o vtype_elaborate.o \ + expression.o package.o scope.o vsignal.o vtype.o vtype_elaborate.o \ lexor.o lexor_keyword.o parse.o \ - parse_misc.o vhdlreal.o vhdlint.o debug.o \ + parse_misc.o library.o vhdlreal.o vhdlint.o debug.o \ architec_emit.o entity_emit.o expression_emit.o vtype_emit.o \ $M diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 19f83f7ec..6d9f47000 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -26,10 +26,9 @@ using namespace std; Architecture::Architecture(perm_string name, map&sigs, map&comps, list&s) -: name_(name) +: Scope(comps), name_(name) { signals_ = sigs; - components_ = comps; statements_.splice(statements_.end(), s); } @@ -37,15 +36,6 @@ Architecture::~Architecture() { } -const ComponentBase* Architecture::find_component(perm_string by_name) -{ - map::const_iterator cur = components_.find(by_name); - if (cur == components_.end()) - return 0; - else - return cur->second; -} - Architecture::Statement::Statement() { } diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index f84f99ce2..e184cb1ea 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -21,6 +21,7 @@ # include "StringHeap.h" # include "LineInfo.h" +# include "scope.h" # include # include @@ -36,7 +37,7 @@ class named_expr_t; * etc.) of a parsed VHDL architecture. These objects are ultimately * put into entities. */ -class Architecture : public LineInfo { +class Architecture : public Scope, public LineInfo { public: // Architectures contain concurrent statements, that are @@ -65,7 +66,6 @@ class Architecture : public LineInfo { ~Architecture(); perm_string get_name() const { return name_; } - const ComponentBase* find_component(perm_string by_name); // Elaborate this architecture in the context of the given entity. int elaborate(Entity*entity); @@ -83,8 +83,6 @@ class Architecture : public LineInfo { perm_string name_; // Signals declared local to this architecture std::map signals_; - // Component declarations... - std::map components_; // Concurrent statements local to this architecture std::list statements_; diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 295144804..f787ad10f 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -76,6 +76,17 @@ void ComponentBase::dump_ports(ostream&out) const } } +void Scope::dump_scope(ostream&out) const +{ + // Dump component declarations + for (map::const_iterator cur = components_.begin() + ; cur != components_.end() ; ++cur) { + out << " component " << cur->first << " is" << endl; + cur->second->dump_ports(out); + out << " end component " << cur->first << endl; + } +} + void Entity::dump(ostream&out) const { out << "entity " << get_name() @@ -100,13 +111,7 @@ void Architecture::dump(ostream&out, perm_string of_entity) const cur->second->dump(out); } - // Dump component declarations - for (map::const_iterator cur = components_.begin() - ; cur != components_.end() ; ++cur) { - out << " component " << cur->first << " is" << endl; - cur->second->dump_ports(out); - out << " end component " << cur->first << endl; - } + dump_scope(out); for (list::const_iterator cur = statements_.begin() ; cur != statements_.end() ; ++cur) { diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc new file mode 100644 index 000000000..6b4f13a85 --- /dev/null +++ b/vhdlpp/library.cc @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "parse_misc.h" +# include "compiler.h" +# include "package.h" +# include + +using namespace std; + + +struct library_contents { + map packages; +}; + +static map libraries; + +/* + * This function saves a package into the named library. Create the + * library if necessary. + */ +void library_save_package(const char*libname, Package*pack) +{ + if (libname == 0) + libname = "work"; + + perm_string use_libname = lex_strings.make(libname); + struct library_contents&lib = libraries[use_libname]; + + lib.packages[pack->name()] = pack; +} + +void library_import(const YYLTYPE&loc, const std::list*names) +{ + for (std::list::const_iterator cur = names->begin() + ; cur != names->end() ; ++cur) { + if (*cur == "ieee") { + // The ieee library is special and handled by an + // internal function. + import_ieee(); + } else { + sorrymsg(loc, "library import (%s) not implemented.\n", cur->str()); + } + } +} + +void library_use(const YYLTYPE&loc, struct library_results&res, + const char*libname, const char*package, const char*name) +{ + if (libname == 0) { + errormsg(loc, "error: No library name for this use clause?\n"); + return; + } + + perm_string use_library = lex_strings.make(libname); + perm_string use_package = lex_strings.make(package); + perm_string use_name = name? lex_strings.make(name) : perm_string::literal("all"); + + // Special case handling for the IEEE library. + if (use_library == "ieee") { + import_ieee_use(use_package, use_name); + return; + } + + struct library_contents&lib = libraries[use_library]; + Package*pack = lib.packages[use_package]; + if (pack == 0) { + errormsg(loc, "No package %s in library %s\n", + use_package.str(), use_library.str()); + return; + } + + // We have a package that we are going to extract names + // from. Use the name to get the selected objects, and write + // results into the "res" members. + + if (use_name == "all") { + sorrymsg(loc, "Don't support all from package\n"); + return; + } + + if (ComponentBase*cur = pack->find_component(use_name)) { + res.components.push_back(cur); + return; + } + + errormsg(loc, "No such name %s in package %s\n", + use_name.str(), pack->name().str()); +} diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc new file mode 100644 index 000000000..1ca6b55e7 --- /dev/null +++ b/vhdlpp/package.cc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "package.h" + +Package::Package(perm_string n, map&comps) +: Scope(comps), name_(n) +{ +} + +Package::~Package() +{ +} diff --git a/vhdlpp/package.h b/vhdlpp/package.h new file mode 100644 index 000000000..0bfa0c909 --- /dev/null +++ b/vhdlpp/package.h @@ -0,0 +1,37 @@ +#ifndef __package_H +#define __package_H +/* + * Copyright (c) 2011 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "scope.h" +# include "LineInfo.h" + +class Package : public Scope, public LineInfo { + + public: + Package(perm_string name, std::map&comps); + ~Package(); + + perm_string name() const { return name_; } + + private: + perm_string name_; +}; + +#endif diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 2547de0b7..eb2dbb405 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -27,6 +27,7 @@ # include "parse_misc.h" # include "architec.h" # include "expression.h" +# include "package.h" # include "vsignal.h" # include "vtype.h" # include @@ -68,9 +69,25 @@ int parse_sorrys = 0; static map block_signals; /* - * This map accumulates component declarations. + * This map accumulates component declarations. This variable is used + * by rules that build up package, architectures, whatever objects + * can contain component declarations. */ static map block_components; + +/* + * Calls to library_use return a collections of declation objects that + * belong in the scope that is being worked on. This is a convenience + * function for collecting those results into the parser variables. + */ +static void collect_library_results(struct library_results&res) +{ + for (list::iterator cur = res.components.begin() + ; cur != res.components.end() ; ++cur) { + block_components[(*cur)->get_name()] = *cur; + } +} + %} @@ -288,6 +305,8 @@ block_declarative_item | component_declaration + | use_clause_lib + /* Various error handling rules for block_declarative_item... */ | K_signal error ';' @@ -796,10 +815,13 @@ package_declaration errormsg(@1, "Identifier %s doesn't match package name %s.\n", $7, name.str()); } + Package*tmp = new Package(name, block_components); + FILE_NAME(tmp, @1); delete[]$2; if ($7) delete[]$7; - sorrymsg(@1, "Package declarations not supported yet.\n"); block_components.clear(); + /* Put this package into the work library. */ + library_save_package(0, tmp); } | K_package IDENTIFIER K_is error K_end K_package_opt identifier_opt ';' { errormsg(@4, "Syntax error in package clause.\n"); @@ -952,19 +974,30 @@ selected_names $$ = tmp; } ; + /* The *_use variant of selected_name is used by the "use" clause. It is syntactically identical to other selected_name rules, but is a convenient place to attach use_clause actions. */ selected_name_use : IDENTIFIER '.' K_all - { library_use(@1, 0, $1, 0); + { struct library_results res; + library_use(@1, res, 0, $1, 0); delete[]$1; } | IDENTIFIER '.' IDENTIFIER '.' K_all - { library_use(@1, $1, $3, 0); + { struct library_results res; + library_use(@1, res, $1, $3, 0); delete[]$1; delete[]$3; } + | IDENTIFIER '.' IDENTIFIER '.' IDENTIFIER + { struct library_results res; + library_use(@1, res, $1, $3, $5); + collect_library_results(res); + delete[]$1; + delete[]$3; + delete[]$5; + } ; selected_names_use diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index 5fc268ca2..c376c3b05 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -88,37 +88,3 @@ const VType* calculate_subtype(const char*base_name, return base_type; } - -void library_import(const YYLTYPE&loc, const std::list*names) -{ - for (std::list::const_iterator cur = names->begin() - ; cur != names->end() ; ++cur) { - if (*cur == "ieee") { - // The ieee library is special and handled by an - // internal function. - import_ieee(); - } else { - errormsg(loc, "sorry: library import (%s) not implemented.\n", cur->str()); - } - } -} - -void library_use(const YYLTYPE&loc, const char*libname, const char*pack, const char*name) -{ - if (libname == 0) { - errormsg(loc, "error: No library name for this use clause?\n"); - return; - } - - perm_string use_library = lex_strings.make(libname); - perm_string use_package = lex_strings.make(pack); - perm_string use_name = name? lex_strings.make(name) : perm_string::literal("all"); - - // Special case handling for the IEEE library. - if (use_library == "ieee") { - import_ieee_use(use_package, use_name); - return; - } - - errormsg(loc, "sorry: Only the IEEE library is supported,\n"); -} diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h index b03bccc73..dbea11861 100644 --- a/vhdlpp/parse_misc.h +++ b/vhdlpp/parse_misc.h @@ -23,6 +23,7 @@ class Architecture; class Expression; +class Package; class VType; extern void bind_architecture_to_entity(const char*ename, Architecture*arch); @@ -32,8 +33,19 @@ extern const VType* calculate_subtype(const char*base_name, bool downto, Expression*array_right); +extern void library_save_package(const char*libname, Package*pack); + extern void library_import(const YYLTYPE&loc, const std::list*names); -extern void library_use(const YYLTYPE&loc, const char*libname, const char*pack, const char*ident); +struct library_results { + std::list components; + std::list types; + void clear() { + components.clear(); + types.clear(); + } +}; + +extern void library_use(const YYLTYPE&loc, struct library_results&res, const char*libname, const char*pack, const char*ident); #endif diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc new file mode 100644 index 000000000..e25b429af --- /dev/null +++ b/vhdlpp/scope.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "scope.h" + +using namespace std; + +Scope::Scope(map&comps) +{ + components_ = comps; +} + +Scope::~Scope() +{ +} + +ComponentBase* Scope::find_component(perm_string by_name) +{ + map::const_iterator cur = components_.find(by_name); + if (cur == components_.end()) + return 0; + else + return cur->second; +} diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h new file mode 100644 index 000000000..93be0c192 --- /dev/null +++ b/vhdlpp/scope.h @@ -0,0 +1,45 @@ +#ifndef __scope_H +#define __scope_H +/* + * Copyright (c) 2011 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include +# include "StringHeap.h" + +class ComponentBase; +class VType; + +class Scope { + + public: + Scope(std::map&comps); + ~Scope(); + + ComponentBase* find_component(perm_string by_name); + + void dump_scope(ostream&out) const; + + private: + // Component declarations... + std::map components_; + // Type declarations... + std::map types_; +}; + +#endif