diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index f223e8b90..b576af3b7 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -28,7 +28,7 @@ using namespace std; Architecture::Architecture(perm_string name, const ActiveScope&ref, list&s) -: Scope(ref), name_(name) +: Scope(ref), name_(name), cur_component_(NULL) { statements_.splice(statements_.end(), s); } @@ -39,6 +39,34 @@ Architecture::~Architecture() ScopeBase::cleanup(); } +bool Architecture::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const +{ + if(Scope::find_constant(by_name, typ, exp)) + return true; + + // Check generics in components + if(cur_component_) { + std::map::const_iterator c = new_components_.find(cur_component_->component_name()); + if(c == new_components_.end()) + c = old_components_.find(cur_component_->component_name()); + + assert(c != old_components_.end()); + ComponentBase*base = c->second; + + const InterfacePort*generic = base->find_generic(by_name); + if(!generic) + return false; // apparently there is no such generic in the component + + Expression*e = cur_component_->find_generic_map(by_name); + + typ = generic->type; + exp = e ? e : generic->expr; + return true; + } + + return false; +} + void Architecture::push_genvar_type(perm_string gname, const VType*gtype) { genvar_type_t tmp; @@ -191,6 +219,17 @@ ComponentInstantiation::~ComponentInstantiation() } } +Expression*ComponentInstantiation::find_generic_map(perm_string by_name) const +{ + map::const_iterator p = generic_map_.find(by_name); + + if(p == generic_map_.end()) + return NULL; + + return p->second; +} + + ProcessStatement::ProcessStatement(perm_string iname, std::list*sensitivity_list, std::list*statements_list) diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 117038eab..491926568 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -25,7 +25,7 @@ # include # include -class ComponentBase; +class ComponentInstantiation; class Entity; class Expression; class ExpName; @@ -54,10 +54,6 @@ class Architecture : public Scope, public LineInfo { virtual int elaborate(Entity*ent, Architecture*arc); virtual int emit(ostream&out, Entity*ent, Architecture*arc); virtual void dump(ostream&out, int indent = 0) const; - - private: - - private: // Not implemented }; public: @@ -69,6 +65,10 @@ class Architecture : public Scope, public LineInfo { perm_string get_name() const { return name_; } + // Sets the currently processed component (to be able to reach its parameters). + void set_cur_component(ComponentInstantiation*component) { cur_component_ = component; } + bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const; + // Elaborate this architecture in the context of the given entity. int elaborate(Entity*entity); @@ -110,6 +110,9 @@ class Architecture : public Scope, public LineInfo { }; std::list genvar_emit_stack_; + // Currently processed component (or NULL if none). + ComponentInstantiation*cur_component_; + private: // Not implemented }; @@ -198,6 +201,12 @@ class ComponentInstantiation : public Architecture::Statement { virtual int emit(ostream&out, Entity*entity, Architecture*arc); virtual void dump(ostream&out, int indent =0) const; + // Returns the expression that initalizes a generic (or NULL if not found). + Expression*find_generic_map(perm_string by_name) const; + + inline perm_string instance_name() const { return iname_; } + inline perm_string component_name() const { return cname_; } + private: perm_string iname_; perm_string cname_; diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index bdbd206dd..9ab09bfa8 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -92,6 +92,8 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc) return 1; } + arc->set_cur_component(this); + for (map::const_iterator cur = generic_map_.begin() ; cur != generic_map_.end() ; ++cur) { // check if generic from component instantiation @@ -133,6 +135,8 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc) cur->second->elaborate_expr(ent, arc, iport->type); } + arc->set_cur_component(NULL); + return errors; } diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 93b9fe2b9..cf18cdd84 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -148,6 +148,8 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc) const char*comma = ""; int errors = 0; + arc->set_cur_component(this); + out << cname_; if (! generic_map_.empty()) { out << " #("; @@ -177,6 +179,8 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc) } out << ");" << endl; + arc->set_cur_component(NULL); + return errors; } diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 19c79b591..e4389caca 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -273,6 +273,9 @@ int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lva errors += 1; } + const VType*dummy_type; + Expression*dummy_expr; + if (const InterfacePort*cur = ent->find_port(name_)) { /* IEEE 1076-2008, p.80: * For a formal port IN, associated port should be IN, OUT, INOUT or BUFFER @@ -301,8 +304,11 @@ int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lva } else if (ent->find_generic(name_)) { /* OK */ + } else if (scope->find_constant(name_, dummy_type, dummy_expr)) { + /* OK */ + } else { - cerr << get_fileline() << ": error: No port or signal " << name_ + cerr << get_fileline() << ": error: No port, signal or constant " << name_ << " to be used as r-value." << endl; errors += 1; } diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 2d498c020..983c0ed6b 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -182,11 +182,10 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const return false; } - if(!scope) + if (!scope) return false; - bool rc = scope->find_constant(name_, type, exp); - if (rc == false) + if (!scope->find_constant(name_, type, exp)) return false; return exp->evaluate(scope, val); diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 5f1d4c33a..918121158 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -53,7 +53,7 @@ class ScopeBase { virtual ~ScopeBase() =0; const VType* find_type(perm_string by_name); - bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const; + virtual bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const; Signal* find_signal(perm_string by_name) const; Variable* find_variable(perm_string by_name) const; virtual const InterfacePort* find_param(perm_string by_name) const;