From a0dbb1aa5dfa5b73116b245441c580f75460918a Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 7 Jul 2008 21:45:27 +0100 Subject: [PATCH] Fix more bugs in part selects --- tgt-vhdl/lpm.cc | 47 ++++++++++++++++++++++++++++++------------- tgt-vhdl/vhdl_type.cc | 10 +++++++++ tgt-vhdl/vhdl_type.hh | 2 ++ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/tgt-vhdl/lpm.cc b/tgt-vhdl/lpm.cc index 48af05b0b..239f9d7be 100644 --- a/tgt-vhdl/lpm.cc +++ b/tgt-vhdl/lpm.cc @@ -23,19 +23,38 @@ #include #include +static vhdl_expr *draw_concat_lpm(vhdl_scope *scope, ivl_lpm_t lpm) +{ + vhdl_type *result_type = + vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0); + vhdl_binop_expr *expr = + new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type); + + for (int i = ivl_lpm_selects(lpm) - 1; i >= 0; i--) { + vhdl_expr *e = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i)); + if (NULL == e) + return NULL; + + expr->add_expr(e); + } + + return expr; +} + static vhdl_expr *draw_binop_lpm(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t op) { - vhdl_expr *lhs = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0)); - if (NULL == lhs) - return NULL; - - vhdl_expr *rhs = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 1)); - if (NULL == rhs) - return NULL; - - vhdl_type *result_type = new vhdl_type(*lhs->get_type()); - vhdl_expr *expr = new vhdl_binop_expr(lhs, op, rhs, result_type); + vhdl_type *result_type = + vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0); + vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type); + + for (int i = 0; i < 2; i++) { + vhdl_expr *e = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i)); + if (NULL == e) + return NULL; + expr->add_expr(e); + } + if (op == VHDL_BINOP_MULT) { // Need to resize the output to the desired size, // as this does not happen automatically in VHDL @@ -46,10 +65,10 @@ static vhdl_expr *draw_binop_lpm(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t resize->add_expr(expr); resize->add_expr(new vhdl_const_int(out_width)); - expr = resize; + return resize; } - - return expr; + else + return expr; } /* @@ -158,7 +177,7 @@ vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) case IVL_LPM_MULT: return draw_binop_lpm(scope, lpm, VHDL_BINOP_MULT); case IVL_LPM_CONCAT: - return draw_binop_lpm(scope, lpm, VHDL_BINOP_CONCAT); + return draw_concat_lpm(scope, lpm); case IVL_LPM_PART_VP: return draw_part_select_vp_lpm(scope, lpm); case IVL_LPM_UFUNC: diff --git a/tgt-vhdl/vhdl_type.cc b/tgt-vhdl/vhdl_type.cc index 77b3a7b0f..18db0dc28 100644 --- a/tgt-vhdl/vhdl_type.cc +++ b/tgt-vhdl/vhdl_type.cc @@ -121,3 +121,13 @@ vhdl_type *vhdl_type::std_logic_vector(int msb, int lsb) { return new vhdl_type(VHDL_TYPE_STD_LOGIC_VECTOR, msb, lsb); } + +vhdl_type *vhdl_type::type_for(int width, bool issigned) +{ + if (width == 0) + return vhdl_type::std_logic(); + else if (issigned) + return vhdl_type::nsigned(width); + else + return vhdl_type::nunsigned(width); +} diff --git a/tgt-vhdl/vhdl_type.hh b/tgt-vhdl/vhdl_type.hh index b0e0c6f3b..0c52814d6 100644 --- a/tgt-vhdl/vhdl_type.hh +++ b/tgt-vhdl/vhdl_type.hh @@ -65,6 +65,8 @@ public: static vhdl_type *integer(); static vhdl_type *boolean(); static vhdl_type *time(); + + static vhdl_type *type_for(int width, bool issigned); protected: vhdl_type_name_t name_; int msb_, lsb_;