diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index 28c8c7921..dc69cd687 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -58,7 +58,7 @@ static vhdl_var_ref *translate_signal(ivl_expr_t e) const char *renamed = get_renamed_signal(sig).c_str(); - const vhdl_decl *decl = scope->get_decl(strip_var(renamed)); + const vhdl_decl *decl = scope->get_decl(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 73cc51e92..57326a11e 100644 --- a/tgt-vhdl/process.cc +++ b/tgt-vhdl/process.cc @@ -24,120 +24,6 @@ #include #include #include -#include - -/* - * Implementing blocking assignment is a little tricky since - * the semantics are a little different to VHDL: - * - * In Verilog a blocking assignment (=) can be used anywhere - * non-blocking assignment (<=) can be. In VHDL blocking - * assignment (:=) can only be used with variables, and - * non-blocking assignment (<=) can only be used with signals. - * All Verilog variables are translated into signals in the - * VHDL architecture. This means we cannot use the VHDL := - * operator directly. Furthermore, VHDL variables can only - * be declared within processes, so it wouldn't help to - * make all Verilog variables VHDL variables. - * - * The solution is to generate a VHDL variable in a process - * whenever a blocking assignment is made to a signal. The - * assignment is made to this variable instead, and - * g_assign_vars below remembers the temporary variables - * that have been generated. Any subsequent blocking assignments - * are made to the same variable. At either the end of the - * process or a `wait' statement, the temporaries are assigned - * back to the signals, and the temporaries are forgotten. - * - * For example: - * - * initial begin - * a = 5; - * b = a + 3; - * end - * - * Is translated to: - * - * process is - * variable a_Var : Some_Type; - * variable b_Var : Some_Type; - * begin - * a_Var := 5; - * b_Var := a_Var + 3; - * a <= a_Var; - * b <= b_Var; - * end process; - */ -typedef std::map var_temp_set_t; -static var_temp_set_t g_assign_vars; - -/* - * Called whenever a blocking assignment is made to sig. - */ -void blocking_assign_to(vhdl_procedural *proc, ivl_signal_t sig) -{ - std::string var(get_renamed_signal(sig)); - std::string tmpname(var + "_Var"); - - 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. - if (!proc->get_scope()->have_declared(tmpname)) { - vhdl_decl *decl = proc->get_scope()->get_decl(var); - assert(decl); - vhdl_type *type = new vhdl_type(*decl->get_type()); - - proc->get_scope()->add_decl(new vhdl_var_decl(tmpname.c_str(), type)); - } - - rename_signal(sig, tmpname); - g_assign_vars[tmpname] = 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_procedural *proc, stmt_container *container) -{ - 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_scope()->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); - - container->add_stmt(new vhdl_nbassign_stmt(lhs, rhs)); - - // Undo the renaming (since the temporary is no longer needed) - rename_signal((*it).second, stripped); - } - - // If this this wait is within e.g. an `if' statement then - // we cannot correctly clear the variables list here (since - // they might not be assigned on another path) - if (container == proc->get_container()) - g_assign_vars.clear(); -} - -/* - * 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 @@ -162,10 +48,6 @@ static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc) if (rc != 0) return rc; - // Output any remaning blocking assignments - draw_blocking_assigns(vhdl_proc, vhdl_proc->get_container()); - g_assign_vars.clear(); - // Initial processes are translated to VHDL processes with // no sensitivity list and and indefinite wait statement at // the end diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 6025d60f8..a7ef4150a 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -102,9 +102,9 @@ static int draw_noop(vhdl_procedural *proc, stmt_container *container, return 0; } -static vhdl_expr *translate_assign_rhs(ivl_signal_t sig, vhdl_scope *scope, - ivl_expr_t e, vhdl_expr *base, - int lval_width) +static vhdl_expr *make_assign_rhs(ivl_signal_t sig, vhdl_scope *scope, + ivl_expr_t e, vhdl_expr *base, + int lval_width) { string signame(get_renamed_signal(sig)); @@ -182,11 +182,11 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container, // Expand ternary expressions into an if statement vhdl_expr *test = translate_expr(ivl_expr_oper1(rval)); vhdl_expr *true_part = - translate_assign_rhs(sig, proc->get_scope(), - ivl_expr_oper2(rval), base, lval_width); + make_assign_rhs(sig, proc->get_scope(), + ivl_expr_oper2(rval), base, lval_width); vhdl_expr *false_part = - translate_assign_rhs(sig, proc->get_scope(), - ivl_expr_oper3(rval), base, lval_width); + make_assign_rhs(sig, proc->get_scope(), + ivl_expr_oper3(rval), base, lval_width); if (!test || !true_part || !false_part) return NULL; @@ -216,11 +216,11 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container, } else { vhdl_expr *rhs = - translate_assign_rhs(sig, proc->get_scope(), rval, base, lval_width); + make_assign_rhs(sig, proc->get_scope(), rval, base, lval_width); if (NULL == rhs) return NULL; - std::string signame(get_renamed_signal(sig)); + string signame(get_renamed_signal(sig)); vhdl_decl *decl = proc->get_scope()->get_decl(signame); // Where possible, move constant assignments into the @@ -349,11 +349,7 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container, if (type == IVL_ST_ASSIGN_NB) { draw_nbassign(proc, container, sub_stmt, time); } - else { - // All blocking assignments need to be made visible - // at this point - draw_blocking_assigns(proc, container); - + else { vhdl_wait_stmt *wait = new vhdl_wait_stmt(VHDL_WAIT_FOR, time); container->add_stmt(wait); diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index d59fbb12e..4d7f808e2 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -23,23 +23,19 @@ vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm); vhdl_expr *translate_expr(ivl_expr_t e); void remember_entity(vhdl_entity *ent); -vhdl_entity *find_entity(const std::string &tname); +vhdl_entity *find_entity(const string &tname); ivl_design_t get_vhdl_design(); -vhdl_entity *get_active_entity(); +//vhdl_entity *get_active_entity(); vhdl_var_ref *nexus_to_var_ref(vhdl_scope *arch_scope, ivl_nexus_t nexus); bool seen_signal_before(ivl_signal_t sig); void remember_signal(ivl_signal_t sig, const vhdl_scope *scope); -void rename_signal(ivl_signal_t sig, const std::string &renamed); +void rename_signal(ivl_signal_t sig, const string &renamed); const vhdl_scope *find_scope_for_signal(ivl_signal_t sig); -const std::string &get_renamed_signal(ivl_signal_t sig); -ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope); - -void blocking_assign_to(vhdl_procedural *proc, ivl_signal_t sig); -std::string strip_var(const std::string &str); -void draw_blocking_assigns(vhdl_procedural *proc, stmt_container *container); +const string &get_renamed_signal(ivl_signal_t sig); +ivl_signal_t find_signal_named(const string &name, const vhdl_scope *scope); int draw_stask_display(vhdl_procedural *proc, stmt_container *container, ivl_statement_t stmt, bool newline = true);