diff --git a/vhdlpp/compiler.h b/vhdlpp/compiler.h index f0ae81ad5..380ca0f01 100644 --- a/vhdlpp/compiler.h +++ b/vhdlpp/compiler.h @@ -36,5 +36,6 @@ extern StringHeapLex filename_strings; extern void library_set_work_path(const char*work_path); extern void library_add_directory(const char*directory); +extern int emit_packages(void); #endif diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index d009446bf..d95a7b47b 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -134,6 +134,8 @@ void library_save_package(perm_string parse_library_name, Package*pack) // library right now, then store it in the work library. if (parse_library_name.str() == 0) store_package_in_work(pack); + else + pack->set_library(parse_library_name); } static void import_library_name(const YYLTYPE&loc, perm_string name) @@ -369,3 +371,25 @@ static void store_package_in_work(const Package*pack) pack->write_to_stream(file); } + +static int emit_packages(perm_string lib_name, const map&packages) +{ + int errors = 0; + for (map::const_iterator cur = packages.begin() + ; cur != packages.end() ; ++cur) { + errors += cur->second->emit_package(cout); + } + + return errors; +} + +int emit_packages(void) +{ + int errors = 0; + for (map::iterator cur = libraries.begin() + ; cur != libraries.end() ; ++cur) { + errors += emit_packages(cur->first, cur->second.packages); + } + + return 0; +} diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index ce3fa2df6..45fb02e9d 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -218,17 +218,24 @@ int main(int argc, char*argv[]) } if (errors > 0) { - parser_cleanup(); + parser_cleanup(); return 2; } errors = elaborate_entities(); if (errors > 0) { fprintf(stderr, "%d errors elaborating design.\n", errors); - parser_cleanup(); + parser_cleanup(); return 3; } + errors = emit_packages(); + if (errors > 0) { + fprintf(stderr, "%d errors emitting packages.\n", errors); + parser_cleanup(); + return 4; + } + errors = emit_entities(); if (errors > 0) { fprintf(stderr, "%d errors emitting design.\n", errors); diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 2dd43ded3..6541b2be8 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -20,6 +20,7 @@ # include "package.h" # include "entity.h" # include "parse_misc.h" +# include "ivl_assert.h" Package::Package(perm_string n, const ScopeBase&ref) : Scope(ref), name_(n) @@ -31,6 +32,12 @@ Package::~Package() ScopeBase::cleanup(); } +void Package::set_library(perm_string lname) +{ + ivl_assert(*this, from_library_.str() == 0); + from_library_ = lname; +} + /* * The Package::write_to_stream is used to write the package to the * work space (or library) so writes proper VHDL that the library diff --git a/vhdlpp/package.h b/vhdlpp/package.h index 8f9fd04ae..bec82a606 100644 --- a/vhdlpp/package.h +++ b/vhdlpp/package.h @@ -1,7 +1,7 @@ #ifndef __package_H #define __package_H /* - * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-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 @@ -29,12 +29,19 @@ class Package : public Scope, public LineInfo { Package(perm_string name, const ScopeBase&ref); ~Package(); + // The the library from which this package came. Having a + // source library influences the emit_package() method. + void set_library(perm_string); + perm_string name() const { return name_; } // This method writes a package header to a library file. void write_to_stream(std::ostream&fd) const; + int emit_package(std::ostream&fd) const; + private: + perm_string from_library_; perm_string name_; }; diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc new file mode 100644 index 000000000..f0b2751b6 --- /dev/null +++ b/vhdlpp/package_emit.cc @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013 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 + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include "package.h" +# include + +using namespace std; + +int Package::emit_package(ostream&fd) const +{ + // Don't emit the package if there is nothing in it that SV + // cares about. + if (new_types_.empty() && old_subprograms_.empty() && new_subprograms_.empty()) + return 0; + + // If this package was imported from a library, then do not + // emit it again. + if (from_library_.str() != 0) { + fd << "/* Suppress package " << name() + << " from library " << from_library_ << " */" << endl; + return 0; + } + + int errors = 0; + + fd << "package \\" << name() << " ;" << endl; + + // Only emit types that were defined within this package. Skip + // the types that were imported from elsewhere. + for (map::const_iterator cur = new_types_.begin() + ; cur != new_types_.end() ; ++ cur) { + errors += cur->second->emit_def(fd); + fd << " " << cur->first << " ;" << endl; + } + + for (map::const_iterator cur = old_subprograms_.begin() + ; cur != old_subprograms_.end() ; ++ cur) { + errors += cur->second->emit_package(fd); + } + + for (map::const_iterator cur = new_subprograms_.begin() + ; cur != new_subprograms_.end() ; ++ cur) { + errors += cur->second->emit_package(fd); + } + + fd << "endpackage" << endl; + + return errors; +} diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index afd4764eb..7ec691d32 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -38,6 +38,9 @@ class Subprogram : public LineInfo { inline const perm_string&name() const { return name_; } + // Emit a definition as it would show up in a package. + int emit_package(std::ostream&fd) const; + void write_to_stream(std::ostream&fd) const; void dump(std::ostream&fd) const; diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc new file mode 100644 index 000000000..e70351a4c --- /dev/null +++ b/vhdlpp/subprogram_emit.cc @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 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 + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include "subprogram.h" +# include "sequential.h" +# include "vtype.h" +# include + +using namespace std; + +int Subprogram::emit_package(ostream&fd) const +{ + int errors = 0; + + if (return_type_) { + fd << "function "; + return_type_->emit_def(fd); + fd << " " << name_; + fd << ";" << endl; + } else { + fd << "task " << name_ << ";" << endl; + } + + if (statements_) { + for (list::const_iterator cur = statements_->begin() + ; cur != statements_->end() ; ++cur) { + errors += (*cur)->emit(fd, 0, 0); + } + } else { + fd << " begin /* empty body */ end" << endl; + } + + if (return_type_) + fd << "endfunction" << endl; + else + fd << "endtask" << endl; + + return errors; +} diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index a3ca1add5..7508ee8c4 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -88,9 +88,15 @@ int VTypeArray::emit_def(ostream&out) const cur = dims.front(); dims.pop_front(); out << "["; - errors += cur->dimension(0).msb()->emit(out, 0, 0); + if (cur->dimension(0).msb()) + errors += cur->dimension(0).msb()->emit(out, 0, 0); + else + out << "?error?"; out << ":"; - errors += cur->dimension(0).lsb()->emit(out, 0, 0); + if (cur->dimension(0).lsb()) + errors += cur->dimension(0).lsb()->emit(out, 0, 0); + else + out << "?error?"; out << "]"; } @@ -130,6 +136,9 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const case INTEGER: out << "bool [31:0]"; break; + case CHARACTER: + out << "char"; + break; default: assert(0); break;