diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index b3f7f1017..eee314caf 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -68,6 +68,68 @@ static vhdl_expr *translate_unary(ivl_expr_t e) default: error("No translation for unary opcode '%c'\n", ivl_expr_opcode(e)); + delete operand; + return NULL; + } +} + +/* + * Translate a numeric binary operator (+, -, etc.) to + * a VHDL equivalent using the numeric_std package. + */ +static vhdl_expr *translate_numeric(vhdl_expr *lhs, vhdl_expr *rhs, + vhdl_binop_t op) +{ + int lwidth = lhs->get_type()->get_width(); + int rwidth = rhs->get_type()->get_width(); + + vhdl_type ltype(VHDL_TYPE_UNSIGNED, lhs->get_type()->get_msb(), + lhs->get_type()->get_lsb()); + vhdl_type rtype(VHDL_TYPE_UNSIGNED, rhs->get_type()->get_msb(), + rhs->get_type()->get_lsb()); + + vhdl_expr *l_cast = lhs->cast(<ype); + vhdl_expr *r_cast = lhs->cast(&rtype); + + // May need to resize the left or right hand side + if (lwidth < rwidth) { + vhdl_fcall *resize = + new vhdl_fcall("resize", vhdl_type::nunsigned(rwidth)); + resize->add_expr(l_cast); + resize->add_expr(new vhdl_const_int(rwidth)); + // l_cast = resize; + } + else if (rwidth < lwidth) { + vhdl_fcall *resize = + new vhdl_fcall("resize", vhdl_type::nunsigned(lwidth)); + resize->add_expr(r_cast); + resize->add_expr(new vhdl_const_int(lwidth)); + //r_cast = resize; + } + + + return new vhdl_binop_expr(l_cast, op, r_cast, + vhdl_type::nunsigned(lwidth)); +} + +static vhdl_expr *translate_binary(ivl_expr_t e) +{ + vhdl_expr *lhs = translate_expr(ivl_expr_oper1(e)); + if (NULL == lhs) + return NULL; + + vhdl_expr *rhs = translate_expr(ivl_expr_oper2(e)); + if (NULL == rhs) + return NULL; + + switch (ivl_expr_opcode(e)) { + case '+': + return translate_numeric(lhs, rhs, VHDL_BINOP_ADD); + default: + error("No translation for binary opcode '%c'\n", + ivl_expr_opcode(e)); + delete lhs; + delete rhs; return NULL; } } @@ -88,6 +150,8 @@ vhdl_expr *translate_expr(ivl_expr_t e) return translate_number(e); case IVL_EX_UNARY: return translate_unary(e); + case IVL_EX_BINARY: + return translate_binary(e); default: error("No VHDL translation for expression at %s:%d (type = %d)", ivl_expr_file(e), ivl_expr_lineno(e), type); diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index ea44d2a13..e9597a55c 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -689,6 +689,9 @@ void vhdl_binop_expr::emit(std::ofstream &of, int level) const case VHDL_BINOP_EQ: of << " = "; break; + case VHDL_BINOP_ADD: + of << " + "; + break; } (*it)->emit(of, level); diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 0df1638fd..cf17f8dfd 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -57,6 +57,7 @@ enum vhdl_binop_t { VHDL_BINOP_AND, VHDL_BINOP_OR, VHDL_BINOP_EQ, + VHDL_BINOP_ADD, }; /* diff --git a/tgt-vhdl/vhdl_type.cc b/tgt-vhdl/vhdl_type.cc index 2aed8f44c..3f9abd29a 100644 --- a/tgt-vhdl/vhdl_type.cc +++ b/tgt-vhdl/vhdl_type.cc @@ -48,6 +48,16 @@ vhdl_type *vhdl_type::integer() return new vhdl_type(VHDL_TYPE_INTEGER); } +vhdl_type *vhdl_type::nunsigned(int width) +{ + return new vhdl_type(VHDL_TYPE_UNSIGNED, width-1, 0); +} + +vhdl_type *vhdl_type::nsigned(int width) +{ + return new vhdl_type(VHDL_TYPE_SIGNED, width-1, 0); +} + std::string vhdl_type::get_string() const { switch (name_) { diff --git a/tgt-vhdl/vhdl_type.hh b/tgt-vhdl/vhdl_type.hh index f597690a5..947ea4651 100644 --- a/tgt-vhdl/vhdl_type.hh +++ b/tgt-vhdl/vhdl_type.hh @@ -31,6 +31,8 @@ enum vhdl_type_name_t { VHDL_TYPE_FILE, VHDL_TYPE_INTEGER, VHDL_TYPE_BOOLEAN, + VHDL_TYPE_SIGNED, + VHDL_TYPE_UNSIGNED, }; /* @@ -48,12 +50,16 @@ public: vhdl_type_name_t get_name() const { return name_; } std::string get_string() const; int get_width() const { return msb_ - lsb_ + 1; } + int get_msb() const { return msb_; } + int get_lsb() const { return lsb_; } // Common types static vhdl_type *std_logic(); static vhdl_type *string(); static vhdl_type *line(); static vhdl_type *std_logic_vector(int msb, int lsb); + static vhdl_type *nunsigned(int width); + static vhdl_type *nsigned(int width); static vhdl_type *integer(); static vhdl_type *boolean(); protected: