diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 446766d72..19f83f7ec 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -37,6 +37,15 @@ Architecture::~Architecture() { } +const ComponentBase* Architecture::find_component(perm_string by_name) +{ + map::const_iterator cur = components_.find(by_name); + if (cur == components_.end()) + return 0; + else + return cur->second; +} + Architecture::Statement::Statement() { } diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 176bf0f05..f84f99ce2 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -47,6 +47,7 @@ class Architecture : public LineInfo { Statement(); virtual ~Statement() =0; + virtual int elaborate(Entity*ent, Architecture*arc); virtual int emit(ostream&out, Entity*ent, Architecture*arc); virtual void dump(ostream&out) const; @@ -64,6 +65,7 @@ class Architecture : public LineInfo { ~Architecture(); perm_string get_name() const { return name_; } + const ComponentBase* find_component(perm_string by_name); // Elaborate this architecture in the context of the given entity. int elaborate(Entity*entity); @@ -99,7 +101,7 @@ class SignalAssignment : public Architecture::Statement { SignalAssignment(ExpName*target, std::list&rval); ~SignalAssignment(); - int emit(ostream&out, Entity*entity, Architecture*arc); + virtual int emit(ostream&out, Entity*entity, Architecture*arc); virtual void dump(ostream&out) const; private: @@ -114,7 +116,8 @@ class ComponentInstantiation : public Architecture::Statement { std::list*ports); ~ComponentInstantiation(); - int emit(ostream&out, Entity*entity, Architecture*arc); + virtual int elaborate(Entity*ent, Architecture*arc); + virtual int emit(ostream&out, Entity*entity, Architecture*arc); virtual void dump(ostream&out) const; private: diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index c815d05ea..89e062051 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -24,6 +24,47 @@ # include int Architecture::elaborate(Entity*entity) +{ + int errors = 0; + + for (list::iterator cur = statements_.begin() + ; cur != statements_.end() ; ++cur) { + + errors += (*cur)->elaborate(entity, this); + } + + return errors; +} + +int Architecture::Statement::elaborate(Entity*, Architecture*) { return 0; } + +int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc) +{ + int errors = 0; + + const ComponentBase*base = arc->find_component(cname_); + if (base == 0) { + cerr << get_fileline() << ": error: No component declaration" + << " for instance " << iname_ + << " of " << cname_ << "." << endl; + return 1; + } + + map port_match; + + for (map::iterator cur = port_map_.begin() + ; cur != port_map_.end() ; ++cur) { + const InterfacePort*iport = base->find_port(cur->first); + if (iport == 0) { + cerr << get_fileline() << ": error: No port " << cur->first + << " in component " << cname_ << "." << endl; + errors += 1; + continue; + } + } + + return errors; +} diff --git a/vhdlpp/entity.cc b/vhdlpp/entity.cc index 8562fc4d0..cec05bc31 100644 --- a/vhdlpp/entity.cc +++ b/vhdlpp/entity.cc @@ -42,6 +42,16 @@ void ComponentBase::set_interface(std::list*ports) } } +const InterfacePort* ComponentBase::find_port(perm_string my_name) const +{ + for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) { + if (ports_[idx]->name == my_name) + return ports_[idx]; + } + + return 0; +} + Entity::Entity(perm_string name) : ComponentBase(name) { diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 691d6f008..44f91e815 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -54,6 +54,7 @@ class ComponentBase : public LineInfo { // Entities have names. perm_string get_name() const { return name_; } + const InterfacePort* find_port(perm_string by_name) const; // Declare the ports for the entity. The parser calls this // method with a list of interface elements that were parsed diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index f42e217c1..2547de0b7 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -286,22 +286,7 @@ block_declarative_item delete $2; } - | K_component IDENTIFIER K_is_opt - port_clause_opt - K_end K_component identifier_opt ';' - { perm_string name = lex_strings.make($2); - if($7) { - if (name != $7) - errormsg(@7, "Identifier %s doesn't match component name %s.\n", - $7, name.str()); - delete[] $7; - } - - ComponentBase*comp = new ComponentBase(name); - if ($4) comp->set_interface($4); - block_components[name] = comp; - delete[]$2; - } + | component_declaration /* Various error handling rules for block_declarative_item... */ @@ -310,13 +295,6 @@ block_declarative_item | error ';' { errormsg(@1, "Syntax error in block declarations.\n"); yyerrok; } - | K_component IDENTIFIER K_is_opt error K_end K_component identifier_opt ';' - { errormsg(@4, "Syntax error in component declaration.\n"); - delete[] $2; - if($7) { - delete[] $7; - } - yyerrok; } ; /* @@ -351,6 +329,31 @@ component_configuration } ; +component_declaration + : K_component IDENTIFIER K_is_opt + port_clause_opt + K_end K_component identifier_opt ';' + { perm_string name = lex_strings.make($2); + if($7 && name != $7) { + errormsg(@7, "Identifier %s doesn't match component name %s.\n", + $7, name.str()); + } + + ComponentBase*comp = new ComponentBase(name); + if ($4) comp->set_interface($4); + block_components[name] = comp; + delete[]$2; + if ($7) delete[] $7; + } + + | K_component IDENTIFIER K_is_opt error K_end K_component identifier_opt ';' + { errormsg(@4, "Syntax error in component declaration.\n"); + delete[] $2; + if($7) delete[] $7; + yyerrok; + } + ; + component_instantiation_statement : IDENTIFIER ':' K_component_opt IDENTIFIER port_map_aspect_opt ';' { perm_string iname = lex_strings.make($1); @@ -788,20 +791,20 @@ package_declaration : K_package IDENTIFIER K_is package_declarative_part_opt K_end K_package_opt identifier_opt ';' - { sorrymsg(@4, "Package declaration not supported yet.\n"); - if($7) { - if($2 != $7) { - errormsg(@1, "Syntax error in package clause. Closing name doesn't match.\n"); - yyerrok; + { perm_string name = lex_strings.make($2); + if($7 && name != $7) { + errormsg(@1, "Identifier %s doesn't match package name %s.\n", + $7, name.str()); } - delete $7; - } - delete $2; + delete[]$2; + if ($7) delete[]$7; + sorrymsg(@1, "Package declarations not supported yet.\n"); + block_components.clear(); } | K_package IDENTIFIER K_is error K_end K_package_opt identifier_opt ';' - { errormsg(@2, "Syntax error in package clause.\n"); - yyerrok; - } + { errormsg(@4, "Syntax error in package clause.\n"); + yyerrok; + } ; /* TODO: this list must be extended in the future @@ -819,11 +822,11 @@ package_body_declarative_part_opt | ; -/* TODO: this list is only a sketch - it must be extended in the future */ package_declarative_item - : use_clause + : component_declaration + | use_clause ; + package_declarative_items : package_declarative_items package_declarative_item | package_declarative_item