Handle generate scopes with signals in VHDL target

This uniques the name of each copy of a signal and adds
it to the containing VHDL entity.
This commit is contained in:
Nick Gasson 2009-08-26 15:49:26 +01:00 committed by Stephen Williams
parent bc7ec04cab
commit 388c9c6747
3 changed files with 64 additions and 35 deletions

View File

@ -472,12 +472,50 @@ static void avoid_name_collision(string& name, vhdl_scope* scope)
}
}
// Concatenate the expanded genvar values together to make a unique
// instance name
// This isn't ideal: it would be better to replace the Verilog
// generate with an equivalent VHDL generate, but this isn't possible
// with the current API
static string genvar_unique_suffix(ivl_scope_t scope)
{
ostringstream suffix;
while (scope && ivl_scope_type(scope) == IVL_SCT_GENERATE) {
for (unsigned i = 0; i < ivl_scope_params(scope); i++) {
ivl_parameter_t param = ivl_scope_param(scope, i);
ivl_expr_t e = ivl_parameter_expr(param);
if (ivl_expr_type(e) == IVL_EX_NUMBER) {
vhdl_expr* value = translate_expr(e);
assert(value);
value = value->cast(vhdl_type::integer());
suffix << "_" << ivl_parameter_basename(param);
value->emit(suffix, 0);
delete value;
}
else {
error("Only numeric genvars supported at the moment");
return "_ERROR"; // Never used
}
}
scope = ivl_scope_parent(scope);
}
return suffix.str();
}
// Declare a single signal in a scope
static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig)
static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
ivl_scope_t scope)
{
remember_signal(sig, ent->get_arch()->get_scope());
string name(make_safe_name(sig));
name += genvar_unique_suffix(scope);
avoid_name_collision(name, ent->get_arch()->get_scope());
rename_signal(sig, name);
@ -586,14 +624,14 @@ static void declare_signals(vhdl_entity *ent, ivl_scope_t scope)
ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) != IVL_SIP_NONE)
declare_one_signal(ent, sig);
declare_one_signal(ent, sig, scope);
}
for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
declare_one_signal(ent, sig);
declare_one_signal(ent, sig, scope);
}
}
@ -898,6 +936,20 @@ static int draw_all_signals(ivl_scope_t scope, void *_parent)
declare_signals(ent, scope);
}
else if (ivl_scope_type(scope) == IVL_SCT_GENERATE) {
// Because generate scopes don't appear in the
// output VHDL all their signals are added to the
// containing entity (after being uniqued)
ivl_scope_t parent = ivl_scope_parent(scope);
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
parent = ivl_scope_parent(scope);
vhdl_entity* ent = find_entity(parent);
assert(ent);
declare_signals(ent, scope);
}
return ivl_scope_children(scope, draw_all_signals, scope);
}
@ -1030,36 +1082,8 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
// Skip over any containing generate scopes
// Concatenate the expanded genvar values together to
// make a unique instance name
// This isn't ideal: it would be better to replace the
// Verilog generate with an equivalent VHDL generate, but
// this isn't possible with the current API
ostringstream suffix;
while (ivl_scope_type(parent) == IVL_SCT_GENERATE) {
for (unsigned i = 0; i < ivl_scope_params(parent); i++) {
ivl_parameter_t param = ivl_scope_param(parent, i);
ivl_expr_t e = ivl_parameter_expr(param);
if (ivl_expr_type(e) == IVL_EX_NUMBER) {
vhdl_expr* value = translate_expr(e);
assert(value);
value = value->cast(vhdl_type::integer());
suffix << "_" << ivl_parameter_basename(param);
value->emit(suffix, 0);
delete value;
}
else {
error("Only numeric genvars supported at the moment");
return 1;
}
}
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
parent = ivl_scope_parent(parent);
}
if (!is_default_scope_instance(parent))
return 0; // Not generating code for the parent instance so
@ -1082,7 +1106,8 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
}
// And an instantiation statement
string inst_name(ivl_scope_basename(scope) + suffix.str());
string inst_name(ivl_scope_basename(scope));
inst_name += genvar_unique_suffix(ivl_scope_parent(scope));
if (inst_name == ent->get_name() || parent_scope->have_declared(inst_name)) {
// Cannot have instance name the same as type in VHDL
inst_name += "_Inst";

View File

@ -170,8 +170,12 @@ vhdl_entity* find_entity(const string& name)
// name should be the same as the Verilog module type name.
// Note that this will return NULL if no entity has been recorded
// for this scope type.
vhdl_entity* find_entity(const ivl_scope_t scope)
vhdl_entity* find_entity(ivl_scope_t scope)
{
// Skip over generate scopes
while (ivl_scope_type(scope) == IVL_SCT_GENERATE)
scope = ivl_scope_parent(scope);
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope));

View File

@ -39,7 +39,7 @@ ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope)
// Manage the set of VHDL entities
void remember_entity(vhdl_entity *ent, ivl_scope_t scope);
vhdl_entity* find_entity(const ivl_scope_t scope);
vhdl_entity* find_entity(ivl_scope_t scope);
vhdl_entity* find_entity(const std::string& name);
void emit_all_entities(std::ostream& os, int max_depth);
void free_all_vhdl_objects();