diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 998eaea90..fecda790c 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -186,97 +186,59 @@ static T *make_assignment(vhdl_procedural *proc, stmt_container *container, unsigned lval_width = ivl_lval_width(lval); ivl_expr_t rval = ivl_stmt_rval(stmt); - if (ivl_expr_type(rval) == IVL_EX_TERNARY) { - // Expand ternary expressions into an if statement - vhdl_expr *test = translate_expr(ivl_expr_oper1(rval)); - vhdl_expr *true_part = - make_assign_rhs(sig, proc->get_scope(), - ivl_expr_oper2(rval), base, lval_width); - vhdl_expr *false_part = - make_assign_rhs(sig, proc->get_scope(), - ivl_expr_oper3(rval), base, lval_width); - - if (!test || !true_part || !false_part) - return NULL; - - vhdl_if_stmt *vhdif = new vhdl_if_stmt(test); - - // True part - { - vhdl_var_ref *lval_ref = - make_assign_lhs(sig, proc->get_scope(), base, lval_width); - - T *a = new T(lval_ref, true_part); - vhdif->get_then_container()->add_stmt(a); - } - - // False part - { - vhdl_var_ref *lval_ref = - make_assign_lhs(sig, proc->get_scope(), base, lval_width); - - T *a = new T(lval_ref, false_part); - vhdif->get_else_container()->add_stmt(a); - } - - container->add_stmt(vhdif); + vhdl_expr *rhs = + make_assign_rhs(sig, proc->get_scope(), rval, base, lval_width); + if (NULL == rhs) return NULL; - } - else { - vhdl_expr *rhs = - make_assign_rhs(sig, proc->get_scope(), rval, base, lval_width); - if (NULL == rhs) + + string signame(get_renamed_signal(sig)); + vhdl_decl *decl = proc->get_scope()->get_decl(signame); + + // Where possible, move constant assignments into the + // declaration as initializers. This optimisation is only + // performed on assignments of constant values to prevent + // ordering problems. + + // This also has another application: If this is an `inital' + // process and we haven't yet generated a `wait' statement then + // moving the assignment to the initialization preserves the + // expected Verilog behaviour: VHDL does not distinguish + // `initial' and `always' processes so an `always' process might + // be activatated before an `initial' process at time 0. The + // `always' process may then use the uninitialized signal value. + // The second test ensures that we only try to initialise + // internal signals not ports + if (proc->get_scope()->initializing() + && ivl_signal_port(sig) == IVL_SIP_NONE + && !decl->has_initial() + && rhs->constant() + && decl->get_type()->get_name() != VHDL_TYPE_ARRAY) { + + // If this assignment is not in the top-level container + // it will not be made on all paths through the code + // This precludes any future extraction of an initialiser + if (container != proc->get_container()) + decl->set_initial(NULL); // Default initial value + else { + decl->set_initial(rhs); return NULL; - - string signame(get_renamed_signal(sig)); - vhdl_decl *decl = proc->get_scope()->get_decl(signame); - - // Where possible, move constant assignments into the - // declaration as initializers. This optimisation is only - // performed on assignments of constant values to prevent - // ordering problems. - - // This also has another application: If this is an `inital' - // process and we haven't yet generated a `wait' statement then - // moving the assignment to the initialization preserves the - // expected Verilog behaviour: VHDL does not distinguish - // `initial' and `always' processes so an `always' process might - // be activatated before an `initial' process at time 0. The - // `always' process may then use the uninitialized signal value. - // The second test ensures that we only try to initialise - // internal signals not ports - if (proc->get_scope()->initializing() - && ivl_signal_port(sig) == IVL_SIP_NONE - && !decl->has_initial() - && rhs->constant() - && decl->get_type()->get_name() != VHDL_TYPE_ARRAY) { - - // If this assignment is not in the top-level container - // it will not be made on all paths through the code - // This precludes any future extraction of an initialiser - if (container != proc->get_container()) - decl->set_initial(NULL); // Default initial value - else { - decl->set_initial(rhs); - return NULL; - } } - - vhdl_var_ref *lval_ref = - make_assign_lhs(sig, proc->get_scope(), base, lval_width); - - T *a = new T(lval_ref, rhs); - container->add_stmt(a); - - ivl_expr_t i_delay; - if (NULL == after && (i_delay = ivl_stmt_delay_expr(stmt))) - after = translate_time_expr(i_delay); - - if (after != NULL) - a->set_after(after); - - return a; } + + vhdl_var_ref *lval_ref = + make_assign_lhs(sig, proc->get_scope(), base, lval_width); + + T *a = new T(lval_ref, rhs); + container->add_stmt(a); + + ivl_expr_t i_delay; + if (NULL == after && (i_delay = ivl_stmt_delay_expr(stmt))) + after = translate_time_expr(i_delay); + + if (after != NULL) + a->set_after(after); + + return a; } else { error("Only signals as lvals supported at the moment"); diff --git a/tgt-vhdl/support.cc b/tgt-vhdl/support.cc index 7b0de5d76..e9592fa06 100644 --- a/tgt-vhdl/support.cc +++ b/tgt-vhdl/support.cc @@ -61,6 +61,10 @@ vhdl_type *support_function::function_type(support_function_t type) case SF_REDUCE_XOR: case SF_TERNARY_LOGIC: return vhdl_type::std_logic(); + case SF_TERNARY_SIGNED: + return new vhdl_type(VHDL_TYPE_SIGNED); + case SF_TERNARY_UNSIGNED: + return new vhdl_type(VHDL_TYPE_UNSIGNED); case SF_LOGIC_TO_INTEGER: return vhdl_type::integer(); default: @@ -76,7 +80,7 @@ void support_function::emit_ternary(std::ostream &of, int level) const void support_function::emit(std::ostream &of, int level) const { - of << "function " << function_name(type_); + of << nl_string(level) << "function " << function_name(type_); switch (type_) { case SF_UNSIGNED_TO_BOOLEAN: @@ -137,7 +141,7 @@ void support_function::emit(std::ostream &of, int level) const emit_ternary(of, level); break; case SF_TERNARY_UNSIGNED: - of << "(T : Boolean; X, Y : signed) return unsigned is"; + of << "(T : Boolean; X, Y : unsigned) return unsigned is"; emit_ternary(of, level); break; case SF_LOGIC_TO_INTEGER: @@ -149,5 +153,5 @@ void support_function::emit(std::ostream &of, int level) const assert(false); } - of << nl_string(level) << "end function;" << nl_string(level); + of << nl_string(level) << "end function;"; }