diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index c67a133f2..9236d6172 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -384,10 +384,28 @@ static void declare_logic(vhdl_arch *arch, ivl_scope_t scope) */ static string make_safe_name(ivl_signal_t sig) { - const char *base = ivl_signal_basename(sig); - if (base[0] == '_') - return string("VL") + base; + string base(ivl_signal_basename(sig)); + if (ivl_signal_local(sig)) + base = "Tmp" + base; + + if (base[0] == '_') + base = "Sig" + base; + + if (*base.rbegin() == '_') + base += "Sig"; + + // Can't have two consecutive underscores + size_t pos = base.find("__"); + while (pos != string::npos) { + base.replace(pos, 2, "_"); + pos = base.find("__"); + } + + // A signal name may not be the same as a component name + if (find_entity(base) != NULL) + base += "_Sig"; + // This is the complete list of VHDL reserved words const char *vhdl_reserved[] = { "abs", "access", "after", "alias", "all", "and", "architecture", @@ -407,14 +425,32 @@ static string make_safe_name(ivl_signal_t sig) }; for (const char **p = vhdl_reserved; *p != NULL; p++) { - if (strcasecmp(*p, base) == 0) { - return string("VL_") + base; + if (strcasecmp(*p, base.c_str()) == 0) { + return "Sig_" + base; break; } } return string(base); } +// Check if `name' differs from an existing name only in case and +// make it unique if it does. +static void avoid_name_collision(string& name, vhdl_scope* scope) +{ + if (scope->name_collides(name)) { + name += "_"; + ostringstream ss; + int i = 1; + do { + // Keep adding an extra number until we get a unique name + ss.str(""); + ss << name << i++; + } while (scope->name_collides(ss.str())); + + name = ss.str(); + } +} + /* * Declare all signals and ports for a scope. */ @@ -428,6 +464,8 @@ static void declare_signals(vhdl_entity *ent, ivl_scope_t scope) remember_signal(sig, ent->get_arch()->get_scope()); string name(make_safe_name(sig)); + avoid_name_collision(name, ent->get_arch()->get_scope()); + rename_signal(sig, name); vhdl_type *sig_type; @@ -977,7 +1015,11 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent) loc = inst_name.find(']', 0); if (loc != string::npos) - inst_name.erase(loc, 1); + inst_name.erase(loc, 1); + + // Make sure the name doesn't collide with anything we've + // already declared + avoid_name_collision(inst_name, parent_arch->get_scope()); vhdl_comp_inst *inst = new vhdl_comp_inst(inst_name.c_str(), ent->get_name().c_str()); diff --git a/tgt-vhdl/state.cc b/tgt-vhdl/state.cc index 7263873cc..97d99ac0f 100644 --- a/tgt-vhdl/state.cc +++ b/tgt-vhdl/state.cc @@ -149,6 +149,19 @@ struct cmp_ent_name { const string& name_; }; +// Find an entity given its name. +vhdl_entity* find_entity(const string& name) +{ + entity_list_t::const_iterator it + = find_if(g_entities.begin(), g_entities.end(), + cmp_ent_name(name)); + + if (it != g_entities.end()) + return *it; + else + return NULL; +} + // Find a VHDL entity given a Verilog module scope. The VHDL entity // name should be the same as the Verilog module type name. // Note that this will return NULL if no entity has been recorded @@ -157,14 +170,7 @@ vhdl_entity* find_entity(const ivl_scope_t scope) { assert(ivl_scope_type(scope) == IVL_SCT_MODULE); - entity_list_t::const_iterator it - = find_if(g_entities.begin(), g_entities.end(), - cmp_ent_name(ivl_scope_tname(scope))); - - if (it != g_entities.end()) - return *it; - else - return NULL; + return find_entity(ivl_scope_tname(scope)); } // Add an entity/architecture pair to the list of entities to emit. diff --git a/tgt-vhdl/state.hh b/tgt-vhdl/state.hh index 018af5b43..7edb3d812 100644 --- a/tgt-vhdl/state.hh +++ b/tgt-vhdl/state.hh @@ -39,7 +39,8 @@ 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); -vhdl_entity *find_entity(const ivl_scope_t scope); +vhdl_entity* find_entity(const 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(); diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index c642c07b9..23aa2c983 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -74,6 +74,16 @@ bool vhdl_scope::have_declared(const std::string &name) const return get_decl(name) != NULL; } +// True if `name' differs in all but case from another declaration +bool vhdl_scope::name_collides(const string& name) const +{ + const vhdl_decl* decl = get_decl(name); + if (decl) + return decl->get_name() != name; + else + return false; +} + bool vhdl_scope::contained_within(const vhdl_scope *other) const { if (this == other) diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 9f5bd8af2..36ce168cc 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -719,6 +719,7 @@ public: void add_forward_decl(vhdl_decl *decl); vhdl_decl *get_decl(const std::string &name) const; bool have_declared(const std::string &name) const; + bool name_collides(const string& name) const; bool contained_within(const vhdl_scope *other) const; vhdl_scope *get_parent() const;