From c81645ff46c42cd7a7b6c57a12ee23ce8c28a9e5 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 6 Apr 2011 22:12:16 +0100 Subject: [PATCH] tgt-vhdl: Fix expression generation corner case and bug in xnor reduction operator Certain types of expressions involving only constants would produce ambiguous VHDL output. Fixed by qualifying one of the arguments. E.g. ('0' or '1') = '1' Which is ambiguous becomes (std_logic'('0') or '1') = '1' This fixes the xnor_test test. Reduce XNOR was implemented incorrectly because of trivial typo --- tgt-vhdl/expr.cc | 13 +++++++++++++ tgt-vhdl/lpm.cc | 2 +- tgt-vhdl/support.cc | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index 2b8322683..555a50f43 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -320,6 +320,19 @@ static vhdl_expr *translate_binary(ivl_expr_t e) int rwidth = rhs->get_type()->get_width(); int result_width = ivl_expr_width(e); + // There's a funny corner-case where both the LHS and RHS are constant + // single bit numbers and the VHDL compiler can't decide between the + // std_ulogic and bit overloads of various operators + const bool lnumber = ivl_expr_type(ivl_expr_oper1(e)) == IVL_EX_NUMBER; + const bool rnumber = ivl_expr_type(ivl_expr_oper2(e)) == IVL_EX_NUMBER; + if (lwidth == 1 && rwidth == 1 && lnumber && rnumber) { + // It's sufficient to qualify only one side + vhdl_fcall *lqual = new vhdl_fcall("std_logic'", lhs->get_type()); + lqual->add_expr(lhs); + + lhs = lqual; + } + // For === and !== we need to compare std_logic_vectors // rather than signeds vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0); diff --git a/tgt-vhdl/lpm.cc b/tgt-vhdl/lpm.cc index 3c7c5bca4..7153ec06b 100644 --- a/tgt-vhdl/lpm.cc +++ b/tgt-vhdl/lpm.cc @@ -271,7 +271,7 @@ static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) case IVL_LPM_RE_XOR: return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, false); case IVL_LPM_RE_XNOR: - return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, true); + return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XNOR, true); case IVL_LPM_SIGN_EXT: return sign_extend_lpm_to_expr(scope, lpm); case IVL_LPM_ARRAY: diff --git a/tgt-vhdl/support.cc b/tgt-vhdl/support.cc index 6f16ba762..3a06efea7 100644 --- a/tgt-vhdl/support.cc +++ b/tgt-vhdl/support.cc @@ -144,7 +144,7 @@ void support_function::emit(std::ostream &of, int level) const emit_reduction(of, level, "and", '1'); break; case SF_REDUCE_XOR: - emit_reduction(of, level, "xnor", '0'); + emit_reduction(of, level, "xor", '0'); break; case SF_REDUCE_XNOR: emit_reduction(of, level, "xnor", '0');