From 449cd0a76edb41fd308a71f309eeb1850e5700ab Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Mon, 23 Jun 2008 14:28:27 +0100 Subject: [PATCH] Correctly generate signed/unsigned types --- tgt-vhdl/expr.cc | 28 ++++++++++++++++++---------- tgt-vhdl/scope.cc | 4 +++- tgt-vhdl/vhdl_syntax.cc | 27 ++++++++++++++++++++++----- tgt-vhdl/vhdl_syntax.hh | 4 ++-- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index f91df6485..36dbbd2a3 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -49,6 +49,8 @@ static vhdl_var_ref *translate_signal(ivl_expr_t e) const vhdl_decl *decl = ent->get_arch()->get_decl(strip_var(renamed)); assert(decl); + std::cout << "ref: " << renamed << " width=" << decl->get_type()->get_width() << std::endl; + vhdl_type *type = new vhdl_type(*decl->get_type()); return new vhdl_var_ref(renamed, type); @@ -59,7 +61,8 @@ static vhdl_var_ref *translate_signal(ivl_expr_t e) */ static vhdl_expr *translate_number(ivl_expr_t e) { - return new vhdl_const_bits(ivl_expr_bits(e), ivl_expr_width(e)); + return new vhdl_const_bits(ivl_expr_bits(e), ivl_expr_width(e), + ivl_expr_signed(e) != 0); } static vhdl_expr *translate_unary(ivl_expr_t e) @@ -127,14 +130,24 @@ static vhdl_expr *translate_binary(ivl_expr_t e) int rwidth = rhs->get_type()->get_width(); // May need to resize the left or right hand side - if (lwidth < rwidth) + int opwidth; + if (lwidth < rwidth) { rhs = rhs->cast(lhs->get_type()); - else if (rwidth < lwidth) + opwidth = lwidth; + } + else if (rwidth < lwidth) { lhs = lhs->cast(rhs->get_type()); + opwidth = rwidth; + } + else + opwidth = lwidth; + + std::cout << "lwidth=" << lwidth << " rwidth=" << rwidth << std::endl; // For === and !== we need to compare std_logic_vectors // rather than signeds - vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR); + int msb = ivl_expr_width(e) - 1; + vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, opwidth-1, 0); bool vectorop = (lhs->get_type()->get_name() == VHDL_TYPE_SIGNED || lhs->get_type()->get_name() == VHDL_TYPE_UNSIGNED) && @@ -190,12 +203,7 @@ vhdl_expr *translate_select(ivl_expr_t e) return NULL; // Hack: resize it to the correct size - vhdl_type *rtype = vhdl_type::nsigned(ivl_expr_width(e)); - vhdl_fcall *resize = new vhdl_fcall("Resize", rtype); - resize->add_expr(from); - resize->add_expr(new vhdl_const_int(ivl_expr_width(e))); - - return resize; + return from->resize(ivl_expr_width(e)); } /* diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index d06ea0a20..743202fb7 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -135,8 +135,10 @@ static void declare_signals(vhdl_arch *arch, ivl_scope_t scope) vhdl_type *sig_type; if (width == 1) sig_type = vhdl_type::std_logic(); - else + else if (ivl_signal_signed(sig)) sig_type = vhdl_type::nsigned(width); + else + sig_type = vhdl_type::nunsigned(width); remember_signal(sig, arch->get_parent()); diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index 823262432..9ef2957ca 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -462,6 +462,11 @@ vhdl_expr::~vhdl_expr() */ vhdl_expr *vhdl_expr::cast(const vhdl_type *to) { + std::cout << "Cast: from=" << type_->get_string() + << " (" << type_->get_width() << ") " + << " to=" << to->get_string() << " (" + << to->get_width() << ")" << std::endl; + if (to->get_name() == type_->get_name()) { if (to->get_width() == type_->get_width()) return this; // Identical @@ -481,10 +486,14 @@ vhdl_expr *vhdl_expr::cast(const vhdl_type *to) return conv; } else { + vhdl_expr *tocast = this; + if (to->get_width() != type_->get_width()) + tocast = resize(to->get_width()); + vhdl_fcall *conv = new vhdl_fcall(to->get_string().c_str(), new vhdl_type(*to)); - conv->add_expr(this); - + conv->add_expr(tocast); + return conv; } } @@ -598,9 +607,14 @@ void vhdl_assign_stmt::emit(std::ofstream &of, int level) const of << ";"; } -vhdl_const_bits::vhdl_const_bits(const char *value, int width) - : vhdl_expr(vhdl_type::nsigned(width), true), qualified_(false) +vhdl_const_bits::vhdl_const_bits(const char *value, int width, bool issigned) + : vhdl_expr(issigned ? vhdl_type::nsigned(width) + : vhdl_type::nunsigned(width), true), + qualified_(false), + signed_(issigned) { + std::cout << (issigned ? "signed" : "unsigned") << " bits" << std::endl; + // Can't rely on value being NULL-terminated while (width--) value_.push_back(*value++); @@ -643,7 +657,10 @@ vhdl_expr *vhdl_const_bits::cast(const vhdl_type *to) void vhdl_const_bits::emit(std::ofstream &of, int level) const { - of << (qualified_ ? "signed'(\"" : "\""); + if (qualified_) + of << (signed_ ? "signed" : "unsigned") << "'(\""; + else + of << "\""; // The bits appear to be in reverse order std::string::const_reverse_iterator it; diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 54a54fb6e..79a8d7177 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -127,13 +127,13 @@ private: class vhdl_const_bits : public vhdl_expr { public: - vhdl_const_bits(const char *value, int width); + vhdl_const_bits(const char *value, int width, bool issigned); void emit(std::ofstream &of, int level) const; const std::string &get_value() const { return value_; } vhdl_expr *cast(const vhdl_type *to); private: std::string value_; - bool qualified_; + bool qualified_, signed_; }; class vhdl_const_bit : public vhdl_expr {