diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index 9742eb764..eee6094cd 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -59,8 +59,10 @@ 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 package.o scope.o sequential.o vsignal.o vtype.o vtype_elaborate.o \ +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 \ 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/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index fcd403ee5..d33ded0bc 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -20,6 +20,7 @@ # include "architec.h" # include "entity.h" # include "expression.h" +# include "sequential.h" # include # include @@ -45,7 +46,7 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc) { int errors = 0; - const ComponentBase*base = arc->find_component(cname_); + ComponentBase*base = arc->find_component(cname_); if (base == 0) { cerr << get_fileline() << ": error: No component declaration" << " for instance " << iname_ @@ -71,5 +72,12 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc) int ProcessStatement::elaborate(Entity*ent, Architecture*arc) { - return 0; + int errors = 0; + + for (list::iterator cur = statements_list_.begin() + ; cur != statements_list_.end() ; ++cur) { + errors += (*cur)->elaborate(ent, arc); + } + + return errors; } diff --git a/vhdlpp/entity.cc b/vhdlpp/entity.cc index cec05bc31..b9ccbff0a 100644 --- a/vhdlpp/entity.cc +++ b/vhdlpp/entity.cc @@ -20,6 +20,7 @@ # include "entity.h" # include "architec.h" +# include using namespace std; @@ -69,3 +70,10 @@ Architecture* Entity::add_architecture(Architecture*that) return arch_[that->get_name()] = that; } + +void Entity::set_declaration_l_value(perm_string nam, bool flag) +{ + map::iterator cur = declarations_.find(nam); + assert(cur != declarations_.end()); + cur->second.reg_flag = flag; +} diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 96780546b..04a37320b 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -33,6 +33,8 @@ class Architecture; class InterfacePort : public LineInfo { public: + InterfacePort() { mode = PORT_NONE; type=0; } + // Port direction from the source code. port_mode_t mode; // Name of the port from the source code @@ -92,7 +94,17 @@ class Entity : public ComponentBase { // returned pointer is the same as the passed pointer. Architecture* add_architecture(Architecture*); + // After the architecture is bound, elaboration calls this + // method to elaborate this entity. This method arranges for + // elaboration to hapen all the way through the architecture + // that is bound to this entity. int elaborate(); + + // During elaboration, it may be discovered that a port is + // used as an l-value in an assignment. This method tweaks the + // declaration to allow for that case. + void set_declaration_l_value(perm_string by_name, bool flag); + int emit(ostream&out); void dump(ostream&out, int indent = 0) const; diff --git a/vhdlpp/entity_emit.cc b/vhdlpp/entity_emit.cc index 2f6faa19f..0a4beb114 100644 --- a/vhdlpp/entity_emit.cc +++ b/vhdlpp/entity_emit.cc @@ -69,6 +69,8 @@ int Entity::emit(ostream&out) break; case PORT_OUT: out << "output "; + if (decl.reg_flag) + out << "reg "; if (decl.msb != decl.lsb) out << "[" << decl.msb << ":" << decl.lsb << "] "; diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 3ab4ce6cc..ae140a36e 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -40,6 +40,13 @@ class Expression : public LineInfo { Expression(); virtual ~Expression() =0; + // This virtual method handles the special case of elaborating + // an expression that is the l-value of a sequential variable + // assignment. This generates an error for most cases, but + // expressions that are valid l-values return 0 and set any + // flags needed to indicate their status as writable variables. + virtual int elaborate_lval(Entity*ent, Architecture*arc); + // The emit virtual method is called by architecture emit to // output the generated code for the expression. The derived // class fills in the details of what exactly happened. @@ -196,6 +203,7 @@ class ExpName : public Expression { ~ExpName(); public: // Base methods + int elaborate_lval(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, Architecture*arc); bool is_primary(void) const; bool evaluate(ScopeBase*scope, int64_t&val) const; @@ -213,6 +221,7 @@ class ExpNameALL : public ExpName { ExpNameALL() : ExpName(perm_string()) { } public: + int elaborate_lval(Entity*ent, Architecture*arc); void dump(ostream&out, int indent =0) const; }; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc new file mode 100644 index 000000000..9551a3770 --- /dev/null +++ b/vhdlpp/expression_elaborate.cc @@ -0,0 +1,62 @@ +/* + * 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 "expression.h" +# include "architec.h" +# include "entity.h" +# include + +using namespace std; + +int Expression::elaborate_lval(Entity*, Architecture*) +{ + cerr << get_fileline() << ": error: Expression is not a valie l-value." << endl; + return 1; +} + +int ExpName::elaborate_lval(Entity*ent, Architecture*arc) +{ + int errors = 0; + + if (const InterfacePort*cur = ent->find_port(name_)) { + if (cur->mode != PORT_OUT) { + cerr << get_fileline() << ": error: Assignment to " + "input port " << name_ << "." << endl; + return errors += 1; + } + + ent->set_declaration_l_value(name_, true); + return errors; + } + + Signal*sig = arc->find_signal(name_); + if (sig == 0) { + cerr << get_fileline() << ": error: Signal/variable " << name_ + << " not found in this context." << endl; + return errors + 1; + } + + return errors; +} + +int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc) +{ + return Expression::elaborate_lval(ent, arc); +} diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 4df3ed487..6f2da84b9 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -93,3 +93,12 @@ ComponentBase* Scope::find_component(perm_string by_name) else return cur->second; } + +Signal* Scope::find_signal(perm_string by_name) +{ + map::const_iterator cur = signals_.find(by_name); + if (cur == signals_.end()) + return 0; + else + return cur->second; +} diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index f6345ab2c..fd5e80272 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -64,6 +64,8 @@ class Scope : public ScopeBase { ComponentBase* find_component(perm_string by_name); + Signal* find_signal(perm_string by_name); + public: void dump_scope(ostream&out) const; diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 1a6fe9474..7ac6c428c 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -33,6 +33,7 @@ class SequentialStmt : public LineInfo { virtual ~SequentialStmt() =0; public: + virtual int elaborate(Entity*ent, Architecture*arc); virtual int emit(ostream&out, Entity*entity, Architecture*arc); virtual void dump(ostream&out, int indent) const; }; @@ -45,6 +46,7 @@ class IfSequential : public SequentialStmt { ~IfSequential(); public: + int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); void dump(ostream&out, int indent) const; @@ -60,6 +62,7 @@ class SignalSeqAssignment : public SequentialStmt { ~SignalSeqAssignment(); public: + int elaborate(Entity*ent, Architecture*arc); int emit(ostream&out, Entity*entity, Architecture*arc); void dump(ostream&out, int indent) const; diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc new file mode 100644 index 000000000..9515943ae --- /dev/null +++ b/vhdlpp/sequential_elaborate.cc @@ -0,0 +1,52 @@ +/* + * 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 "sequential.h" +# include "expression.h" + +int SequentialStmt::elaborate(Entity*, Architecture*) +{ + return 0; +} + +int IfSequential::elaborate(Entity*ent, Architecture*arc) +{ + int errors = 0; + + for (list::iterator cur = if_.begin() + ; cur != if_.end() ; ++cur) { + errors += (*cur)->elaborate(ent, arc); + } + + for (list::iterator cur = else_.begin() + ; cur != else_.end() ; ++cur) { + errors += (*cur)->elaborate(ent, arc); + } + + return errors; +} + +int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc) +{ + int errors = 0; + + errors += lval_->elaborate_lval(ent, arc); + + return errors; +} diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 9488a9ae6..d9a5636db 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -42,9 +42,10 @@ class VType { enum vtype_t { VNONE, VBOOL, VLOGIC }; struct decl_t { public: - decl_t() : signed_flag(false), type(VNONE), msb(0), lsb(0) { } + decl_t() : reg_flag(false), signed_flag(false), type(VNONE), msb(0), lsb(0) { } int emit(std::ostream&out, perm_string name) const; public: + bool reg_flag; bool signed_flag; vtype_t type; long msb, lsb; diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index 981e08bdd..482b523db 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -27,12 +27,14 @@ using namespace std; int VType::decl_t::emit(ostream&out, perm_string name) const { + const char*wire = reg_flag? "reg" : "wire"; + switch (type) { case VType::VNONE: out << "// N type for " << name << endl; break; case VType::VLOGIC: - out << "wire logic "; + out << wire<< " logic "; if (signed_flag) out << "signed "; if (msb != lsb) @@ -40,7 +42,7 @@ int VType::decl_t::emit(ostream&out, perm_string name) const out << name << ";" << endl; break; case VType::VBOOL: - out << "wire bool "; + out << wire << " bool "; if (signed_flag) out << "signed "; if (msb != lsb)