From 55b8ff4441d76048cbf5075fdff2bb5553403116 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 12 Oct 2008 21:38:07 -0700 Subject: [PATCH] Pad the subexpression of unary not. The operand of unary not needs to be padded to the expression width before the operator itself. Otherwise, the high (pad) bits will come out wrong. --- PExpr.h | 3 +++ elab_expr.cc | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/PExpr.h b/PExpr.h index 652a56d7f..c1584d0f6 100644 --- a/PExpr.h +++ b/PExpr.h @@ -444,6 +444,9 @@ class PEUnary : public PExpr { virtual bool is_constant(Module*) const; + private: + NetExpr* elaborate_expr_bits_(NetExpr*operand, int expr_wid) const; + private: char op_; PExpr*expr_; diff --git a/elab_expr.cc b/elab_expr.cc index 773d922bf..4eef2cb81 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2716,6 +2716,7 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope, // then the tested width. case '-': case '+': + case '~': if (test_wid < min) test_wid = min; break; @@ -2854,10 +2855,38 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, break; case '~': - tmp = new NetEUBits(op_, ip); - tmp->set_line(*this); + tmp = elaborate_expr_bits_(ip, expr_wid); break; } return tmp; } + +NetExpr* PEUnary::elaborate_expr_bits_(NetExpr*operand, int expr_wid) const +{ + // Handle the special case that the operand is a + // constant. Simply calculate the constant results of the + // expression and return that. + if (NetEConst*ctmp = dynamic_cast (operand)) { + verinum value = ctmp->value(); + if (expr_wid > (int)value.len()) + value = pad_to_width(value, expr_wid); + + // The only operand that I know can get here is the + // unary not (~). + ivl_assert(*this, op_ == '~'); + value = v_not(value); + + ctmp = new NetEConst(value); + ctmp->set_line(*this); + delete operand; + return ctmp; + } + + if (expr_wid > (int)operand->expr_width()) + operand = pad_to_width(operand, expr_wid); + + NetEUBits*tmp = new NetEUBits(op_, operand); + tmp->set_line(*this); + return tmp; +}