From d9bf96d8fa09860509cdcbdef68a784567ff4837 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 11 Sep 2010 12:17:06 +0100 Subject: [PATCH] Basic parameter support in VHDL target This is a fix for pr2555831. A separate entity/architecture pair is generated for each module that is instantiated with a unique parameter combination. --- tgt-vhdl/scope.cc | 6 ++-- tgt-vhdl/state.cc | 75 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index 423fe505d..bb932e374 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -933,7 +933,7 @@ static void create_skeleton_entity_for(ivl_scope_t scope, int depth) break; case IVL_EX_NUMBER: - ss << ivl_expr_value(value); + ss << ivl_expr_uvalue(value); break; default: @@ -954,7 +954,7 @@ static void create_skeleton_entity_for(ivl_scope_t scope, int depth) extern "C" int draw_skeleton_scope(ivl_scope_t scope, void *_unused) { static int depth = 0; - + if (seen_this_scope_type(scope)) return 0; // Already generated a skeleton for this scope type @@ -1071,7 +1071,7 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent) vhdl_var_ref *ref = nexus_to_var_ref(arch_scope, nex); ent->get_arch()->add_stmt - (new vhdl_cassign_stmt(ref, priv->const_driver)); + (new vhdl_cassign_stmt(ref, priv->const_driver)); priv->const_driver = NULL; } diff --git a/tgt-vhdl/state.cc b/tgt-vhdl/state.cc index 0ced93f27..e03c201e1 100644 --- a/tgt-vhdl/state.cc +++ b/tgt-vhdl/state.cc @@ -25,8 +25,9 @@ #include #include #include -#include +#include #include +#include using namespace std; @@ -67,7 +68,7 @@ struct signal_defn_t { static entity_list_t g_entities; // Store the mapping of ivl scope names to entity names -typedef map scope_name_map_t; +typedef map scope_name_map_t; static scope_name_map_t g_scope_names; typedef std::map signal_defn_map_t; @@ -77,10 +78,9 @@ static vhdl_entity *g_active_entity = NULL; // Set of scopes that are treated as the default examples of // that type. Any other scopes of the same type are ignored. -typedef set default_scopes_t; +typedef vector default_scopes_t; static default_scopes_t g_default_scopes; - // True if signal `sig' has already been encountered by the code // generator. This means we have already assigned it to a VHDL code // object and possibly renamed it. @@ -179,18 +179,31 @@ vhdl_entity* find_entity(ivl_scope_t scope) assert(ivl_scope_type(scope) == IVL_SCT_MODULE); - scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope)); - if (it != g_scope_names.end()) - return find_entity((*it).second); - else + if (is_default_scope_instance(scope)) { + scope_name_map_t::iterator it = g_scope_names.find(scope); + if (it != g_scope_names.end()) + return find_entity((*it).second); + else + return NULL; + } + else { + const char *tname = ivl_scope_tname(scope); + + for (scope_name_map_t::iterator it = g_scope_names.begin(); + it != g_scope_names.end(); ++it) { + if (strcmp(tname, ivl_scope_tname((*it).first)) == 0) + return find_entity((*it).second); + } + return NULL; + } } // Add an entity/architecture pair to the list of entities to emit. void remember_entity(vhdl_entity* ent, ivl_scope_t scope) { g_entities.push_back(ent); - g_scope_names[ivl_scope_tname(scope)] = ent->get_name(); + g_scope_names[scope] = ent->get_name(); } // Print all VHDL entities, in order, to the specified output stream. @@ -228,12 +241,52 @@ void set_active_entity(vhdl_entity *ent) { g_active_entity = ent; } + /* * True if two scopes have the same type name. */ static bool same_scope_type_name(ivl_scope_t a, ivl_scope_t b) { - return strcmp(ivl_scope_tname(a), ivl_scope_tname(b)) == 0; + if (strcmp(ivl_scope_tname(a), ivl_scope_tname(b)) != 0) + return false; + + unsigned nparams_a = ivl_scope_params(a); + unsigned nparams_b = ivl_scope_params(b); + + if (nparams_a != nparams_b) + return false; + + for (unsigned i = 0; i < nparams_a; i++) { + ivl_parameter_t param_a = ivl_scope_param(a, i); + ivl_parameter_t param_b = ivl_scope_param(b, i); + + if (strcmp(ivl_parameter_basename(param_a), + ivl_parameter_basename(param_b)) != 0) + return false; + + ivl_expr_t value_a = ivl_parameter_expr(param_a); + ivl_expr_t value_b = ivl_parameter_expr(param_b); + + if (ivl_expr_type(value_a) != ivl_expr_type(value_b)) + return false; + + switch (ivl_expr_type(value_a)) { + case IVL_EX_STRING: + if (strcmp(ivl_expr_string(value_a), ivl_expr_string(value_b)) != 0) + return false; + break; + + case IVL_EX_NUMBER: + if (ivl_expr_uvalue(value_a) != ivl_expr_uvalue(value_b)) + return false; + break; + + default: + assert(false); + } + } + + return true; } /* @@ -246,7 +299,7 @@ bool seen_this_scope_type(ivl_scope_t s) if (find_if(g_default_scopes.begin(), g_default_scopes.end(), bind1st(ptr_fun(same_scope_type_name), s)) == g_default_scopes.end()) { - g_default_scopes.insert(s); + g_default_scopes.push_back(s); return false; } else