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:
parent
bc7ec04cab
commit
388c9c6747
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue