From a6f898a702e94ef0f1308435e6c8e0efb63a59f8 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 27 Jun 2007 21:51:31 -0700 Subject: [PATCH] Careful not to lose bits parameter add expression Parameter expressions that do not otherwise have a size should evaluate expressions losslessly, expanding as necessary to prevent overflow of data. Signed-off-by: Stephen Williams --- PExpr.h | 12 +++++++++--- elab_expr.cc | 2 +- elab_pexpr.cc | 2 +- elaborate.cc | 4 ++++ net_expr.cc | 8 +++++--- netlist.h | 2 +- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/PExpr.h b/PExpr.h index 82a35035c..f4f8145a7 100644 --- a/PExpr.h +++ b/PExpr.h @@ -79,9 +79,15 @@ class PExpr : public LineInfo { // Procedural elaboration of the expression. The expr_width is // the width of the context of the expression (i.e. the - // l-value width of an assignment) or -1 if the expression is - // self-determinted. The sys_task_arg flag is true if - // expressions are allowed to be incomplete. + // l-value width of an assignment), + // + // ... or -1 if the expression is self-determined. or + // ... or -2 if the expression is losslessly + // self-determined. This can happen in situations where the + // result is going to a pseudo-infinitely wide context. + // + // The sys_task_arg flag is true if expressions are allowed to + // be incomplete. virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, int expr_width, bool sys_task_arg) const; diff --git a/elab_expr.cc b/elab_expr.cc index 43fc52e83..8c364c753 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -208,7 +208,7 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des, case '+': case '-': - tmp = new NetEBAdd(op_, lp, rp); + tmp = new NetEBAdd(op_, lp, rp, expr_wid==-2? true : false); if (expr_wid > 0 && (tmp->expr_type() == IVL_VT_BOOL || tmp->expr_type() == IVL_VT_LOGIC)) tmp->set_width(expr_wid); diff --git a/elab_pexpr.cc b/elab_pexpr.cc index 19d589b18..0de0b441d 100644 --- a/elab_pexpr.cc +++ b/elab_pexpr.cc @@ -54,7 +54,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const return 0; } - NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -1); + NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -2); return tmp; } diff --git a/elaborate.cc b/elaborate.cc index e54cade9d..92323d4a8 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1754,6 +1754,10 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const { assert(scope); + if (debug_elaborate) + cerr << get_line() << ": debug: Elaborate condition statement" + << " with conditional: " << *expr_ << endl; + // Elaborate and try to evaluate the conditional expression. NetExpr*expr = elab_and_eval(des, scope, expr_, -1); if (expr == 0) { diff --git a/net_expr.cc b/net_expr.cc index 4129039d6..780928cef 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -37,7 +37,7 @@ ivl_variable_type_t NetExpr::expr_type() const * Create an add/sub node from the two operands. Make a best guess of * the */ -NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r) +NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag) : NetEBinary(op, l, r) { NetEConst* tmp; @@ -75,14 +75,16 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r) } + unsigned pad_width = lossless_flag? 1 : 0; + /* Now that we have the operand sizes the way we like, or as good as we are going to get them, set the size of myself. */ if (r->expr_width() > l->expr_width()) { - expr_width(r->expr_width()); + expr_width(r->expr_width() + pad_width); } else { - expr_width(l->expr_width()); + expr_width(l->expr_width() + pad_width); } cast_signed(l->has_sign() && r->has_sign()); diff --git a/netlist.h b/netlist.h index c6b23b631..26cb9086e 100644 --- a/netlist.h +++ b/netlist.h @@ -2636,7 +2636,7 @@ class NetEBinary : public NetExpr { class NetEBAdd : public NetEBinary { public: - NetEBAdd(char op, NetExpr*l, NetExpr*r); + NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag =false); ~NetEBAdd(); virtual ivl_variable_type_t expr_type() const;