From 7b82bd26f5bcbe571d9ac366dede6004429aa33c Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 5 Mar 2011 11:37:48 +0000 Subject: [PATCH] tgt-vhdl: Fix shift2 test regression Caused by translate_select emitting a logical instead of arithmetic shift for signed arguments. --- tgt-vhdl/expr.cc | 14 ++++++++++++-- tgt-vhdl/vhdl_syntax.cc | 2 +- tgt-vhdl/vhdl_syntax.hh | 6 +++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index a382fb8f6..2b8322683 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -473,8 +473,18 @@ static vhdl_expr *translate_select(ivl_expr_t e) // We can't directly select bits from something that's not // a variable reference in VHDL, but we can emulate the // effect with a shift and a resize - return new vhdl_binop_expr(from, VHDL_BINOP_SR, base->to_integer(), - new vhdl_type(*from->get_type())); + + if (ivl_expr_signed(ivl_expr_oper1(e))) { + vhdl_fcall *sra = new vhdl_fcall("shift_right", from->get_type()); + sra->add_expr(from); + sra->add_expr(base->to_integer()); + + return sra; + } + else + return new vhdl_binop_expr(from, VHDL_BINOP_SR, base->to_integer(), + from->get_type()); + } else if (from_var_ref->get_type()->get_name() != VHDL_TYPE_STD_LOGIC) { // We can use the more idiomatic VHDL slice notation on a diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index f74256eeb..4f231e1ee 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -923,7 +923,7 @@ void vhdl_unaryop_expr::emit(std::ostream &of, int level) const } vhdl_binop_expr::vhdl_binop_expr(vhdl_expr *left, vhdl_binop_t op, - vhdl_expr *right, vhdl_type *type) + vhdl_expr *right, const vhdl_type *type) : vhdl_expr(type), op_(op) { add_expr(left); diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index a27c45bac..3e04dce88 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -119,10 +119,10 @@ enum vhdl_binop_t { */ class vhdl_binop_expr : public vhdl_expr { public: - vhdl_binop_expr(vhdl_binop_t op, vhdl_type *type) + vhdl_binop_expr(vhdl_binop_t op, const vhdl_type *type) : vhdl_expr(type), op_(op) {} vhdl_binop_expr(vhdl_expr *left, vhdl_binop_t op, - vhdl_expr *right, vhdl_type *type); + vhdl_expr *right, const vhdl_type *type); ~vhdl_binop_expr(); void add_expr(vhdl_expr *e); @@ -271,7 +271,7 @@ private: */ class vhdl_fcall : public vhdl_expr { public: - vhdl_fcall(const string& name, vhdl_type *rtype) + vhdl_fcall(const string& name, const vhdl_type *rtype) : vhdl_expr(rtype), name_(name) {}; ~vhdl_fcall() {}