Support VHDL component instantiations with generics as Verilog parameters.

This commit is contained in:
Stephen Williams 2011-10-23 17:08:48 -07:00
parent eeeadea3ac
commit 2be682f8a5
5 changed files with 108 additions and 50 deletions

View File

@ -20,6 +20,8 @@
# include "architec.h"
# include "expression.h"
# include "parse_types.h"
// Need this for parse_errors?
# include "parse_api.h"
using namespace std;
@ -66,22 +68,45 @@ SignalAssignment::~SignalAssignment()
}
ComponentInstantiation::ComponentInstantiation(perm_string i, perm_string c,
list<named_expr_t*>*parms,
list<named_expr_t*>*ports)
: iname_(i), cname_(c)
{
while (! ports->empty()) {
typedef pair<map<perm_string,Expression*>::iterator,bool> insert_rc;
while (parms && ! parms->empty()) {
named_expr_t*cur = parms->front();
parms->pop_front();
insert_rc rc = generic_map_.insert(make_pair(cur->name(), cur->expr()));
if (! rc.second) {
cerr << "?:?: error: Duplicate map of generic " << cur->name()
<< " ignored." << endl;
parse_errors += 1;
}
}
while (ports && ! ports->empty()) {
named_expr_t*cur = ports->front();
ports->pop_front();
port_map_.insert(make_pair(cur->name(), cur->expr()));
insert_rc rc = port_map_.insert(make_pair(cur->name(), cur->expr()));
if (! rc.second) {
cerr << "?:?: error: Duplicate map of port " << cur->name()
<< " ignored." << endl;
parse_errors += 1;
}
}
}
ComponentInstantiation::~ComponentInstantiation()
{
for(multimap<perm_string, Expression*>::iterator it = port_map_.begin()
; it != port_map_.end(); ++it) {
delete it->second;
}
for (map<perm_string,Expression*>::iterator it = generic_map_.begin()
; it != generic_map_.end() ; ++it) {
delete it->second;
}
for (map<perm_string,Expression*>::iterator it = port_map_.begin()
; it != port_map_.end(); ++it) {
delete it->second;
}
}
ProcessStatement::ProcessStatement(perm_string iname,

View File

@ -111,6 +111,7 @@ class ComponentInstantiation : public Architecture::Statement {
public:
ComponentInstantiation(perm_string iname, perm_string cname,
std::list<named_expr_t*>*parms,
std::list<named_expr_t*>*ports);
~ComponentInstantiation();
@ -122,7 +123,8 @@ class ComponentInstantiation : public Architecture::Statement {
perm_string iname_;
perm_string cname_;
std::multimap<perm_string,Expression*> port_map_;
std::map<perm_string,Expression*> generic_map_;
std::map<perm_string,Expression*> port_map_;
};
class ProcessStatement : public Architecture::Statement {

View File

@ -54,12 +54,30 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
return 1;
}
for (map<perm_string,Expression*>::const_iterator cur = generic_map_.begin()
; cur != generic_map_.end() ; ++cur) {
// check if generic from component instantiation
// exists in the component declaration
const InterfacePort*iparm = base->find_generic(cur->first);
if (iparm == 0) {
cerr << get_fileline() << ": error: No generic " << cur->first
<< " in component " << cname_ << "." << endl;
errors += 1;
continue;
}
for (multimap<perm_string,Expression*>::const_iterator cur = port_map_.begin()
ExpName* tmp;
if (cur->second && (tmp = dynamic_cast<ExpName*>(cur->second)))
errors += tmp->elaborate_rval(ent, arc, iparm);
if (cur->second)
errors += cur->second->elaborate_expr(ent, arc, iparm->type);
}
for (map<perm_string,Expression*>::const_iterator cur = port_map_.begin()
; cur != port_map_.end() ; ++cur) {
/* check if a port from component instantiation
exists in the component declaration
*/
// check if a port from component instantiation
// exists in the component declaration
const InterfacePort*iport = base->find_port(cur->first);
if (iport == 0) {
cerr << get_fileline() << ": error: No port " << cur->first
@ -68,9 +86,9 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
continue;
}
ExpName* tmp;
if (cur->second && (tmp = dynamic_cast<ExpName*>(cur->second)))
errors += tmp->elaborate_rval(ent, arc, iport);
ExpName* tmp;
if (cur->second && (tmp = dynamic_cast<ExpName*>(cur->second)))
errors += tmp->elaborate_rval(ent, arc, iport);
/* It is possible for the port to be explicitly
unconnected. In that case, the Expression will be nil */
@ -78,15 +96,6 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc)
cur->second->elaborate_expr(ent, arc, iport->type);
}
//each formal (component's) port should be associated at most once
for(multimap<perm_string,Expression*>::const_iterator cur = port_map_.begin()
; cur != port_map_.end() ; ++cur)
if(port_map_.count(cur->first) != 1) {
//at least one port is associated twice or more
cerr << cur->second->get_fileline() << ": error: At least one port is associated"
<< " twice or more in a single component instantiation." << endl;
errors += 1;
}
return errors;
}

View File

@ -24,7 +24,7 @@
# include "vsignal.h"
# include <iostream>
# include <typeinfo>
# include <cassert>
# include <ivl_assert.h>
int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc)
{
@ -116,7 +116,7 @@ int SignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
{
int errors = 0;
assert(rval_.size() == 1);
ivl_assert(*this, rval_.size() == 1);
Expression*rval = rval_.front();
out << "// " << get_fileline() << endl;
@ -132,16 +132,32 @@ int SignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
{
const char*comma = "";
int errors = 0;
out << cname_ << " " << iname_ << "(";
const char*comma = "";
for (multimap<perm_string,Expression*>::iterator cur = port_map_.begin()
out << cname_;
if (generic_map_.size() > 0) {
out << " #(";
comma = "";
for (map<perm_string,Expression*>::iterator cur = generic_map_.begin()
; cur != generic_map_.end() ; ++cur) {
ivl_assert(*this, cur->second);
out << comma << ".\\" << cur->first << " (";
errors += cur->second->emit(out, ent, arc);
out << ")";
comma = ", ";
}
out << ")";
}
out << " \\" << iname_ << " (";
comma = "";
for (map<perm_string,Expression*>::iterator cur = port_map_.begin()
; cur != port_map_.end() ; ++cur) {
// Skip unconnected ports
if (cur->second == 0)
continue;
out << comma << "." << cur->first << "(";
out << comma << ".\\" << cur->first << " (";
errors += cur->second->emit(out, ent, arc);
out << ")";
comma = ", ";

View File

@ -256,6 +256,7 @@ const VType*parse_type_by_name(perm_string name)
%type <named_expr> association_element
%type <named_expr_list> association_list port_map_aspect port_map_aspect_opt
%type <named_expr_list> generic_map_aspect generic_map_aspect_opt
%type <vtype> subtype_indication type_definition
@ -366,11 +367,12 @@ association_list
;
binding_indication
: K_use entity_aspect_opt
port_map_aspect_opt
generic_map_aspect_opt
{ //TODO: do sth with generic map aspect
$$ = $2;
: K_use entity_aspect_opt port_map_aspect_opt generic_map_aspect_opt
{ $$ = $2;
if ($3) sorrymsg(@3, "Port map aspect not supported here. (binding_indication)\n");
if ($4) sorrymsg(@4, "Generic map aspect not supported here. (binding_indication)\n");
delete $3;
delete $4;
}
;
@ -524,22 +526,22 @@ component_configuration
component_declaration
: K_component IDENTIFIER K_is_opt
port_clause_opt
generic_clause_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());
if($8 && name != $8) {
errormsg(@8, "Identifier %s doesn't match component name %s.\n",
$8, name.str());
}
ComponentBase*comp = new ComponentBase(name);
if ($4) {
comp->set_interface(0, $4);
delete $4;
}
comp->set_interface($4, $5);
if ($4) delete $4;
if ($5) delete $5;
active_scope->bind_name(name, comp);
delete[]$2;
if ($7) delete[] $7;
if ($8) delete[] $8;
}
| K_component IDENTIFIER K_is_opt error K_end K_component identifier_opt ';'
@ -551,11 +553,12 @@ component_declaration
;
component_instantiation_statement
: IDENTIFIER ':' K_component_opt IDENTIFIER port_map_aspect_opt ';'
: IDENTIFIER ':' K_component_opt IDENTIFIER generic_map_aspect_opt port_map_aspect_opt ';'
{ perm_string iname = lex_strings.make($1);
perm_string cname = lex_strings.make($4);
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5);
delete $5;
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5, $6);
delete $5;
delete $6;
FILE_NAME(tmp, @1);
delete[]$1;
delete[]$4;
@ -958,14 +961,17 @@ generic_clause
;
generic_map_aspect_opt
: generic_map_aspect
|
: generic_map_aspect { $$ = $1; }
| { $$ = 0; }
;
generic_map_aspect
: K_generic K_map '(' association_list ')'
{
sorrymsg(@1, "Generic map aspect not yet supported.\n");
{ $$ = $4; }
| K_generic K_map '(' error ')'
{ errormsg(@4, "Error in association list for generic map.\n");
yyerrok;
$$ = 0;
}
;