Skip to content

Commit

Permalink
Account for unsized arguments to comparisons.
Browse files Browse the repository at this point in the history
Comparison expressions have sorta-self-determined arguments.
Handle the special cause that some of the arguments may be
themselves unsized, and so expecting to be even wider then
otherwise.
  • Loading branch information
steveicarus committed Apr 27, 2010
1 parent 46a22e9 commit c4098cf
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 27 deletions.
2 changes: 2 additions & 0 deletions PExpr.cc
Expand Up @@ -92,6 +92,8 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
left_width_ = 0;
right_width_ = 0;
}

PEBComp::~PEBComp()
Expand Down
4 changes: 4 additions & 0 deletions PExpr.h
Expand Up @@ -540,6 +540,10 @@ class PEBComp : public PEBinary {
NetExpr* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;

private:
int left_width_;
int right_width_;
};

/*
Expand Down
73 changes: 46 additions & 27 deletions elab_expr.cc
Expand Up @@ -829,53 +829,72 @@ NetExpr* PEBinary::elaborate_expr_base_add_(Design*des,
return tmp;
}

unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned,
ivl_variable_type_t&expr_type__,
unsigned PEBComp::test_width(Design*des, NetScope*scope, unsigned, unsigned,
ivl_variable_type_t&my_expr_type,
bool&)
{
// The width and type of a comparison operator is fixed and
// well known. Set them now.
expr_type_ = IVL_VT_LOGIC;
expr_type__ = expr_type_;
my_expr_type = expr_type_;
expr_width_ = 1;
return 1;
}

NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
int expr_width_dummy, bool sys_task_arg) const
{
assert(left_);
assert(right_);

// The widths of operands are self-determined, but need to be
// figured out.
bool unsized_flag = false;
ivl_variable_type_t left_type = IVL_VT_NO_TYPE;
unsigned left_width = left_->test_width(des, scope, 0, 0, left_type, unsized_flag);
bool save_flag = unsized_flag;
bool left_unsized_flag = unsized_flag;
ivl_variable_type_t right_type = IVL_VT_NO_TYPE;
unsigned right_width = right_->test_width(des, scope, 0, 0, right_type, unsized_flag);

if (save_flag != unsized_flag)
if (left_unsized_flag != unsized_flag) {
left_width = left_->test_width(des, scope, 0, 0, left_type, unsized_flag);
}

/* Width of operands is self-determined. */

int use_wid_l = left_width;
int try_wid_l = left_width;
if (type_is_vectorable(left_type) && (right_width > left_width))
use_wid_l = right_width;
try_wid_l = right_width;

int use_wid_r = right_width;
int try_wid_r = right_width;
if (type_is_vectorable(right_type) && (left_width > right_width))
use_wid_r = left_width;
try_wid_r = left_width;

// If the expression is unsized and smaller then the integer
// minimum, then tweak the size up.
// NOTE: I really would rather try to figure out what it would
// take to get expand the sub-expressions so that they are
// exactly the right width to behave just like infinite
// width. I suspect that adding 1 more is sufficient in all
// cases, but I'm not certain. Ideas?
if (type_is_vectorable(left_type) && unsized_flag && try_wid_l<(int)integer_width)
try_wid_l += 1;
if (type_is_vectorable(right_type) && unsized_flag && try_wid_r<(int)integer_width)
try_wid_r += 1;

if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Comparison expression operands are "
<< left_width << " bits and "
<< right_width << " bits. Resorting to "
<< use_wid_l << " bits and "
<< use_wid_r << " bits." << endl;
<< try_wid_l << " bits and "
<< try_wid_r << " bits." << endl;
}

NetExpr*lp = left_->elaborate_expr(des, scope, use_wid_l, false);
NetExpr*rp = right_->elaborate_expr(des, scope, use_wid_r, false);
left_width_ = try_wid_l;
right_width_ = try_wid_r;

return 1;
}

NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
int expr_width_dummy, bool sys_task_arg) const
{
assert(left_);
assert(right_);

NetExpr*lp = left_->elaborate_expr(des, scope, left_width_, false);
NetExpr*rp = right_->elaborate_expr(des, scope, right_width_, false);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
Expand All @@ -888,12 +907,12 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
// pad the width here. This matters because if the arguments
// are signed, then this padding will do sign extension.
if (type_is_vectorable(lp->expr_type()))
lp = pad_to_width(lp, use_wid_l, *this);
lp = pad_to_width(lp, left_width_, *this);
if (type_is_vectorable(rp->expr_type()))
rp = pad_to_width(rp, use_wid_r, *this);
rp = pad_to_width(rp, right_width_, *this);

eval_expr(lp, use_wid_l);
eval_expr(rp, use_wid_r);
eval_expr(lp, left_width_);
eval_expr(rp, right_width_);

// Handle some operand-specific special cases...
switch (op_) {
Expand Down

0 comments on commit c4098cf

Please sign in to comment.