diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index 78a6b5235..9727d34db 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -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(_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"; diff --git a/tgt-vhdl/state.cc b/tgt-vhdl/state.cc index 223975f47..7acab014c 100644 --- a/tgt-vhdl/state.cc +++ b/tgt-vhdl/state.cc @@ -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)); diff --git a/tgt-vhdl/state.hh b/tgt-vhdl/state.hh index 2b43ed359..3dda1056d 100644 --- a/tgt-vhdl/state.hh +++ b/tgt-vhdl/state.hh @@ -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();