From 791adfab68dbfaeb206fc18fcc1305a94204e160 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 10 Apr 2011 09:42:22 -0700 Subject: [PATCH] Check ports match up in component instantiations. Make sure in a conponent instantiation that the instantiated component is really declared, and that the ports of the binding really do match the ports of the declared component. This requires that we create and save component declarations, and that components have methods for mapping the ports. --- vhdlpp/architec.cc | 9 +++++ vhdlpp/architec.h | 7 +++- vhdlpp/architec_elaborate.cc | 41 +++++++++++++++++++ vhdlpp/entity.cc | 10 +++++ vhdlpp/entity.h | 1 + vhdlpp/parse.y | 77 +++++++++++++++++++----------------- 6 files changed, 106 insertions(+), 39 deletions(-) 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