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