From dffe1be819c76baeaa6e0cba7174d3a61608e16b Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Tue, 15 Apr 2008 19:18:03 -0700 Subject: [PATCH] Trim results of unsized constant add to prevent width expansion When constant values are added to get another constant value, and the expression is not otherwise a fixed size, then trim the result to prevent unbounded expansion of unsized expression with. In the process, find and fix a bug in the vtrim function that caused an assert if trimming were not possible for an unsigned value. --- eval_tree.cc | 14 ++++++++++---- verinum.cc | 10 +++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/eval_tree.cc b/eval_tree.cc index c0c9c5019..47d7d211f 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -95,12 +95,14 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width) return 0; } + if (debug_eval_tree) { + cerr << get_fileline() << ": debug: Evaluate expr=" << *this + << " --- prune=" << prune_to_width + << " has_width=" << (has_width()? "true" : "false") << endl; + } + /* Result might have known width. */ if (has_width()) { - if (debug_eval_tree) { - cerr << get_fileline() << ": debug: Evaluate expr=" << *this - << " --- prune=" << prune_to_width << endl; - } unsigned lwid = lc->expr_width(); unsigned rwid = rc->expr_width(); unsigned wid = (rwid > lwid) ? rwid : lwid; @@ -108,6 +110,10 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width) wid += 1; verinum val2=verinum(val,wid); val=val2; + } else { + /* No fixed width, so trim the bits losslessly. */ + verinum val2 = trim_vnum(val); + val = val2; } return new NetEConst(val); diff --git a/verinum.cc b/verinum.cc index 0f9907389..44e114731 100644 --- a/verinum.cc +++ b/verinum.cc @@ -505,12 +505,20 @@ verinum trim_vnum(const verinum&that) unsigned top = that.len()-1; while ((top > 0) && (that.get(top) == verinum::V0)) top -= 1; + + /* Now top is the index of the highest non-zero bit. If + that turns out to the highest bit in the vector, then + tere is no trimming possible. */ + if (top+1 == that.len()) + return that; + + /* Make tlen wide enough to include the highest non-zero + bit, plus one extra 0 bit. */ tlen = top+2; /* This can only happen when the verinum is all zeros, so make it a single bit wide. */ if (that.get(top) == verinum::V0) tlen -= 1; - } verinum tmp (verinum::V0, tlen, false);