diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index 049b6d0e3..bdc9723cc 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -46,7 +46,7 @@ static vhdl_expr *translate_signal(ivl_expr_t e) const char *renamed = get_renamed_signal(sig).c_str(); - const vhdl_decl *decl = ent->get_arch()->get_decl(renamed); + const vhdl_decl *decl = ent->get_arch()->get_decl(strip_var(renamed)); assert(decl); vhdl_type *type = new vhdl_type(*decl->get_type()); diff --git a/tgt-vhdl/process.cc b/tgt-vhdl/process.cc index 1342f1e53..d6f310e50 100644 --- a/tgt-vhdl/process.cc +++ b/tgt-vhdl/process.cc @@ -32,11 +32,40 @@ typedef std::set string_set_t; static string_set_t g_assign_vars; -void blocking_assign_to(vhdl_process *proc, std::string var) +void blocking_assign_to(vhdl_process *proc, ivl_signal_t sig) { + std::string var(get_renamed_signal(sig)); + std::cout << "blocking_assign_to " << var << std::endl; + + if (g_assign_vars.find(var) == g_assign_vars.end()) { + // This is the first time a non-blocking assignment + // has been made to this signal: create a variable + // to shadow it. + + vhdl_decl *decl = proc->get_parent()->get_decl(var); + assert(decl); + vhdl_type *type = new vhdl_type(*decl->get_type()); + + var += "_Var"; + proc->add_decl(new vhdl_var_decl(var.c_str(), type)); + + rename_signal(sig, var); + g_assign_vars.insert(var); + } } +/* + * Remove _Var from the end of a string, if it is present. + */ +std::string strip_var(const std::string &str) +{ + std::string result(str); + size_t pos = result.find("_Var"); + if (pos != std::string::npos) + result.erase(pos, 4); + return result; +} /* * Convert a Verilog process to VHDL and add it to the architecture diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 7a8a6075c..6d7b254bb 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -250,8 +250,6 @@ static int draw_assign(vhdl_process *proc, stmt_container *container, if ((sig = ivl_lval_sig(lval))) { const std::string &signame = get_renamed_signal(sig); - blocking_assign_to(proc, signame); - vhdl_decl *decl = proc->get_decl(signame); assert(decl); @@ -266,8 +264,13 @@ static int draw_assign(vhdl_process *proc, stmt_container *container, decl->set_initial(rhs); } else { + blocking_assign_to(proc, sig); + + // The signal may have been renamed by the above call + const std::string &renamed = get_renamed_signal(sig); + // The type here can be null as it is never actually needed - vhdl_var_ref *lval_ref = new vhdl_var_ref(signame.c_str(), NULL); + vhdl_var_ref *lval_ref = new vhdl_var_ref(renamed.c_str(), NULL); vhdl_assign_stmt *assign = new vhdl_assign_stmt(lval_ref, rhs); container->add_stmt(assign); diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index 785b01000..befdbd2eb 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -31,7 +31,8 @@ void rename_signal(ivl_signal_t sig, const std::string &renamed); const vhdl_entity *find_entity_for_signal(ivl_signal_t sig); const std::string &get_renamed_signal(ivl_signal_t sig); -void blocking_assign_to(vhdl_process *proc, std::string var); +void blocking_assign_to(vhdl_process *proc, ivl_signal_t sig); +std::string strip_var(const std::string &str); #endif /* #ifndef INC_VHDL_TARGET_H */