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.
This commit is contained in:
Stephen Williams 2011-04-10 09:42:22 -07:00
parent 71743c687a
commit 791adfab68
6 changed files with 106 additions and 39 deletions

View File

@ -37,6 +37,15 @@ Architecture::~Architecture()
{
}
const ComponentBase* Architecture::find_component(perm_string by_name)
{
map<perm_string,ComponentBase*>::const_iterator cur = components_.find(by_name);
if (cur == components_.end())
return 0;
else
return cur->second;
}
Architecture::Statement::Statement()
{
}

View File

@ -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<Expression*>&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<named_expr_t*>*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:

View File

@ -24,6 +24,47 @@
# include <cassert>
int Architecture::elaborate(Entity*entity)
{
int errors = 0;
for (list<Architecture::Statement*>::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<perm_string,const InterfacePort*> port_match;
for (map<perm_string,Expression*>::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;
}

View File

@ -42,6 +42,16 @@ void ComponentBase::set_interface(std::list<InterfacePort*>*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)
{

View File

@ -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

View File

@ -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