diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index eee6094cd..a181be4eb 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -63,6 +63,7 @@ O = main.o architec.o compiler.o entity.o \ expression.o package.o scope.o sequential.o vsignal.o vtype.o \ architec_elaborate.o entity_elaborate.o expression_elaborate.o \ sequential_elaborate.o vtype_elaborate.o \ + entity_stream.o vtype_stream.o \ lexor.o lexor_keyword.o parse.o \ parse_misc.o library.o vhdlreal.o vhdlint.o \ architec_emit.o entity_emit.o expression_emit.o sequential_emit.o vtype_emit.o \ diff --git a/vhdlpp/compiler.h b/vhdlpp/compiler.h index 43d352e11..80e8a1bc7 100644 --- a/vhdlpp/compiler.h +++ b/vhdlpp/compiler.h @@ -30,4 +30,6 @@ extern StringHeapLex lex_strings; extern StringHeapLex filename_strings; +extern void library_set_work_path(const char*work_path); + #endif diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 04a37320b..4d430f7e8 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -65,8 +65,11 @@ class ComponentBase : public LineInfo { // empties the list in the process. void set_interface(std::list*ports); + + void write_to_stream(std::ostream&fd) const; + public: - void dump_ports(ostream&out, int indent = 0) const; + void dump_ports(std::ostream&out, int indent = 0) const; protected: // This is really only used by the Entity derived class. diff --git a/vhdlpp/entity_stream.cc b/vhdlpp/entity_stream.cc new file mode 100644 index 000000000..90f85719e --- /dev/null +++ b/vhdlpp/entity_stream.cc @@ -0,0 +1,57 @@ +/* + * 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 "entity.h" + +using namespace std; + +void ComponentBase::write_to_stream(ostream&fd) const +{ + fd << " component " << name_ << " is" << endl; + fd << " port(" << endl; + + vector::const_iterator cur = ports_.begin(); + while (cur != ports_.end()) { + InterfacePort*item = *cur; + ++cur; + + fd << " " << item->name << " : "; + switch (item->mode) { + case PORT_NONE: + fd << "???? "; + break; + case PORT_IN: + fd << "in "; + break; + case PORT_OUT: + fd << "out "; + break; + } + + item->type->write_to_stream(fd); + + if (cur != ports_.end()) + fd << ";" << endl; + else + fd << endl; + } + + fd << " );" << endl; + fd << " end component;" << endl; +} diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 67511b4ef..435f27297 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -20,10 +20,16 @@ # include "parse_misc.h" # include "compiler.h" # include "package.h" +# include # include +# include +# include using namespace std; +static const char*library_work_path = 0; +static void store_package_in_work(const Package*pack); + struct library_contents { map packages; }; @@ -69,6 +75,9 @@ void library_save_package(const char*libname, Package*pack) struct library_contents&lib = libraries[use_libname]; lib.packages[pack->name()] = pack; + + if (use_libname == "work") + store_package_in_work(pack); } void library_import(const YYLTYPE&loc, const std::list*names) @@ -211,3 +220,18 @@ void generate_global_types(ActiveScope*res) res->bind_name(perm_string::literal("std_logic"), &primitive_STDLOGIC); res->bind_name(perm_string::literal("bit_vector"),&primitive_BOOL_VECTOR); } + +void library_set_work_path(const char*path) +{ + assert(library_work_path == 0); + library_work_path = path; +} + +static void store_package_in_work(const Package*pack) +{ + string path = string(library_work_path).append("/").append(pack->name()).append(".pkg"); + + ofstream file (path.c_str(), ios_base::out|ios_base::app); + + pack->write_to_stream(file); +} diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index 87e4cd9cf..3bcf7f69e 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -45,9 +45,11 @@ const char NOTICE[] = # include # include # include +# include #if defined(HAVE_GETOPT_H) # include #endif +# include bool verbose_flag = false; @@ -55,6 +57,7 @@ bool verbose_flag = false; const char*dump_design_entities_path = 0; const char*dump_libraries_path = 0; + extern void dump_libraries(ostream&file); static void process_debug_token(const char*word) @@ -74,8 +77,9 @@ int main(int argc, char*argv[]) { int opt; int rc; + const char*work_path = "ivl_vhdl_work"; - while ( (opt=getopt(argc, argv, "D:vV")) != EOF) switch (opt) { + while ( (opt=getopt(argc, argv, "D:vVw:")) != EOF) switch (opt) { case 'D': process_debug_token(optarg); @@ -96,8 +100,27 @@ int main(int argc, char*argv[]) fputs(NOTICE, stdout); break; + case 'w': + work_path = optarg; + break; } + if ( (rc = mkdir(work_path, 0777)) < 0 ) { + if (errno != EEXIST) { + fprintf(stderr, "Icarus Verilog VHDL unable to create work directory %s, errno=%d\n", work_path, errno); + return -1; + } + struct stat stat_buf; + rc = stat(work_path, &stat_buf); + + if (!S_ISDIR(stat_buf.st_mode)) { + fprintf(stderr, "Icarus Verilog VHDL work path `%s' is not a directory.\n", work_path); + return -1; + } + } + + library_set_work_path(work_path); + preload_global_types(); int errors = 0; diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 936464569..aa14ebab1 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -18,6 +18,7 @@ */ # include "package.h" +# include "entity.h" Package::Package(perm_string n, const ScopeBase&ref) : Scope(ref), name_(n) @@ -27,3 +28,16 @@ Package::Package(perm_string n, const ScopeBase&ref) Package::~Package() { } + +void Package::write_to_stream(ostream&fd) const +{ + fd << "package " << name_ << " is" << endl; + + for (map::const_iterator cur = components_.begin() + ; cur != components_.end() ; ++cur) { + + cur->second->write_to_stream(fd); + } + + fd << "end package " << name_ << ";" << endl; +} diff --git a/vhdlpp/package.h b/vhdlpp/package.h index a56e176d5..c648eea50 100644 --- a/vhdlpp/package.h +++ b/vhdlpp/package.h @@ -21,6 +21,7 @@ # include "scope.h" # include "LineInfo.h" +# include class Package : public Scope, public LineInfo { @@ -30,6 +31,9 @@ class Package : public Scope, public LineInfo { perm_string name() const { return name_; } + // This method writes a package header to a library file. + void write_to_stream(std::ostream&fd) const; + private: perm_string name_; }; diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index d9a5636db..4950927aa 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -36,6 +36,11 @@ class VType { VType() { } virtual ~VType() =0; + // This virtual method writes a VHDL-accurate representation + // of this type to the designated stream. This is used for + // writing parsed types to library files. + virtual void write_to_stream(std::ostream&fd) const; + virtual void show(std::ostream&) const; public: @@ -74,6 +79,7 @@ class VTypePrimitive : public VType { VTypePrimitive(type_t); ~VTypePrimitive(); + void write_to_stream(std::ostream&fd) const; void show(std::ostream&) const; void elaborate(decl_t&decl) const; @@ -116,6 +122,7 @@ class VTypeArray : public VType { VTypeArray(const VType*etype, const std::vector&r, bool signed_vector =false); ~VTypeArray(); + void write_to_stream(std::ostream&fd) const; void show(std::ostream&) const; void elaborate(decl_t&decl) const; diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc new file mode 100644 index 000000000..b1d5d5735 --- /dev/null +++ b/vhdlpp/vtype_stream.cc @@ -0,0 +1,58 @@ +/* + * 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 "vtype.h" +# include +# include + +using namespace std; + +void VType::write_to_stream(ostream&fd) const +{ + fd << "/* UNKNOWN TYPE: " << typeid(*this).name() << " */"; +} + +void VTypeArray::write_to_stream(ostream&fd) const +{ + fd << "array "; + if (ranges_.size() > 0) { + assert(ranges_.size() < 2); + fd << "(" << ranges_[0].msb() + << " downto " << ranges_[0].lsb() << ") "; + } + + fd << "of "; + etype_->write_to_stream(fd); +} + +void VTypePrimitive::write_to_stream(ostream&fd) const +{ + switch (type_) { + case INTEGER: + fd << "integer"; + break; + case STDLOGIC: + fd << "std_logic"; + break; + default: + assert(0); + fd << "/* PRIMITIVE: " << type_ << " */"; + break; + } +}