Account for unsized arguments to comparisons.
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.
This commit is contained in:
parent
46a22e9ea2
commit
c4098cffdf
2
PExpr.cc
2
PExpr.cc
|
|
@ -92,6 +92,8 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
|
||||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||||
: PEBinary(op, l, r)
|
: PEBinary(op, l, r)
|
||||||
{
|
{
|
||||||
|
left_width_ = 0;
|
||||||
|
right_width_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PEBComp::~PEBComp()
|
PEBComp::~PEBComp()
|
||||||
|
|
|
||||||
4
PExpr.h
4
PExpr.h
|
|
@ -540,6 +540,10 @@ class PEBComp : public PEBinary {
|
||||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||||
int expr_width, bool sys_task_arg) const;
|
int expr_width, bool sys_task_arg) const;
|
||||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int left_width_;
|
||||||
|
int right_width_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
95
elab_expr.cc
95
elab_expr.cc
|
|
@ -829,13 +829,61 @@ NetExpr* PEBinary::elaborate_expr_base_add_(Design*des,
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned,
|
unsigned PEBComp::test_width(Design*des, NetScope*scope, unsigned, unsigned,
|
||||||
ivl_variable_type_t&expr_type__,
|
ivl_variable_type_t&my_expr_type,
|
||||||
bool&)
|
bool&)
|
||||||
{
|
{
|
||||||
|
// The width and type of a comparison operator is fixed and
|
||||||
|
// well known. Set them now.
|
||||||
expr_type_ = IVL_VT_LOGIC;
|
expr_type_ = IVL_VT_LOGIC;
|
||||||
expr_type__ = expr_type_;
|
my_expr_type = expr_type_;
|
||||||
expr_width_ = 1;
|
expr_width_ = 1;
|
||||||
|
|
||||||
|
// 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 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 (left_unsized_flag != unsized_flag) {
|
||||||
|
left_width = left_->test_width(des, scope, 0, 0, left_type, unsized_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int try_wid_l = left_width;
|
||||||
|
if (type_is_vectorable(left_type) && (right_width > left_width))
|
||||||
|
try_wid_l = right_width;
|
||||||
|
|
||||||
|
int try_wid_r = right_width;
|
||||||
|
if (type_is_vectorable(right_type) && (left_width > right_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 "
|
||||||
|
<< try_wid_l << " bits and "
|
||||||
|
<< try_wid_r << " bits." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
left_width_ = try_wid_l;
|
||||||
|
right_width_ = try_wid_r;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -845,37 +893,8 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||||
assert(left_);
|
assert(left_);
|
||||||
assert(right_);
|
assert(right_);
|
||||||
|
|
||||||
bool unsized_flag = false;
|
NetExpr*lp = left_->elaborate_expr(des, scope, left_width_, false);
|
||||||
ivl_variable_type_t left_type = IVL_VT_NO_TYPE;
|
NetExpr*rp = right_->elaborate_expr(des, scope, right_width_, false);
|
||||||
unsigned left_width = left_->test_width(des, scope, 0, 0, left_type, unsized_flag);
|
|
||||||
bool save_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)
|
|
||||||
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;
|
|
||||||
if (type_is_vectorable(left_type) && (right_width > left_width))
|
|
||||||
use_wid_l = right_width;
|
|
||||||
|
|
||||||
int use_wid_r = right_width;
|
|
||||||
if (type_is_vectorable(right_type) && (left_width > right_width))
|
|
||||||
use_wid_r = left_width;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetExpr*lp = left_->elaborate_expr(des, scope, use_wid_l, false);
|
|
||||||
NetExpr*rp = right_->elaborate_expr(des, scope, use_wid_r, false);
|
|
||||||
if ((lp == 0) || (rp == 0)) {
|
if ((lp == 0) || (rp == 0)) {
|
||||||
delete lp;
|
delete lp;
|
||||||
delete rp;
|
delete rp;
|
||||||
|
|
@ -888,12 +907,12 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||||
// pad the width here. This matters because if the arguments
|
// pad the width here. This matters because if the arguments
|
||||||
// are signed, then this padding will do sign extension.
|
// are signed, then this padding will do sign extension.
|
||||||
if (type_is_vectorable(lp->expr_type()))
|
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()))
|
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(lp, left_width_);
|
||||||
eval_expr(rp, use_wid_r);
|
eval_expr(rp, right_width_);
|
||||||
|
|
||||||
// Handle some operand-specific special cases...
|
// Handle some operand-specific special cases...
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue