diff --git a/tgt-vhdl/process.cc b/tgt-vhdl/process.cc index d6f310e50..c5136e7fd 100644 --- a/tgt-vhdl/process.cc +++ b/tgt-vhdl/process.cc @@ -24,13 +24,13 @@ #include #include #include -#include +#include /* * TODO: Explanation here. */ -typedef std::set string_set_t; -static string_set_t g_assign_vars; +typedef std::map var_temp_set_t; +static var_temp_set_t g_assign_vars; void blocking_assign_to(vhdl_process *proc, ivl_signal_t sig) { @@ -51,10 +51,39 @@ void blocking_assign_to(vhdl_process *proc, ivl_signal_t sig) proc->add_decl(new vhdl_var_decl(var.c_str(), type)); rename_signal(sig, var); - g_assign_vars.insert(var); + g_assign_vars[var] = sig; } } +/* + * Assign all _Var variables to the corresponding signals. This makes + * the new values visible outside the current process. This should be + * called before any `wait' statement or the end of the process. + */ +void draw_blocking_assigns(vhdl_process *proc) +{ + var_temp_set_t::const_iterator it; + for (it = g_assign_vars.begin(); it != g_assign_vars.end(); ++it) { + std::string stripped(strip_var((*it).first)); + + vhdl_decl *decl = proc->get_decl(stripped); + assert(decl); + vhdl_type *type = new vhdl_type(*decl->get_type()); + + vhdl_var_ref *lhs = new vhdl_var_ref(stripped.c_str(), NULL); + vhdl_expr *rhs = new vhdl_var_ref((*it).first.c_str(), type); + + // TODO: I'm not sure this will work properly if, e.g., the delay + // is inside a `if' statement + proc->get_container()->add_stmt(new vhdl_nbassign_stmt(lhs, rhs)); + + // Undo the renaming (since the temporary is no longer needed) + rename_signal((*it).second, stripped); + } + + g_assign_vars.clear(); +} + /* * Remove _Var from the end of a string, if it is present. */ @@ -111,6 +140,9 @@ static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc) ss << ivl_scope_tname(scope); vhdl_proc->set_comment(ss.str()); + // Output any remaning blocking assignments + draw_blocking_assigns(vhdl_proc); + return 0; } diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 6d7b254bb..0f410d667 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -311,6 +311,10 @@ static int draw_delay(vhdl_process *proc, stmt_container *container, draw_nbassign(proc, container, sub_stmt, time); } else { + // All blocking assignments need to be made visible + // at this point + draw_blocking_assigns(proc); + vhdl_wait_stmt *wait = new vhdl_wait_stmt(VHDL_WAIT_FOR_NS, time); container->add_stmt(wait); diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index befdbd2eb..cfad1dc13 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -33,7 +33,7 @@ const std::string &get_renamed_signal(ivl_signal_t sig); void blocking_assign_to(vhdl_process *proc, ivl_signal_t sig); std::string strip_var(const std::string &str); - +void draw_blocking_assigns(vhdl_process *proc); #endif /* #ifndef INC_VHDL_TARGET_H */