The test_width methods scan and mark expressions with type and size.

Later passes need the intermediate results for width and size so that
some special cases, were self-determined arguments occur, can be
processed properly during elaboration. This can be especially tricky
and interesting for ternary expressions.
This commit is contained in:
Stephen Williams 2008-10-10 20:42:07 -07:00
parent fd4018cb33
commit c85eff93f2
7 changed files with 173 additions and 84 deletions

View File

@ -28,6 +28,8 @@
PExpr::PExpr() PExpr::PExpr()
{ {
expr_type_ = IVL_VT_NO_TYPE;
has_sign_ = false;
} }
PExpr::~PExpr() PExpr::~PExpr()

36
PExpr.h
View File

@ -73,7 +73,13 @@ class PExpr : public LineInfo {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
// After the test_width method is complete, these methods
// return valid results.
ivl_variable_type_t expr_type() const { return expr_type_; }
unsigned expr_width() const { return expr_width_; }
bool has_sign() const { return has_sign_; }
// During the elaborate_sig phase, we may need to scan // During the elaborate_sig phase, we may need to scan
// expressions to find implicit net declarations. // expressions to find implicit net declarations.
@ -134,6 +140,12 @@ class PExpr : public LineInfo {
// of expressions. // of expressions.
virtual bool is_constant(Module*) const; virtual bool is_constant(Module*) const;
protected:
// The derived class test_width methods should fill these in.
ivl_variable_type_t expr_type_;
unsigned expr_width_;
bool has_sign_;
private: // not implemented private: // not implemented
PExpr(const PExpr&); PExpr(const PExpr&);
PExpr& operator= (const PExpr&); PExpr& operator= (const PExpr&);
@ -218,7 +230,7 @@ class PEFNumber : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
virtual NetExpr*elaborate_expr(Design*des, NetScope*, virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const; int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const; virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@ -244,7 +256,7 @@ class PEIdent : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -360,7 +372,7 @@ class PENumber : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
virtual NetEConst*elaborate_expr(Design*des, NetScope*, virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const; int expr_width, bool) const;
@ -397,7 +409,7 @@ class PEString : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
virtual NetEConst*elaborate_expr(Design*des, NetScope*, virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const; int expr_width, bool) const;
@ -421,7 +433,7 @@ class PEUnary : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -450,7 +462,7 @@ class PEBinary : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -491,7 +503,7 @@ class PEBComp : public PEBinary {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&flag) const; bool&flag);
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;
@ -506,7 +518,7 @@ class PEBShift : public PEBinary {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&flag) const; bool&flag);
virtual NetExpr*elaborate_expr(Design*des, NetScope*, virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const; int expr_width, bool sys_task_arg) const;
}; };
@ -527,7 +539,7 @@ class PETernary : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -571,7 +583,7 @@ class PECallFunction : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
private: private:
pform_name_t path_; pform_name_t path_;
@ -584,7 +596,7 @@ class PECallFunction : public PExpr {
unsigned test_width_sfunc_(Design*des, NetScope*scope, unsigned test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag);
}; };
#endif #endif

View File

@ -80,7 +80,7 @@ class PGate : public LineInfo {
bool as_net_flag =false) const; bool as_net_flag =false) const;
unsigned pin_count() const { return pins_? pins_->count() : 0; } unsigned pin_count() const { return pins_? pins_->count() : 0; }
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; } PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
strength_t strength0() const; strength_t strength0() const;
strength_t strength1() const; strength_t strength1() const;

View File

@ -99,7 +99,7 @@ class PAssign_ : public Statement {
virtual ~PAssign_() =0; virtual ~PAssign_() =0;
const PExpr* lval() const { return lval_; } const PExpr* lval() const { return lval_; }
const PExpr* rval() const { return rval_; } PExpr* rval() const { return rval_; }
protected: protected:
NetAssign_* elaborate_lval(Design*, NetScope*scope) const; NetAssign_* elaborate_lval(Design*, NetScope*scope) const;

View File

@ -44,12 +44,25 @@ bool type_is_vectorable(ivl_variable_type_t type)
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t data_type_lv, int expr_wid_lv, ivl_variable_type_t data_type_lv, int expr_wid_lv,
const PExpr*expr) PExpr*expr)
{ {
int expr_wid = 0; bool unsized_flag = type_is_vectorable(data_type_lv)? true : false;
bool unsized_flag = false;
ivl_variable_type_t rval_type = IVL_VT_NO_TYPE; ivl_variable_type_t rval_type = IVL_VT_NO_TYPE;
/* Find out what the r-value width is going to be. We
guess it will be the l-value width, but it may turn
out to be something else based on self-determined
widths inside. */
int expr_wid = expr->test_width(des, scope, expr_wid_lv, expr_wid_lv, rval_type, unsized_flag);
if (debug_elaborate) {
cerr << expr->get_fileline() << ": debug: r-value tested "
<< "type=" << rval_type
<< ", width=" << expr_wid
<< ", min=" << expr_wid_lv
<< ", unsized_flag=" << (unsized_flag?"true":"false") << endl;
}
switch (data_type_lv) { switch (data_type_lv) {
case IVL_VT_REAL: case IVL_VT_REAL:
unsized_flag = true; unsized_flag = true;
@ -58,19 +71,6 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
break; break;
case IVL_VT_BOOL: case IVL_VT_BOOL:
case IVL_VT_LOGIC: case IVL_VT_LOGIC:
/* Find out what the r-value width is going to be. We
guess it will be the l-value width, but it may turn
out to be something else based on self-determined
widths inside. */
expr_wid = expr->test_width(des, scope, expr_wid_lv, expr_wid_lv, rval_type, unsized_flag);
if (debug_elaborate) {
cerr << expr->get_fileline() << ": debug: r-value tested "
<< "width is " << expr_wid
<< ", min=" << expr_wid_lv
<< ", unsized_flag=" << (unsized_flag?"true":"false") << endl;
}
break; break;
case IVL_VT_VOID: case IVL_VT_VOID:
case IVL_VT_NO_TYPE: case IVL_VT_NO_TYPE:
@ -90,7 +90,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
*/ */
unsigned PExpr::test_width(Design*des, NetScope*scope, unsigned PExpr::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&, bool&) const ivl_variable_type_t&, bool&)
{ {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: test_width defaults to " cerr << get_fileline() << ": debug: test_width defaults to "
@ -113,7 +113,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, int, bool) const
unsigned PEBinary::test_width(Design*des, NetScope*scope, unsigned PEBinary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
ivl_variable_type_t expr_type_left = IVL_VT_NO_TYPE; ivl_variable_type_t expr_type_left = IVL_VT_NO_TYPE;
ivl_variable_type_t expr_type_right= IVL_VT_NO_TYPE; ivl_variable_type_t expr_type_right= IVL_VT_NO_TYPE;
@ -126,23 +126,23 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope,
if (flag_right && !flag_left) { if (flag_right && !flag_left) {
flag_left = flag_right; flag_left = flag_right;
wid_left = left_->test_width(des, scope, min, 0, expr_type_right, flag_right); wid_left = left_->test_width(des, scope, min, 0, expr_type_left, flag_right);
} }
if (flag_left || flag_right) if (flag_left || flag_right)
unsized_flag = true; unsized_flag = true;
if (expr_type_left == IVL_VT_REAL || expr_type_right == IVL_VT_REAL) if (expr_type_left == IVL_VT_REAL || expr_type_right == IVL_VT_REAL)
expr_type = IVL_VT_REAL; expr_type_ = IVL_VT_REAL;
else if (expr_type_left==IVL_VT_LOGIC || expr_type_right==IVL_VT_LOGIC) else if (expr_type_left==IVL_VT_LOGIC || expr_type_right==IVL_VT_LOGIC)
expr_type = IVL_VT_LOGIC; expr_type_ = IVL_VT_LOGIC;
else else
expr_type = IVL_VT_BOOL; expr_type_ = IVL_VT_BOOL;
switch (op_) { switch (op_) {
case '+': case '+':
case '-': case '-':
if (unsized_flag && type_is_vectorable(expr_type)) { if (unsized_flag && type_is_vectorable(expr_type_)) {
wid_left += 1; wid_left += 1;
wid_right += 1; wid_right += 1;
} }
@ -172,7 +172,13 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope,
break; break;
} }
return min; if (type_is_vectorable(expr_type_))
expr_width_ = min;
else
expr_width_ = 1;
expr_type = expr_type_;
return expr_width_;
} }
/* /*
@ -697,7 +703,7 @@ NetExpr* PEBinary::elaborate_expr_base_add_(Design*des,
unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned, unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&) const bool&)
{ {
expr_type = IVL_VT_LOGIC; expr_type = IVL_VT_LOGIC;
return 1; return 1;
@ -748,7 +754,7 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
unsigned PEBShift::test_width(Design*des, NetScope*scope, unsigned PEBShift::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
unsigned wid_left = left_->test_width(des,scope,min, 0, expr_type, unsized_flag); unsigned wid_left = left_->test_width(des,scope,min, 0, expr_type, unsized_flag);
@ -794,7 +800,7 @@ NetExpr*PEBShift::elaborate_expr(Design*des, NetScope*scope,
unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope, unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
perm_string name = peek_tail_name(path_); perm_string name = peek_tail_name(path_);
@ -810,14 +816,33 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
return wid; return wid;
} }
// Run through the arguments of the system function and make
// sure their widths/types are calculated. They are all self-
// determined.
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
PExpr*expr = parms_[idx];
ivl_variable_type_t sub_type = IVL_VT_NO_TYPE;
bool flag = false;
unsigned wid = expr->test_width(des,scope,0,0,sub_type,flag);
if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width"
<< " of " << name << " argument " << idx+1
<< " returns type=" << sub_type
<< ", wid=" << wid << endl;
}
if (name=="$sizeof" || name=="$bits") { if (name=="$sizeof" || name=="$bits") {
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width" cerr << get_fileline() << ": debug: test_width"
<< " of $sizeof/$bits returns test_width" << " of $sizeof/$bits returns test_width"
<< " of compiler integer." << endl; << " of compiler integer." << endl;
expr_type = IVL_VT_BOOL; expr_type_ = IVL_VT_BOOL;
return integer_width; expr_width_= integer_width;
has_sign_ = false;
expr_type = expr_type_;
return expr_width_;
} }
if (name=="$is_signed") { if (name=="$is_signed") {
@ -826,8 +851,10 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
<< " of $is_signed returns test_width" << " of $is_signed returns test_width"
<< " of 1." << endl; << " of 1." << endl;
expr_type = IVL_VT_BOOL; expr_type_ = IVL_VT_BOOL;
return 1; expr_width_ = 1;
expr_type = expr_type_;
return expr_width_;
} }
/* Get the return type of the system function by looking it up /* Get the return type of the system function by looking it up
@ -835,22 +862,24 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
const struct sfunc_return_type*sfunc_info const struct sfunc_return_type*sfunc_info
= lookup_sys_func(peek_tail_name(path_)); = lookup_sys_func(peek_tail_name(path_));
expr_type = sfunc_info->type; expr_type_ = sfunc_info->type;
unsigned wid = sfunc_info->wid; expr_width_ = sfunc_info->wid;
expr_type = expr_type_;
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width " cerr << get_fileline() << ": debug: test_width "
<< "of system function " << name << "of system function " << name
<< " returns wid=" << wid << " returns wid=" << expr_width_
<< ", type=" << expr_type << "." << endl; << ", type=" << expr_type_ << "." << endl;
return wid; return expr_width_;
} }
unsigned PECallFunction::test_width(Design*des, NetScope*scope, unsigned PECallFunction::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
if (peek_tail_name(path_)[0] == '$') if (peek_tail_name(path_)[0] == '$')
return test_width_sfunc_(des, scope, min, lval, expr_type, unsized_flag); return test_width_sfunc_(des, scope, min, lval, expr_type, unsized_flag);
@ -1312,10 +1341,14 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
unsigned PEFNumber::test_width(Design*des, NetScope*scope, unsigned PEFNumber::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
expr_type = IVL_VT_REAL; expr_type_ = IVL_VT_REAL;
expr_width_ = 1;
has_sign_ = true;
unsized_flag = true; unsized_flag = true;
expr_type = expr_type_;
return 1; return 1;
} }
@ -1342,11 +1375,19 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
ivl_assert(*this, index_tail.sel == index_component_t::SEL_PART); ivl_assert(*this, index_tail.sel == index_component_t::SEL_PART);
ivl_assert(*this, index_tail.msb && index_tail.lsb); ivl_assert(*this, index_tail.msb && index_tail.lsb);
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
bool tmp_flag = false;
int msb_wid = index_tail.msb->test_width(des, scope, 0, 0, tmp_type, tmp_flag);
tmp_type = IVL_VT_NO_TYPE;
tmp_flag = false;
int lsb_wid = index_tail.lsb->test_width(des, scope, 0, 0, tmp_type, tmp_flag);
/* This handles part selects. In this case, there are /* This handles part selects. In this case, there are
two bit select expressions, and both must be two bit select expressions, and both must be
constant. Evaluate them and pass the results back to constant. Evaluate them and pass the results back to
the caller. */ the caller. */
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1); NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, lsb_wid);
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex); NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
if (lsb_c == 0) { if (lsb_c == 0) {
cerr << index_tail.lsb->get_fileline() << ": error: " cerr << index_tail.lsb->get_fileline() << ": error: "
@ -1359,7 +1400,7 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
return false; return false;
} }
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1); NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, msb_wid);
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex); NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
if (msb_c == 0) { if (msb_c == 0) {
cerr << index_tail.msb->get_fileline() << ": error: " cerr << index_tail.msb->get_fileline() << ": error: "
@ -1458,7 +1499,7 @@ bool PEIdent::calculate_param_range_(Design*des, NetScope*scope,
unsigned PEIdent::test_width(Design*des, NetScope*scope, unsigned PEIdent::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
NetNet* net = 0; NetNet* net = 0;
const NetExpr*par = 0; const NetExpr*par = 0;
@ -1468,14 +1509,21 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
symbol_search(des, scope, path_, net, par, eve, ex1, ex2); symbol_search(des, scope, path_, net, par, eve, ex1, ex2);
if (net != 0)
expr_type_ = net->data_type();
expr_type = expr_type;
// If there is a part/bit select expression, then process it // If there is a part/bit select expression, then process it
// here. This constrains the results no matter what kind the // here. This constrains the results no matter what kind the
// name is. // name is.
const name_component_t&name_tail = path_.back(); const name_component_t&name_tail = path_.back();
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty()) if (!name_tail.index.empty()) {
use_sel = name_tail.index.back().sel; const index_component_t&index_tail = name_tail.index.back();
use_sel = index_tail.sel;
}
unsigned use_width = UINT_MAX; unsigned use_width = UINT_MAX;
switch (use_sel) { switch (use_sel) {
@ -1506,15 +1554,18 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
// The width of a signal expression is the width of the signal. // The width of a signal expression is the width of the signal.
if (net != 0) { if (net != 0) {
expr_type = net->data_type(); expr_type_ = net->data_type();
return max(net->vector_width(), (unsigned long)min); expr_width_= max(net->vector_width(), (unsigned long)min);
expr_type = expr_type_;
return expr_width_;
} }
// The width of a parameter name is the width of the range for // The width of a parameter name is the width of the range for
// the parameter name, if a range is declared. Otherwise, the // the parameter name, if a range is declared. Otherwise, the
// width is undefined. // width is undefined.
if (par != 0) { if (par != 0) {
expr_type = par->expr_type(); expr_type_ = par->expr_type();
expr_type = expr_type_;
if (ex1) { if (ex1) {
ivl_assert(*this, ex2); ivl_assert(*this, ex2);
const NetEConst*ex1_const = dynamic_cast<const NetEConst*> (ex1); const NetEConst*ex1_const = dynamic_cast<const NetEConst*> (ex1);
@ -1524,19 +1575,22 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
long msb = ex1_const->value().as_long(); long msb = ex1_const->value().as_long();
long lsb = ex2_const->value().as_long(); long lsb = ex2_const->value().as_long();
if (msb >= lsb) if (msb >= lsb)
return msb - lsb + 1; expr_width_ = msb - lsb + 1;
else else
return lsb - msb + 1; expr_width_ = lsb - msb + 1;
return expr_width_;
} }
// This is a parameter. If it is sized (meaning it was // This is a parameter. If it is sized (meaning it was
// declared with range expresions) then the range // declared with range expresions) then the range
// expressions would have been caught above. So if we // expressions would have been caught above. So if we
// got there there we know this is an unsized constant. // got there there we know this is an unsized constant.
expr_width_ = par->expr_width();
unsized_flag = true; unsized_flag = true;
return par->expr_width(); return expr_width_;
} }
expr_width_ = min;
return min; return min;
} }
@ -2392,9 +2446,9 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
unsigned PENumber::test_width(Design*, NetScope*, unsigned PENumber::test_width(Design*, NetScope*,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
expr_type = IVL_VT_LOGIC; expr_type_ = IVL_VT_LOGIC;
unsigned use_wid = value_->len(); unsigned use_wid = value_->len();
if (min > use_wid) if (min > use_wid)
use_wid = min; use_wid = min;
@ -2405,6 +2459,8 @@ unsigned PENumber::test_width(Design*, NetScope*,
if (lval > 0 && lval < use_wid) if (lval > 0 && lval < use_wid)
use_wid = lval; use_wid = lval;
expr_type = expr_type_;
expr_width_ = use_wid;
return use_wid; return use_wid;
} }
@ -2435,7 +2491,7 @@ NetEConst* PENumber::elaborate_expr(Design*des, NetScope*,
unsigned PEString::test_width(Design*des, NetScope*scope, unsigned PEString::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
expr_type = IVL_VT_BOOL; expr_type = IVL_VT_BOOL;
unsigned use_wid = text_? 8*strlen(text_) : 0; unsigned use_wid = text_? 8*strlen(text_) : 0;
@ -2456,7 +2512,7 @@ NetEConst* PEString::elaborate_expr(Design*des, NetScope*,
unsigned PETernary::test_width(Design*des, NetScope*scope, unsigned PETernary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&flag) const bool&flag)
{ {
ivl_variable_type_t tru_type = IVL_VT_NO_TYPE; ivl_variable_type_t tru_type = IVL_VT_NO_TYPE;
unsigned tru_wid = tru_->test_width(des, scope, min, lval, tru_type,flag); unsigned tru_wid = tru_->test_width(des, scope, min, lval, tru_type,flag);
@ -2477,13 +2533,16 @@ unsigned PETernary::test_width(Design*des, NetScope*scope,
} }
if (tru_type == IVL_VT_REAL || fal_type == IVL_VT_REAL) if (tru_type == IVL_VT_REAL || fal_type == IVL_VT_REAL)
expr_type = IVL_VT_REAL; expr_type_ = IVL_VT_REAL;
else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC) else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC)
expr_type = IVL_VT_LOGIC; expr_type_ = IVL_VT_LOGIC;
else else
expr_type = tru_type; expr_type_ = tru_type;
return max(tru_wid,fal_wid); expr_width_ = max(tru_wid,fal_wid);
expr_type = expr_type_;
return expr_width_;
} }
bool NetETernary::test_operand_compat(ivl_variable_type_t l, bool NetETernary::test_operand_compat(ivl_variable_type_t l,
@ -2520,13 +2579,11 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
int use_wid = expr_wid >= 0? expr_wid : 0; int use_wid = expr_wid >= 0? expr_wid : 0;
if (expr_wid < 0) { if (expr_wid < 0) {
bool flag = expr_wid == -2; use_wid = expr_width();
ivl_variable_type_t expr_type = IVL_VT_NO_TYPE;
use_wid = this->test_width(des, scope, 0, 0, expr_type, flag);
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: " cerr << get_fileline() << ": debug: "
<< "Self-sized ternary chooses wid="<< use_wid << "Self-sized ternary chooses wid="<< use_wid
<< ", type=" << expr_type << ", type=" << expr_type()
<< endl; << endl;
ivl_assert(*this, use_wid > 0); ivl_assert(*this, use_wid > 0);
} }
@ -2611,7 +2668,7 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
unsigned PEUnary::test_width(Design*des, NetScope*scope, unsigned PEUnary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type, ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag)
{ {
switch (op_) { switch (op_) {
case '!': case '!':

View File

@ -2321,12 +2321,30 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) { for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
PExpr*ex = parm(idx); PExpr*ex = parm(idx);
eparms[idx] = ex? ex->elaborate_expr(des, scope, -1, true) : 0; if (ex != 0) {
ivl_variable_type_t use_type;
bool flag = false;
int use_wid = ex->test_width(des,scope,0,0, use_type, flag);
if (debug_elaborate)
cerr << ex->get_fileline() << ": debug: "
<< "Argument " << (idx+1)
<< " of system task tests its width as " << use_wid
<< ", type=" << use_type
<< ", unsized_flag=" << flag << endl;
/* Attempt to pre-evaluate the parameters. It may be // If the argument expression is unsized, then
possible to at least partially reduce the // elaborate as self-determined *lossless* instead
expression. */ // of sized.
if (eparms[idx]) eval_expr(eparms[idx]); if (flag==true)
use_wid = -2;
eparms[idx] = ex->elaborate_expr(des, scope, use_wid, true);
if (eparms[idx])
eval_expr(eparms[idx]);
} else {
eparms[idx] = 0;
}
} }
NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms); NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms);

View File

@ -157,7 +157,7 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
*/ */
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t data_type_lv, ivl_variable_type_t data_type_lv,
int expr_wid_lv, const PExpr*expr); int expr_wid_lv, PExpr*expr);
/* /*
* This procedure elaborates an expression and if the elaboration is * This procedure elaborates an expression and if the elaboration is
* successful the original expression is replaced with the new one. * successful the original expression is replaced with the new one.