From 78028a3310b7539b23f5b389936628e973c13b8e Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 28 Jul 2008 12:59:10 +0100 Subject: [PATCH] Fully support ternary expressions --- tgt-vhdl/expr.cc | 30 ++++++++++++++++++++++++++++-- tgt-vhdl/support.cc | 31 ++++++++++++++++++++++++++++++- tgt-vhdl/support.hh | 7 ++++++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index 007abb203..0632e53f5 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -419,9 +419,35 @@ static vhdl_expr *translate_ufunc(ivl_expr_t e) static vhdl_expr *translate_ternary(ivl_expr_t e) { - error("Ternary expression only supported as RHS of assignment"); + support_function_t sf; + int width = ivl_expr_width(e); + bool issigned = ivl_expr_signed(e) != 0; + if (width == 1) + sf = SF_TERNARY_LOGIC; + else if (issigned) + sf = SF_TERNARY_SIGNED; + else + sf = SF_TERNARY_UNSIGNED; - return NULL; + require_support_function(sf); + + vhdl_expr *test = translate_expr(ivl_expr_oper1(e)); + vhdl_expr *true_part = translate_expr(ivl_expr_oper2(e)); + vhdl_expr *false_part = translate_expr(ivl_expr_oper3(e)); + if (!test || !true_part || !false_part) + return NULL; + + vhdl_type boolean(VHDL_TYPE_BOOLEAN); + test = test->cast(&boolean); + + vhdl_fcall *fcall = + new vhdl_fcall(support_function::function_name(sf), + vhdl_type::type_for(width, issigned)); + fcall->add_expr(test); + fcall->add_expr(true_part); + fcall->add_expr(false_part); + + return fcall; } static vhdl_expr *translate_concat(ivl_expr_t e) diff --git a/tgt-vhdl/support.cc b/tgt-vhdl/support.cc index 4c396407f..5e26f159a 100644 --- a/tgt-vhdl/support.cc +++ b/tgt-vhdl/support.cc @@ -46,6 +46,12 @@ const char *support_function::function_name(support_function_t type) return "Reduce_AND"; case SF_REDUCE_XOR: return "Reduce_XOR"; + case SF_TERNARY_LOGIC: + return "Ternary_Logic"; + case SF_TERNARY_UNSIGNED: + return "Ternary_Unsigned"; + case SF_TERNARY_SIGNED: + return "Ternary_Signed"; default: assert(false); } @@ -61,12 +67,20 @@ vhdl_type *support_function::function_type(support_function_t type) case SF_REDUCE_OR: case SF_REDUCE_AND: case SF_REDUCE_XOR: + case SF_TERNARY_LOGIC: return vhdl_type::std_logic(); default: assert(false); } } +void support_function::emit_ternary(std::ostream &of, int level) const +{ + of << "begin" << nl_string(indent(level)) + << "if T then return X; else return Y; end if;" + << nl_string(level); +} + void support_function::emit(std::ostream &of, int level) const { of << "function " << function_name(type_); @@ -80,7 +94,7 @@ void support_function::emit(std::ostream &of, int level) const case SF_SIGNED_TO_BOOLEAN: of << "(X : signed) return Boolean is" << nl_string(level) << "begin" << nl_string(indent(level)) - << "return X /= To_Signed(0, X'Length);" << nl_string (level); + << "return X /= To_Signed(0, X'Length);" << nl_string(level); break; case SF_BOOLEAN_TO_LOGIC: of << "(B : Boolean) return std_logic is" << nl_string(level) @@ -121,6 +135,21 @@ void support_function::emit(std::ostream &of, int level) const << "end loop;" << nl_string(indent(level)) << "return R;" << nl_string(level); break; + case SF_TERNARY_LOGIC: + of << "(T : Boolean; X, Y : std_logic) return std_logic is" + << nl_string(level); + emit_ternary(of, level); + break; + case SF_TERNARY_SIGNED: + of << "(T : Boolean; X, Y : signed) return signed is" + << nl_string(level); + emit_ternary(of, level); + break; + case SF_TERNARY_UNSIGNED: + of << "(T : Boolean; X, Y : signed) return unsigned is" + << nl_string(level); + emit_ternary(of, level); + break; default: assert(false); } diff --git a/tgt-vhdl/support.hh b/tgt-vhdl/support.hh index a5e247c94..80d6cfaff 100644 --- a/tgt-vhdl/support.hh +++ b/tgt-vhdl/support.hh @@ -24,12 +24,15 @@ #include "vhdl_syntax.hh" enum support_function_t { - SF_UNSIGNED_TO_BOOLEAN, + SF_UNSIGNED_TO_BOOLEAN = 0, SF_SIGNED_TO_BOOLEAN, SF_BOOLEAN_TO_LOGIC, SF_REDUCE_OR, SF_REDUCE_AND, SF_REDUCE_XOR, + SF_TERNARY_LOGIC, + SF_TERNARY_UNSIGNED, + SF_TERNARY_SIGNED, }; class support_function : public vhdl_function { @@ -42,6 +45,8 @@ public: static vhdl_type *function_type(support_function_t type); private: + void emit_ternary(std::ostream &of, int level) const; + support_function_t type_; };