diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index a22622df0..acf9eafad 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -22,6 +22,7 @@ # include "parse_types.h" // Need this for parse_errors? # include "parse_api.h" +# include using namespace std; @@ -38,6 +39,54 @@ Architecture::~Architecture() ScopeBase::cleanup(); } +void Architecture::push_genvar_type(perm_string gname, const VType*gtype) +{ + genvar_type_t tmp; + tmp.name = gname; + tmp.vtype = gtype; + genvar_type_stack_.push_back(tmp); +} + +void Architecture::pop_genvar_type(void) +{ + assert(! genvar_type_stack_.empty()); + genvar_type_stack_.pop_back(); +} + +const VType* Architecture::probe_genvar_type(perm_string gname) +{ + for (std::list::reverse_iterator cur = genvar_type_stack_.rbegin() + ; cur != genvar_type_stack_.rend() ; ++cur) { + if (cur->name == gname) + return cur->vtype; + } + return 0; +} + +void Architecture::push_genvar_emit(perm_string gname, const GenerateStatement*gen) +{ + genvar_emit_t tmp; + tmp.name = gname; + tmp.gen = gen; + genvar_emit_stack_.push_back(tmp); +} + +void Architecture::pop_genvar_emit(void) +{ + assert(! genvar_emit_stack_.empty()); + genvar_emit_stack_.pop_back(); +} + +const GenerateStatement* Architecture::probe_genvar_emit(perm_string gname) +{ + for (std::list::reverse_iterator cur = genvar_emit_stack_.rbegin() + ; cur != genvar_emit_stack_.rend() ; ++cur) { + if (cur->name == gname) + return cur->gen; + } + return 0; +} + Architecture::Statement::Statement() { } diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 4b2baae14..33224f485 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -29,6 +29,7 @@ class ComponentBase; class Entity; class Expression; class ExpName; +class GenerateStatement; class SequentialStmt; class Signal; class named_expr_t; @@ -71,6 +72,18 @@ class Architecture : public Scope, public LineInfo { // Elaborate this architecture in the context of the given entity. int elaborate(Entity*entity); + // These methods are used while in the scope of a generate + // block to mark that a name is a genvar at this point. + const VType* probe_genvar_type(perm_string); + void push_genvar_type(perm_string gname, const VType*gtype); + void pop_genvar_type(void); + + // These methods are used during EMIT to check for names that + // are genvar names. + const GenerateStatement* probe_genvar_emit(perm_string); + void push_genvar_emit(perm_string gname, const GenerateStatement*); + void pop_genvar_emit(void); + // Emit this architecture to the given out file in the context // of the specified entity. This method is used by the // elaborate code to display generated code to the specified @@ -85,6 +98,18 @@ class Architecture : public Scope, public LineInfo { // Concurrent statements local to this architecture std::list statements_; + struct genvar_type_t { + perm_string name; + const VType*vtype; + }; + std::list genvar_type_stack_; + + struct genvar_emit_t { + perm_string name; + const GenerateStatement*gen; + }; + std::list genvar_emit_stack_; + private: // Not implemented }; @@ -98,9 +123,9 @@ class GenerateStatement : public Architecture::Statement { GenerateStatement(perm_string gname, std::list&s); ~GenerateStatement(); - protected: - inline perm_string get_name() { return name_; } + inline perm_string get_name() const { return name_; } + protected: int elaborate_statements(Entity*ent, Architecture*arc); int emit_statements(ostream&out, Entity*ent, Architecture*arc); void dump_statements(ostream&out, int indent) const; diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index c496101fc..0e85dd05d 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -133,7 +133,9 @@ int GenerateStatement::elaborate_statements(Entity*ent, Architecture*arc) int ForGenerate::elaborate(Entity*ent, Architecture*arc) { int errors = 0; + arc->push_genvar_type(genvar_, lsb_->probe_type(ent, arc)); errors += elaborate_statements(ent, arc); + arc->pop_genvar_type(); return errors; } diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index a7e797f9f..0f517294b 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -183,16 +183,19 @@ int GenerateStatement::emit_statements(ostream&out, Entity*ent, Architecture*arc int ForGenerate::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; - out << "genvar \\" << genvar_ << " ;" << endl; - out << "for (\\" << genvar_ << " = "; + out << "genvar \\" << get_name() << ":" << genvar_ << " ;" << endl; + out << "for (\\" << get_name() << ":" << genvar_ << " = "; errors += lsb_->emit(out, ent, arc); - out << "; \\" << genvar_ << " <= "; + out << "; \\" << get_name() << ":" << genvar_ << " <= "; errors += msb_->emit(out, ent, arc); - out << "; \\" << genvar_ << " = \\" << genvar_ << " + 1)" + out << "; \\" << get_name() << ":" << genvar_ << " = \\" << get_name() << ":" << genvar_ << " + 1)" << " begin : \\" << get_name() << endl; + arc->push_genvar_emit(genvar_, this); + errors += emit_statements(out, ent, arc); + arc->pop_genvar_emit(); out << "end" << endl; return errors; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 465e3b743..ffc2301b0 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -700,6 +700,10 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const return 0; } + while (const VTypeDef*def = dynamic_cast (prefix_type)) { + prefix_type = def->peek_definition(); + } + // If the prefix type is a record, then the current name is // the name of a member. if (const VTypeRecord*pref_record = dynamic_cast (prefix_type)) { @@ -745,6 +749,10 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const if (arc->find_constant(name_, ctype, cval)) return ctype; + if (const VType*gtype = arc->probe_genvar_type(name_)) { + return gtype; + } + cerr << get_fileline() << ": error: Signal/variable " << name_ << " not found in this context." << endl; return 0; diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index c4ba78ed3..c0d22210b 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -628,7 +628,12 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc) errors += prefix_->emit_as_prefix_(out, ent, arc); } - out << "\\" << name_ << " "; + const GenerateStatement*gs = 0; + if (arc && (gs = arc->probe_genvar_emit(name_))) + out << "\\" << gs->get_name() << ":" << name_ << " "; + else + out << "\\" << name_ << " "; + if (index_) { out << "["; errors += index_->emit(out, ent, arc);