diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index 4e51a4d1b..d52a703fc 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -59,7 +59,7 @@ LIBS = @LIBS@ @EXTRALIBS@ M = StringHeap.o LineInfo.o -O = main.o compiler.o entity.o entity_elaborate.o \ +O = main.o architec.o compiler.o entity.o entity_elaborate.o \ lexor.o lexor_keyword.o parse.o vhdlreal.o vhdlint.o $M all: dep vhdlpp@EXEEXT@ @@ -86,6 +86,10 @@ dep: vhdlpp@EXEEXT@: $O $(CXX) -o vhdlpp@EXEEXT@ $(LDFLAGS) $O $(LIBS) +%.o: $(srcdir)/../libmisc/%.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o + mv $*.d dep/$*.d + %.o: %.cc vhdlpp_config.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o mv $*.d dep/$*.d @@ -123,4 +127,4 @@ stamp-vhdlpp_config-h: $(srcdir)/vhdlpp_config.h.in ../config.status vhplpp_config.h: stamp-vhdlpp_config-h --include $(patsubst %.o, dep/%.d, $O) +-include $(patsubst %.o, dep/%.d, $O $M) diff --git a/vhdlpp/README.txt b/vhdlpp/README.txt new file mode 100644 index 000000000..0dc3def06 --- /dev/null +++ b/vhdlpp/README.txt @@ -0,0 +1,16 @@ + +vhdlpp COMMAND LINE FLAGS: + +-D + Debug flags. The token can be + + * yydebug | no-yydebug + + * entities= + +-V + Display version on stdout + +-v + Verbose: Display version on stderr, and enable verbose messages to + stderr. diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc new file mode 100644 index 000000000..cfce9a371 --- /dev/null +++ b/vhdlpp/architec.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 "architec.h" + +Architecture::Architecture(perm_string name) +: name_(name) +{ +} + +Architecture::~Architecture() +{ +} diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h new file mode 100644 index 000000000..0cfc41535 --- /dev/null +++ b/vhdlpp/architec.h @@ -0,0 +1,41 @@ +#ifndef __architec_H +#define __architec_H +/* + * Copyright (c) 2011Stephen 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 "StringHeap.h" +# include "LineInfo.h" + +class Architecture : public LineInfo { + + public: + Architecture(perm_string name); + ~Architecture(); + + perm_string get_name() const { return name_; } + + void dump(ostream&out, perm_string of_entity) const; + + private: + perm_string name_; + + private: // Not implemented +}; + +#endif diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc new file mode 100644 index 000000000..dabd13283 --- /dev/null +++ b/vhdlpp/debug.cc @@ -0,0 +1,83 @@ +/* + * 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 + * Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704. + */ + +# include "entity.h" +# include "architec.h" +# include +# include + +static ostream& operator << (ostream&out, port_mode_t that) +{ + switch (that) { + case PORT_NONE: + out << "NO-PORT"; + break; + case PORT_IN: + out << "IN"; + break; + case PORT_OUT: + out << "OUT"; + break; + default: + out << "PORT-????"; + break; + } + return out; +} + +void dump_design_entities(const char*path) +{ + ofstream file (path); + for (map::iterator cur = design_entities.begin() + ; cur != design_entities.end() ; ++cur) { + cur->second->dump(file); + } +} + +void Entity::dump(ostream&out) const +{ + out << "entity " << name_ + << " file=" << get_fileline() << endl; + if (ports.size() == 0) { + out << " No ports" << endl; + } else { + out << " PORTS:" << endl; + for (vector::const_iterator cur = ports.begin() + ; cur != ports.end() ; ++cur) { + InterfacePort*item = *cur; + out << setw(6) << "" << item->name + << " : " << item->mode + << ", type=" << item->type_name + << ", file=" << item->get_fileline() << endl; + } + } + + for (map::const_iterator cur = arch_.begin() + ; cur != arch_.end() ; ++cur) { + cur->second->dump(out, name_); + } +} + +void Architecture::dump(ostream&out, perm_string of_entity) const +{ + out << "architecture " << name_ + << " of entity " << of_entity + << " file=" << get_fileline() << endl; +} diff --git a/vhdlpp/entity.cc b/vhdlpp/entity.cc index 13841e677..a674b558a 100644 --- a/vhdlpp/entity.cc +++ b/vhdlpp/entity.cc @@ -19,55 +19,26 @@ */ # include "entity.h" -# include -# include +# include "architec.h" using namespace std; std::map design_entities; -static ostream& operator << (ostream&out, port_mode_t that) +Entity::Entity(perm_string name) +: name_(name) { - switch (that) { - case PORT_NONE: - out << "NO-PORT"; - break; - case PORT_IN: - out << "IN"; - break; - case PORT_OUT: - out << "OUT"; - break; - default: - out << "PORT-????"; - break; - } - return out; } -static void dump_design_entity(ostream&out, Entity*obj) +Entity::~Entity() { - out << "entity " << obj->name << " file=" << obj->get_fileline() << endl; - if (obj->ports.size() == 0) { - out << " No ports" << endl; - } else { - out << " PORTS:" << endl; - for (vector::iterator cur = obj->ports.begin() - ; cur != obj->ports.end() ; ++cur) { - InterfacePort*item = *cur; - out << setw(6) << "" << item->name - << " : " << item->mode - << ", type=" << item->type_name - << ", file=" << item->get_fileline() << endl; - } - } } -void dump_design_entities(const char*path) +Architecture* Entity::add_architecture(Architecture*that) { - ofstream file (path); - for (map::iterator cur = design_entities.begin() - ; cur != design_entities.end() ; ++cur) { - dump_design_entity(file, cur->second); + if (Architecture*tmp = arch_ [that->get_name()]) { + return tmp; } + + return arch_[that->get_name()] = that; } diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 1feb43fd2..5ab750fd5 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -26,6 +26,8 @@ typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t; +class Architecture; + class InterfacePort : public LineInfo { public: // Port direction from the source code. @@ -39,12 +41,31 @@ class InterfacePort : public LineInfo { class Entity : public LineInfo { public: + Entity(perm_string name); + ~Entity(); + + // Entities have names. + perm_string get_name() const { return name_; } + + // bind an architecture to the entity, and return the + // Architecture that was bound. If there was a previous + // architecture with the same name bound, then do not replace + // the architecture and instead return the old + // value. The caller can tell that the bind worked if the + // returned pointer is the same as the passed pointer. + Architecture* add_architecture(Architecture*); + int elaborate(); + void dump(ostream&out) const; + public: - perm_string name; std::vector ports; + private: + perm_string name_; + + std::maparch_; }; /* diff --git a/vhdlpp/entity_elaborate.cc b/vhdlpp/entity_elaborate.cc index 699cc732d..6a860ffc5 100644 --- a/vhdlpp/entity_elaborate.cc +++ b/vhdlpp/entity_elaborate.cc @@ -42,9 +42,9 @@ int Entity::elaborate() int errors = 0; if (verbose_flag) - cerr << "Elaborate entity " << name << "..." << endl; + cerr << "Elaborate entity " << name_ << "..." << endl; - cout << "module " << name; + cout << "module " << name_; // If there are ports, emit them. if (ports.size() > 0) { diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index d5f8de0e9..775298a83 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -24,7 +24,8 @@ # include "vhdlreal.h" # include "compiler.h" # include "parse_api.h" -# include +# include "parse_misc.h" +# include "architec.h" # include # include @@ -100,6 +101,12 @@ architecture_body K_of IDENTIFIER K_is K_begin architecture_statement_part K_end K_architecture_opt ';' + { Architecture*tmp = new Architecture(lex_strings.make($2)); + FILE_NAME(tmp, @1); + bind_architecture_to_entity($4, tmp); + delete[]$2; + delete[]$4; + } | K_architecture IDENTIFIER K_of IDENTIFIER K_is @@ -150,11 +157,8 @@ design_units /* As an entity is declared, add it to the map of design entities. */ entity_declaration : K_entity IDENTIFIER K_is entity_header K_end K_entity_opt ';' - { Entity*tmp = new Entity; + { Entity*tmp = new Entity(lex_strings.make($2)); FILE_NAME(tmp, @1); - // Store the name - tmp->name = lex_strings.make($2); - delete[]$2; // Transfer the ports std::list*ports = $4; while (ports->size() > 0) { @@ -163,15 +167,14 @@ entity_declaration } delete ports; // Save the entity in the entity map. - design_entities[tmp->name] = tmp; + design_entities[tmp->get_name()] = tmp; + delete[]$2; } | K_entity IDENTIFIER K_is entity_header K_end K_entity_opt IDENTIFIER ';' - { Entity*tmp = new Entity; + { Entity*tmp = new Entity(lex_strings.make($2)); FILE_NAME(tmp, @1); - // Store the name - tmp->name = lex_strings.make($2); - if(strcmp($2, $7) != 0) { - errormsg(@1, "Syntax error in entity clause. \n"); yyerrok; + if(tmp->get_name() != $7) { + errormsg(@1, "Syntax error in entity clause. \n"); } delete[]$2; @@ -184,7 +187,7 @@ entity_declaration } delete ports; // Save the entity in the entity map. - design_entities[tmp->name] = tmp; + design_entities[tmp->get_name()] = tmp; } ; diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc new file mode 100644 index 000000000..10b159af7 --- /dev/null +++ b/vhdlpp/parse_misc.cc @@ -0,0 +1,51 @@ +/* + * 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 + * Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704. + */ + +# include "parse_misc.h" +# include "parse_api.h" +# include "entity.h" +# include "architec.h" +# include "compiler.h" +# include + +using namespace std; + +void bind_architecture_to_entity(const char*ename, Architecture*arch) +{ + perm_string ekey = lex_strings.make(ename); + std::map::const_iterator idx = design_entities.find(ekey); + if (idx == design_entities.end()) { + cerr << arch->get_fileline() << ": error: No entity " << ekey + << " for architecture " << arch->get_name() + << "." << endl; + parse_errors += 1; + return; + } + + Architecture*old_arch = idx->second->add_architecture(arch); + if (old_arch != arch) { + cerr << arch->get_fileline() << ": error: " + << "Architecture " << arch->get_name() + << " for entity " << idx->second->get_name() + << " is already defined here: " << old_arch->get_fileline() << endl; + parse_errors += 1; + return; + } +} diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h new file mode 100644 index 000000000..9f2d0416d --- /dev/null +++ b/vhdlpp/parse_misc.h @@ -0,0 +1,26 @@ +#ifndef __parse_misc_H +#define __parse_misc_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 + */ + +class Architecture; + +extern void bind_architecture_to_entity(const char*ename, Architecture*arch); + +#endif