From c4a62dee0df46b166726fff6ad9db61eefc9938a Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 11 Mar 2009 13:22:11 -0700 Subject: [PATCH] Pass unsigned-ness of arithmetic operators through operands. The arithmetic operands are signed only if both operands are signed. If the expression is unsigned, then the expression as a whole needs to be processed as unsigned in order to get padding right. --- netlist.h | 3 +++ set_width.cc | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/netlist.h b/netlist.h index 23c613f4b..256c68ebe 100644 --- a/netlist.h +++ b/netlist.h @@ -3262,6 +3262,7 @@ class NetEBAdd : public NetEBinary { virtual ivl_variable_type_t expr_type() const; virtual bool set_width(unsigned w, bool last_chance); + virtual void cast_signed(bool sign_flag); virtual NetEBAdd* dup_expr() const; virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); @@ -3284,6 +3285,7 @@ class NetEBDiv : public NetEBinary { virtual ivl_variable_type_t expr_type() const; virtual bool set_width(unsigned w, bool last_chance); + virtual void cast_signed(bool sign_flag); virtual NetEBDiv* dup_expr() const; virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); @@ -3414,6 +3416,7 @@ class NetEBMult : public NetEBinary { virtual ivl_variable_type_t expr_type() const; virtual bool set_width(unsigned w, bool last_chance); + virtual void cast_signed(bool sign_flag); virtual NetEBMult* dup_expr() const; virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); diff --git a/set_width.cc b/set_width.cc index ed209c754..2e013d438 100644 --- a/set_width.cc +++ b/set_width.cc @@ -106,6 +106,18 @@ bool NetEBAdd::set_width(unsigned w, bool) return wid == w; } +void NetEBAdd::cast_signed(bool sign_flag) +{ + if (has_sign() == sign_flag) + return; + + if (sign_flag == false) { + left_->cast_signed(sign_flag); + right_->cast_signed(sign_flag); + } + cast_signed_base_(sign_flag); +} + /* * The bitwise logical operators have operands the same size as the * result. Anything else is a mess. I first try to get the operands to @@ -168,6 +180,19 @@ bool NetEBDiv::set_width(unsigned w, bool) return w == expr_width(); } +void NetEBDiv::cast_signed(bool sign_flag) +{ + if (has_sign() == sign_flag) + return; + + if (sign_flag == false) { + left_->cast_signed(sign_flag); + right_->cast_signed(sign_flag); + } + + cast_signed_base_(sign_flag); +} + bool NetEBLogic::set_width(unsigned w, bool) { bool flag; @@ -192,6 +217,19 @@ bool NetEBMult::set_width(unsigned w, bool) return true; } +void NetEBMult::cast_signed(bool sign_flag) +{ + if (has_sign() == sign_flag) + return; + + if (sign_flag == false) { + left_->cast_signed(sign_flag); + right_->cast_signed(sign_flag); + } + + cast_signed_base_(sign_flag); +} + bool NetEBPow::set_width(unsigned w, bool last_chance) { return w == expr_width();