Rework of constant expression error reporting.
This patch changes the method used to signal that a constant expression is being elaborated from flags stored in global variables to flags passed down the call chain. It also generates more informative error messages when variable references are found in a constant expression.
This commit is contained in:
parent
240880d81b
commit
93067149f1
63
PExpr.h
63
PExpr.h
|
|
@ -45,6 +45,11 @@ class PExpr : public LineInfo {
|
|||
public:
|
||||
enum width_mode_t { SIZED, EXPAND, LOSSLESS, UNSIZED };
|
||||
|
||||
// Flag values that can be passed to elaborate_expr.
|
||||
static const unsigned NO_FLAGS = 0x0;
|
||||
static const unsigned NEED_CONST = 0x1;
|
||||
static const unsigned SYS_TASK_ARG = 0x2;
|
||||
|
||||
PExpr();
|
||||
virtual ~PExpr();
|
||||
|
||||
|
|
@ -122,7 +127,7 @@ class PExpr : public LineInfo {
|
|||
// be incomplete.
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
|
|
@ -195,7 +200,7 @@ class PEConcat : public PExpr {
|
|||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
|
@ -261,7 +266,7 @@ class PEFNumber : public PExpr {
|
|||
width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -301,7 +306,7 @@ class PEIdent : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
|
||||
// Elaborate the PEIdent as a port to a module. This method
|
||||
// only applies to Ident expressions.
|
||||
|
|
@ -330,7 +335,7 @@ class PEIdent : public PExpr {
|
|||
// invalid bits (xz) in either expression, then the defined
|
||||
// flag is set to *false*.
|
||||
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb, bool&defined) const;
|
||||
NetExpr* calculate_up_do_base_(Design*, NetScope*) const;
|
||||
NetExpr* calculate_up_do_base_(Design*, NetScope*, bool need_const) const;
|
||||
bool calculate_param_range_(Design*, NetScope*,
|
||||
const NetExpr*msb_ex, long&msb,
|
||||
const NetExpr*lsb_ex, long&lsb,
|
||||
|
|
@ -352,7 +357,8 @@ class PEIdent : public PExpr {
|
|||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
unsigned expr_wid) const;
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_param_part_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
|
|
@ -365,25 +371,27 @@ class PEIdent : public PExpr {
|
|||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_param_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
NetExpr*elaborate_expr_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
|
|
@ -392,15 +400,18 @@ class PEIdent : public PExpr {
|
|||
NetExpr*elaborate_expr_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
NetExpr*elaborate_expr_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetScope*found,
|
||||
bool need_const) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
|
|
@ -423,7 +434,7 @@ class PENumber : public PExpr {
|
|||
width_mode_t&mode);
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, bool) const;
|
||||
unsigned expr_wid, unsigned) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
|
@ -456,7 +467,7 @@ class PEString : public PExpr {
|
|||
width_mode_t&mode);
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, bool) const;
|
||||
unsigned expr_wid, unsigned) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
|
||||
private:
|
||||
|
|
@ -480,7 +491,7 @@ class PEUnary : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
private:
|
||||
|
|
@ -508,7 +519,7 @@ class PEBinary : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
protected:
|
||||
|
|
@ -546,7 +557,7 @@ class PEBComp : public PEBinary {
|
|||
width_mode_t&mode);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool sys_task_arg) const;
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
private:
|
||||
unsigned l_width_;
|
||||
|
|
@ -566,7 +577,7 @@ class PEBLogic : public PEBinary {
|
|||
width_mode_t&mode);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool sys_task_arg) const;
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -589,7 +600,7 @@ class PEBLeftWidth : public PEBinary {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
};
|
||||
|
||||
class PEBPower : public PEBLeftWidth {
|
||||
|
|
@ -633,12 +644,13 @@ class PETernary : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
private:
|
||||
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
|
||||
PExpr*expr, unsigned expr_wid) const;
|
||||
PExpr*expr, unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
|
|
@ -672,7 +684,7 @@ class PECallFunction : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
|
@ -686,7 +698,8 @@ class PECallFunction : public PExpr {
|
|||
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const;
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, ivl_nature_t,
|
||||
unsigned expr_wid) const;
|
||||
unsigned test_width_sfunc_(Design*des, NetScope*scope,
|
||||
|
|
@ -705,7 +718,7 @@ class PEVoid : public PExpr {
|
|||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const;
|
||||
unsigned flags) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
265
elab_expr.cc
265
elab_expr.cc
|
|
@ -82,7 +82,7 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
|
|||
|
||||
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||
ivl_variable_type_t lv_type, unsigned lv_width,
|
||||
PExpr*expr)
|
||||
PExpr*expr, bool need_const)
|
||||
{
|
||||
int context_wid = -1;
|
||||
switch (lv_type) {
|
||||
|
|
@ -99,7 +99,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
|||
break;
|
||||
}
|
||||
|
||||
return elab_and_eval(des, scope, expr, context_wid);
|
||||
return elab_and_eval(des, scope, expr, context_wid, need_const);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -127,7 +127,7 @@ unsigned PExpr::test_width(Design*des, NetScope*, width_mode_t&)
|
|||
return 1;
|
||||
}
|
||||
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, bool) const
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: I do not know how to"
|
||||
<< " elaborate this expression. " << endl;
|
||||
|
|
@ -224,8 +224,10 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
* types.
|
||||
*/
|
||||
NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
ivl_assert(*this, left_);
|
||||
ivl_assert(*this, right_);
|
||||
|
||||
|
|
@ -249,8 +251,8 @@ NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
|||
left_->cast_signed(signed_flag_);
|
||||
}
|
||||
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, l_width, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, l_width, flags);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -505,8 +507,10 @@ unsigned PEBComp::test_width(Design*des, NetScope*scope, width_mode_t&)
|
|||
}
|
||||
|
||||
NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
ivl_assert(*this, left_);
|
||||
ivl_assert(*this, right_);
|
||||
|
||||
|
|
@ -517,8 +521,8 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
|||
if (type_is_vectorable(right_->expr_type()) && !right_->has_sign())
|
||||
left_->cast_signed(false);
|
||||
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, false);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, flags);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, flags);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -569,13 +573,14 @@ unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
|
|||
}
|
||||
|
||||
NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
ivl_assert(*this, left_);
|
||||
ivl_assert(*this, right_);
|
||||
|
||||
NetExpr*lp = elab_and_eval(des, scope, left_, -1);
|
||||
NetExpr*rp = elab_and_eval(des, scope, right_, -1);
|
||||
bool need_const = NEED_CONST & flags;
|
||||
NetExpr*lp = elab_and_eval(des, scope, left_, -1, need_const);
|
||||
NetExpr*rp = elab_and_eval(des, scope, right_, -1, need_const);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -626,7 +631,7 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
|
||||
// If the right operand is constant, we can use the
|
||||
// actual value.
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, NO_FLAGS);
|
||||
if (rp) {
|
||||
eval_expr(rp, r_width);
|
||||
} else {
|
||||
|
|
@ -707,8 +712,10 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
}
|
||||
|
||||
NetExpr*PEBLeftWidth::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
ivl_assert(*this, left_);
|
||||
|
||||
// The left operand is always context determined, so propagate
|
||||
|
|
@ -717,8 +724,8 @@ NetExpr*PEBLeftWidth::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
unsigned r_width = right_->expr_width();
|
||||
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, false);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, flags);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
|
||||
if (lp == 0 || rp == 0) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
|
|
@ -1074,7 +1081,8 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
|
|||
* known function names.
|
||||
*/
|
||||
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const
|
||||
{
|
||||
perm_string name = peek_tail_name(path_);
|
||||
|
||||
|
|
@ -1090,7 +1098,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, true);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
|
||||
|
||||
return cast_to_width_(sub, expr_wid);
|
||||
}
|
||||
|
|
@ -1162,11 +1170,14 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
|||
expression as much as possible, and use the reduced
|
||||
expression if one is created. */
|
||||
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
unsigned missing_parms = 0;
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||
PExpr*expr = parms_[idx];
|
||||
if (expr) {
|
||||
NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx, expr);
|
||||
NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx,
|
||||
expr, need_const);
|
||||
fun->parm(idx, tmp);
|
||||
|
||||
} else {
|
||||
|
|
@ -1250,10 +1261,12 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
if (peek_tail_name(path_)[0] == '$')
|
||||
return elaborate_sfunc_(des, scope, expr_wid);
|
||||
return elaborate_sfunc_(des, scope, expr_wid, flags);
|
||||
|
||||
NetFuncDef*def = des->find_function(scope, path_);
|
||||
if (def == 0) {
|
||||
|
|
@ -1268,7 +1281,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
// We do not currently support constant user function and
|
||||
// this is where things fail because of that, though we
|
||||
// don't know for sure so we need to display both messages.
|
||||
if (need_constant_expr || is_param_expr) {
|
||||
if (NEED_CONST & flags) {
|
||||
cerr << get_fileline() << ": sorry: constant user "
|
||||
"functions are not currently supported: "
|
||||
<< path_ << "()." << endl << " or" << endl;
|
||||
|
|
@ -1297,6 +1310,8 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
of the function being called. The scope of the called
|
||||
function is elaborated when the definition is elaborated. */
|
||||
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
unsigned missing_parms = 0;
|
||||
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
|
||||
PExpr*tmp = parms_[idx];
|
||||
|
|
@ -1304,7 +1319,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
parms[idx] = elaborate_rval_expr(des, scope,
|
||||
def->port(idx)->data_type(),
|
||||
(unsigned)def->port(idx)->vector_width(),
|
||||
tmp);
|
||||
tmp, need_const);
|
||||
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[idx])) {
|
||||
cerr << evt->get_fileline() << ": error: An event '"
|
||||
<< evt->event()->name() << "' can not be a user "
|
||||
|
|
@ -1372,9 +1387,7 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
|
|||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
if (repeat_ && (scope != tested_scope_)) {
|
||||
need_constant_expr = true;
|
||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1, true);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
if (tmp->expr_type() == IVL_VT_REAL) {
|
||||
|
|
@ -1426,8 +1439,10 @@ unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
|
|||
static int concat_depth = 0;
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
concat_depth += 1;
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
@ -1459,7 +1474,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
assert(parms_[idx]);
|
||||
unsigned wid = parms_[idx]->expr_width();
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, scope, wid, false);
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, scope, wid, flags);
|
||||
if (ex == 0) continue;
|
||||
|
||||
ex->set_line(*parms_[idx]);
|
||||
|
|
@ -1542,7 +1557,7 @@ unsigned PEFNumber::test_width(Design*, NetScope*, width_mode_t&)
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, bool) const
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
|
||||
{
|
||||
NetECReal*tmp = new NetECReal(*value_);
|
||||
tmp->set_line(*this);
|
||||
|
|
@ -1569,9 +1584,7 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
|||
two bit select expressions, and both must be
|
||||
constant. Evaluate them and pass the results back to
|
||||
the caller. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
|
||||
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
|
||||
if (lsb_c == 0) {
|
||||
cerr << index_tail.lsb->get_fileline() << ": error: "
|
||||
|
|
@ -1589,9 +1602,7 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
|||
lsb = lsb_c->value().as_long();
|
||||
}
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
|
||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||
if (msb_c == 0) {
|
||||
cerr << index_tail.msb->get_fileline() << ": error: "
|
||||
|
|
@ -1628,9 +1639,7 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
|
|||
/* Calculate the width expression (in the lsb_ position)
|
||||
first. If the expression is not constant, error but guess 1
|
||||
so we can keep going and find more errors. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
||||
|
||||
if (wid_c == 0) {
|
||||
|
|
@ -1651,7 +1660,8 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
|
|||
* When we know that this is an indexed part select (up or down) this
|
||||
* method calculates the up/down base, as far at it can be calculated.
|
||||
*/
|
||||
NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
|
||||
NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope,
|
||||
bool need_const) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
|
@ -1660,7 +1670,7 @@ NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, index_tail.lsb != 0);
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
@ -1831,7 +1841,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
* The signal name may be escaped, but that affects nothing here.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool sys_task_arg) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
|
|
@ -1841,10 +1851,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
if (is_param_expr && path_.size() > 1) {
|
||||
cerr << get_fileline() << ": error: parameter r-value expression "
|
||||
"does not support hierarchical references `" << path_
|
||||
<< "`." << endl;
|
||||
if ((NEED_CONST & flags) && (path_.size() > 1)) {
|
||||
cerr << get_fileline() << ": error: A hierarchical reference ('"
|
||||
<< path_ << "') is not allowed in a constant expression."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1857,7 +1867,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// the parameter value.
|
||||
if (par != 0) {
|
||||
NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in,
|
||||
ex1, ex2, expr_wid);
|
||||
ex1, ex2, expr_wid, flags);
|
||||
|
||||
if (!tmp) return 0;
|
||||
|
||||
|
|
@ -1867,20 +1877,19 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
// If this is a parameter expression, no other identifiers are valid.
|
||||
if (is_param_expr) {
|
||||
cerr << get_fileline() << ": error: identifier `"
|
||||
<< path_ << "` is not a parameter in "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (net != 0) {
|
||||
if (NEED_CONST & flags) {
|
||||
cerr << get_fileline() << ": error: A reference to a wire "
|
||||
"or register ('" << path_ << "') is not allowed in "
|
||||
"a constant expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*tmp = elaborate_expr_net(des, scope, net, found_in,
|
||||
expr_wid, sys_task_arg);
|
||||
expr_wid, flags);
|
||||
|
||||
if (!tmp) return 0;
|
||||
|
||||
|
|
@ -1890,9 +1899,17 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
// If the identifier is a named event.
|
||||
// is a variable reference.
|
||||
// If the identifier is a named event
|
||||
// then create a NetEEvent node to handle it.
|
||||
if (eve != 0) {
|
||||
if (NEED_CONST & flags) {
|
||||
cerr << get_fileline() << ": error: A reference to a named "
|
||||
"event ('" << path_ << "') is not allowed in a "
|
||||
"constant expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEEvent*tmp = new NetEEvent(eve);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
|
|
@ -1987,7 +2004,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetExpr*expr = elaborate_expr_net(des, scope, net, found_in,
|
||||
expr_wid, false);
|
||||
expr_wid, NO_FLAGS);
|
||||
NetESFunc*sys_expr = 0;
|
||||
|
||||
if (method_name == "name") {
|
||||
|
|
@ -2007,7 +2024,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< " attached to " << use_path << "." << endl;
|
||||
des->errors += 1;
|
||||
return elaborate_expr_net(des, scope, net, found_in,
|
||||
expr_wid, false);
|
||||
expr_wid, NO_FLAGS);
|
||||
}
|
||||
|
||||
sys_expr->set_line(*this);
|
||||
|
|
@ -2023,10 +2040,12 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// are not scopes. If this is not a system task argument, then
|
||||
// it cannot be a scope name, so give up.
|
||||
|
||||
if (! sys_task_arg) {
|
||||
if ( !(SYS_TASK_ARG & flags) ) {
|
||||
// I cannot interpret this identifier. Error message.
|
||||
cerr << get_fileline() << ": error: Unable to bind wire/reg/memory "
|
||||
"`" << path_ << "' in `" << scope_path(scope) << "'"<< endl;
|
||||
cerr << get_fileline() << ": error: Unable to bind "
|
||||
<< (NEED_CONST & flags ? "parameter" : "wire/reg/memory")
|
||||
<< " `" << path_ << "' in `" << scope_path(scope) << "'"
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2063,7 +2082,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< nsc->basename()
|
||||
<< " path=" << path_ << endl;
|
||||
|
||||
if (! sys_task_arg) {
|
||||
if ( !(SYS_TASK_ARG & flags) ) {
|
||||
cerr << get_fileline() << ": error: Scope name "
|
||||
<< nsc->basename() << " not allowed here." << endl;
|
||||
des->errors += 1;
|
||||
|
|
@ -2248,7 +2267,8 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
|||
const NetExpr*par,
|
||||
NetScope*,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const
|
||||
{
|
||||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||
ivl_assert(*this, par_ex);
|
||||
|
|
@ -2258,7 +2278,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
|||
par_lsb, par_lsv,
|
||||
par_ex->value().len())) return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
if (base == 0) return 0;
|
||||
|
||||
unsigned long wid = 0;
|
||||
|
|
@ -2327,7 +2347,8 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
|
|||
const NetExpr*par,
|
||||
NetScope*,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
const NetExpr*par_lsb,
|
||||
bool need_const) const
|
||||
{
|
||||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||
ivl_assert(*this, par_ex);
|
||||
|
|
@ -2337,7 +2358,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
|
|||
par_lsb, par_lsv,
|
||||
par_ex->value().len())) return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
if (base == 0) return 0;
|
||||
|
||||
unsigned long wid = 0;
|
||||
|
|
@ -2414,8 +2435,10 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb,
|
||||
unsigned expr_wid) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
|
|
@ -2440,11 +2463,11 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
|
||||
par_msb, par_lsb);
|
||||
par_msb, par_lsb, need_const);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_param_idx_do_(des, scope, par, found_in,
|
||||
par_msb, par_lsb);
|
||||
par_msb, par_lsb, need_const);
|
||||
|
||||
// NOTE TO SELF (continued): The code below should be
|
||||
// rewritten in the above format, as I get to it.
|
||||
|
|
@ -2469,7 +2492,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
/* Handle the case where a parameter has a bit
|
||||
select attached to it. Generate a NetESelect
|
||||
object to select the bit as desired. */
|
||||
NetExpr*mtmp = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetExpr*mtmp = elab_and_eval(des, scope, index_tail.msb, -1,
|
||||
need_const);
|
||||
|
||||
/* Let's first try to get constant values for both
|
||||
the parameter and the bit select. If they are
|
||||
|
|
@ -2622,11 +2646,13 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const
|
||||
unsigned flags) const
|
||||
{
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
if (name_tail.index.empty() && !sys_task_arg) {
|
||||
if (name_tail.index.empty() && !(SYS_TASK_ARG & flags)) {
|
||||
cerr << get_fileline() << ": error: Array " << path()
|
||||
<< " Needs an array index here." << endl;
|
||||
des->errors += 1;
|
||||
|
|
@ -2647,10 +2673,12 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, !index_front.lsb);
|
||||
}
|
||||
|
||||
NetExpr*word_index = index_front.sel == index_component_t::SEL_NONE
|
||||
? 0
|
||||
: elab_and_eval(des, scope, index_front.msb, -1);
|
||||
if (word_index == 0 && !sys_task_arg)
|
||||
NetExpr*word_index = 0;
|
||||
if (index_front.sel != index_component_t::SEL_NONE)
|
||||
word_index = elab_and_eval(des, scope, index_front.msb, -1,
|
||||
need_const);
|
||||
|
||||
if (word_index == 0 && !(SYS_TASK_ARG & flags))
|
||||
return 0;
|
||||
|
||||
if (NetEConst*word_addr = dynamic_cast<NetEConst*>(word_index)) {
|
||||
|
|
@ -2711,16 +2739,20 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
if (word_sel == index_component_t::SEL_PART)
|
||||
return elaborate_expr_net_part_(des, scope, res, found_in, expr_wid);
|
||||
return elaborate_expr_net_part_(des, scope, res, found_in,
|
||||
expr_wid);
|
||||
|
||||
if (word_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, res, found_in);
|
||||
return elaborate_expr_net_idx_up_(des, scope, res, found_in,
|
||||
need_const);
|
||||
|
||||
if (word_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, res, found_in);
|
||||
return elaborate_expr_net_idx_do_(des, scope, res, found_in,
|
||||
need_const);
|
||||
|
||||
if (word_sel == index_component_t::SEL_BIT)
|
||||
return elaborate_expr_net_bit_(des, scope, res, found_in);
|
||||
return elaborate_expr_net_bit_(des, scope, res, found_in,
|
||||
need_const);
|
||||
|
||||
ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
|
||||
|
||||
|
|
@ -2837,9 +2869,10 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
|||
* Part select indexed up, i.e. net[<m> +: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetESignal*net, NetScope*) const
|
||||
NetESignal*net, NetScope*,
|
||||
bool need_const) const
|
||||
{
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
|
@ -2925,9 +2958,10 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
|||
* Part select indexed down, i.e. net[<m> -: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
NetESignal*net, NetScope*)const
|
||||
NetESignal*net, NetScope*,
|
||||
bool need_const) const
|
||||
{
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
|
@ -3009,7 +3043,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
NetESignal*net, NetScope*) const
|
||||
NetESignal*net, NetScope*,
|
||||
bool need_const) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
|
@ -3018,7 +3053,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
NetExpr*ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetExpr*ex = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
|
||||
|
||||
// If the bit select is constant, then treat it similar
|
||||
// to the part select, so that I save the effort of
|
||||
|
|
@ -3111,11 +3146,13 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in,
|
||||
unsigned expr_wid,
|
||||
bool sys_task_arg) const
|
||||
unsigned flags) const
|
||||
{
|
||||
if (net->array_dimensions() > 0)
|
||||
return elaborate_expr_net_word_(des, scope, net, found_in,
|
||||
expr_wid, sys_task_arg);
|
||||
expr_wid, flags);
|
||||
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
|
|
@ -3143,13 +3180,16 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
|||
expr_wid);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, node, found_in);
|
||||
return elaborate_expr_net_idx_up_(des, scope, node, found_in,
|
||||
need_const);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, node, found_in);
|
||||
return elaborate_expr_net_idx_do_(des, scope, node, found_in,
|
||||
need_const);
|
||||
|
||||
if (use_sel == index_component_t::SEL_BIT)
|
||||
return elaborate_expr_net_bit_(des, scope, node, found_in);
|
||||
return elaborate_expr_net_bit_(des, scope, node, found_in,
|
||||
need_const);
|
||||
|
||||
// It's not anything else, so this must be a simple identifier
|
||||
// expression with no part or bit select. Return the signal
|
||||
|
|
@ -3173,7 +3213,7 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
|
|||
}
|
||||
|
||||
NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned) const
|
||||
{
|
||||
assert(value_);
|
||||
verinum val = *value_;
|
||||
|
|
@ -3198,7 +3238,7 @@ unsigned PEString::test_width(Design*, NetScope*, width_mode_t&)
|
|||
}
|
||||
|
||||
NetEConst* PEString::elaborate_expr(Design*, NetScope*,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned) const
|
||||
{
|
||||
verinum val(value());
|
||||
val = pad_to_width(val, expr_wid);
|
||||
|
|
@ -3295,15 +3335,17 @@ bool NetETernary::test_operand_compat(ivl_variable_type_t l,
|
|||
* methods. If any elaboration fails, then give up and return 0.
|
||||
*/
|
||||
NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
assert(expr_);
|
||||
assert(tru_);
|
||||
assert(fal_);
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
ivl_assert(*this, expr_);
|
||||
ivl_assert(*this, tru_);
|
||||
ivl_assert(*this, fal_);
|
||||
|
||||
// Elaborate and evaluate the condition expression. Note that
|
||||
// it is always self-determined.
|
||||
NetExpr*con = elab_and_eval(des, scope, expr_, -1);
|
||||
NetExpr*con = elab_and_eval(des, scope, expr_, -1, NEED_CONST & flags);
|
||||
if (con == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -3326,7 +3368,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
|||
"elaborate TRUE clause of ternary."
|
||||
<< endl;
|
||||
|
||||
return elab_and_eval_alternative_(des, scope, tru_, expr_wid);
|
||||
return elab_and_eval_alternative_(des, scope, tru_,
|
||||
expr_wid, flags);
|
||||
}
|
||||
|
||||
// Condition is constant FALSE, so we only need the
|
||||
|
|
@ -3337,20 +3380,21 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
|||
"elaborate FALSE clause of ternary."
|
||||
<< endl;
|
||||
|
||||
return elab_and_eval_alternative_(des, scope, fal_, expr_wid);
|
||||
return elab_and_eval_alternative_(des, scope, fal_,
|
||||
expr_wid, flags);
|
||||
}
|
||||
|
||||
// X and Z conditions need to blend both results, so we
|
||||
// can't short-circuit.
|
||||
}
|
||||
|
||||
NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_, expr_wid);
|
||||
NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_, expr_wid, flags);
|
||||
if (tru == 0) {
|
||||
delete con;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_, expr_wid);
|
||||
NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_, expr_wid, flags);
|
||||
if (fal == 0) {
|
||||
delete con;
|
||||
delete tru;
|
||||
|
|
@ -3378,7 +3422,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
|||
* self-determined.
|
||||
*/
|
||||
NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
|
||||
PExpr*expr, unsigned expr_wid) const
|
||||
PExpr*expr, unsigned expr_wid,
|
||||
unsigned flags) const
|
||||
{
|
||||
int context_wid = expr_wid;
|
||||
if (type_is_vectorable(expr->expr_type()) && !type_is_vectorable(expr_type_)) {
|
||||
|
|
@ -3387,7 +3432,7 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
|
|||
} else {
|
||||
expr->cast_signed(signed_flag_);
|
||||
}
|
||||
NetExpr*tmp = expr->elaborate_expr(des, scope, expr_wid, false);
|
||||
NetExpr*tmp = expr->elaborate_expr(des, scope, expr_wid, flags);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
eval_expr(tmp, context_wid);
|
||||
|
|
@ -3436,8 +3481,10 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
|
||||
|
||||
NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, bool) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
unsigned sub_width = expr_wid;
|
||||
switch (op_) {
|
||||
// Reduction operators and ! always have a self determined width.
|
||||
|
|
@ -3457,7 +3504,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
|||
expr_->cast_signed(signed_flag_);
|
||||
break;
|
||||
}
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope, sub_width, false);
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope, sub_width, flags);
|
||||
if (ip == 0) return 0;
|
||||
|
||||
ivl_assert(*expr_, expr_type_ != IVL_VT_NO_TYPE);
|
||||
|
|
@ -3604,7 +3651,7 @@ NetExpr* PEUnary::elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, bool) const
|
||||
NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,9 +222,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
|||
|
||||
case index_component_t::SEL_IDX_DO:
|
||||
case index_component_t::SEL_IDX_UP: {
|
||||
need_constant_expr = true;
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
if (!tmp) {
|
||||
cerr << get_fileline() << ": error: indexed part select of "
|
||||
|
|
@ -480,9 +478,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
}
|
||||
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1, true);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
if (!tmp) {
|
||||
cerr << get_fileline() << ": error: array " << sig->name()
|
||||
|
|
|
|||
|
|
@ -554,9 +554,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
// The initial value for the genvar does not need (nor can it
|
||||
// use) the genvar itself, so we can evaluate this expression
|
||||
// the same way any other parameter value is evaluated.
|
||||
need_constant_expr = true;
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1, true);
|
||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||
if (init == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
|
|
@ -620,9 +618,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
|
||||
container->genvar_tmp = loop_index;
|
||||
container->genvar_tmp_val = genvar;
|
||||
need_constant_expr = true;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
|
||||
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
||||
if (test == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
|
|
@ -668,9 +664,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
elaborate_subscope_(des, scope);
|
||||
|
||||
// Calculate the step for the loop variable.
|
||||
need_constant_expr = true;
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1, true);
|
||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||
if (step == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
|
|
@ -700,9 +694,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|||
|
||||
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
|
||||
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
||||
if (test == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||
|
|
@ -792,9 +784,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
|||
|
||||
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1, true);
|
||||
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
||||
if (case_value_co == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
||||
|
|
@ -824,9 +814,9 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
|||
|
||||
bool match_flag = false;
|
||||
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
|
||||
need_constant_expr = true;
|
||||
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*item_value_ex = elab_and_eval(des, container,
|
||||
item->item_test[idx],
|
||||
-1, true);
|
||||
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
||||
if (item_value_co == 0) {
|
||||
cerr << get_fileline() << ": error: Cannot evaluate "
|
||||
|
|
@ -1196,10 +1186,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
|||
*/
|
||||
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
||||
need_constant_expr = false;
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1, true) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1, true) : 0;
|
||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||
|
||||
|
|
|
|||
50
elab_sig.cc
50
elab_sig.cc
|
|
@ -35,14 +35,6 @@
|
|||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* Set the following to true when you need to process an expression
|
||||
* that is being done in a constant context. This allows the
|
||||
* elaboration to explicitly say we do not currently support constant
|
||||
* user functions when the function is not found.
|
||||
*/
|
||||
bool need_constant_expr = false;
|
||||
|
||||
static bool get_const_argument(NetExpr*exp, verinum&res)
|
||||
{
|
||||
switch (exp->expr_type()) {
|
||||
|
|
@ -472,14 +464,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (return_type_.range) {
|
||||
ivl_assert(*this, return_type_.range->size() == 2);
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
return_type_.range->at(0), -1);
|
||||
return_type_.range->at(0), -1,
|
||||
true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
return_type_.range->at(1), -1);
|
||||
return_type_.range->at(1), -1,
|
||||
true);
|
||||
assert(le);
|
||||
need_constant_expr = false;
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
|
|
@ -545,14 +537,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, return_type_.range != 0);
|
||||
long use_wid;
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0], -1);
|
||||
(*return_type_.range)[0], -1,
|
||||
true);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[1], -1);
|
||||
(*return_type_.range)[1], -1,
|
||||
true);
|
||||
assert(le);
|
||||
need_constant_expr = false;
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
|
|
@ -848,10 +840,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
bool bad_lsb = false, bad_msb = false;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
if (port_set_ && port_msb_ != 0) {
|
||||
/* We do not currently support constant user function. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1, true);
|
||||
|
||||
if (! eval_as_long(pmsb, texpr)) {
|
||||
cerr << port_msb_->get_fileline() << ": error: "
|
||||
|
|
@ -865,10 +854,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
delete texpr;
|
||||
|
||||
/* We do not currently support constant user function. */
|
||||
need_constant_expr = true;
|
||||
texpr = elab_and_eval(des, scope, port_lsb_, -1);
|
||||
need_constant_expr = false;
|
||||
texpr = elab_and_eval(des, scope, port_lsb_, -1, true);
|
||||
|
||||
if (! eval_as_long(plsb, texpr)) {
|
||||
cerr << port_lsb_->get_fileline() << ": error: "
|
||||
|
|
@ -892,10 +878,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
/* If they exist get the net/etc. definition MSB and LSB */
|
||||
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
|
||||
/* We do not currently support constant user function. */
|
||||
need_constant_expr = true;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1, true);
|
||||
|
||||
if (! eval_as_long(nmsb, texpr)) {
|
||||
cerr << net_msb_->get_fileline() << ": error: "
|
||||
|
|
@ -909,10 +892,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
delete texpr;
|
||||
|
||||
/* We do not currently support constant user function. */
|
||||
need_constant_expr = true;
|
||||
texpr = elab_and_eval(des, scope, net_lsb_, -1);
|
||||
need_constant_expr = false;
|
||||
texpr = elab_and_eval(des, scope, net_lsb_, -1, true);
|
||||
|
||||
if (! eval_as_long(nlsb, texpr)) {
|
||||
cerr << net_lsb_->get_fileline() << ": error: "
|
||||
|
|
@ -1003,10 +983,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (lidx_ || ridx_) {
|
||||
assert(lidx_ && ridx_);
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1, true);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1, true);
|
||||
|
||||
if ((lexp == 0) || (rexp == 0)) {
|
||||
cerr << get_fileline() << ": internal error: There is "
|
||||
|
|
|
|||
19
elaborate.cc
19
elaborate.cc
|
|
@ -227,10 +227,8 @@ unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
|
|||
gates, then I am expected to make more than one
|
||||
gate. Figure out how many are desired. */
|
||||
if (msb_) {
|
||||
need_constant_expr = true;
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1, true);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1, true);
|
||||
|
||||
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
||||
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
||||
|
|
@ -2057,9 +2055,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
|||
{
|
||||
ivl_assert(*this, rval_);
|
||||
|
||||
need_constant_expr = is_constant_;
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval());
|
||||
need_constant_expr = false;
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval(),
|
||||
is_constant_);
|
||||
|
||||
if (!is_constant_ || !rv) return rv;
|
||||
|
||||
|
|
@ -3376,7 +3373,8 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
|
|||
|
||||
PExpr::width_mode_t mode;
|
||||
pe->test_width(des, scope, mode);
|
||||
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(), false);
|
||||
NetExpr*expr = pe->elaborate_expr(des, scope, pe->expr_width(),
|
||||
PExpr::NO_FLAGS);
|
||||
if (expr == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to elaborate"
|
||||
" wait condition expression." << endl;
|
||||
|
|
@ -4204,9 +4202,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
|||
for (specparam_it_t cur = specparams.begin()
|
||||
; cur != specparams.end() ; ++ cur ) {
|
||||
|
||||
need_constant_expr = true;
|
||||
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1);
|
||||
need_constant_expr = false;
|
||||
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1,
|
||||
true);
|
||||
NetScope::spec_val_t value;
|
||||
|
||||
if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) {
|
||||
|
|
|
|||
|
|
@ -1946,12 +1946,5 @@ NetExpr* NetESFunc::eval_tree()
|
|||
|
||||
NetExpr* NetEUFunc::eval_tree()
|
||||
{
|
||||
if (need_constant_expr) {
|
||||
cerr << get_fileline() << ": sorry: constant user "
|
||||
"functions are not currently supported: "
|
||||
<< func_->basename() << "()." << endl;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
|||
/* Evaluate the msb expression, if it is present. */
|
||||
PExpr*msb_expr = (*cur).second.msb_expr;
|
||||
if (msb_expr) {
|
||||
(*cur).second.msb = elab_and_eval(des, this, msb_expr, -1);
|
||||
(*cur).second.msb = elab_and_eval(des, this, msb_expr, -1, true);
|
||||
if (! eval_as_long(msb, (*cur).second.msb)) {
|
||||
cerr << (*cur).second.val->get_fileline()
|
||||
<< ": error: Unable to evaluate msb expression "
|
||||
|
|
@ -348,7 +348,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
|||
/* Evaluate the lsb expression, if it is present. */
|
||||
PExpr*lsb_expr = (*cur).second.lsb_expr;
|
||||
if (lsb_expr) {
|
||||
(*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -1);
|
||||
(*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -1, true);
|
||||
if (! eval_as_long(lsb, (*cur).second.lsb)) {
|
||||
cerr << (*cur).second.val->get_fileline()
|
||||
<< ": error: Unable to evaluate lsb expression "
|
||||
|
|
@ -369,7 +369,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
|||
if (range_flag)
|
||||
lv_width = (msb >= lsb) ? 1 + msb - lsb : 1 + lsb - msb;
|
||||
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width);
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width, true);
|
||||
if (! expr)
|
||||
return;
|
||||
|
||||
|
|
@ -488,7 +488,7 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
|
|||
PExpr*val_expr = (*cur).second.val_expr;
|
||||
NetScope*val_scope = (*cur).second.val_scope;
|
||||
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1);
|
||||
NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true);
|
||||
if (! expr)
|
||||
return;
|
||||
|
||||
|
|
@ -631,14 +631,6 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
|
|||
cur->second.val_expr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the following to true when evaluating the parameter expressions.
|
||||
* This causes PEIdent::elaborate_expr() to report an error if an
|
||||
* identifier in an expression is anything other than a non-hierarchical
|
||||
* parameter name.
|
||||
*/
|
||||
bool is_param_expr = false;
|
||||
|
||||
void NetScope::evaluate_parameters(Design*des)
|
||||
{
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
|
|
@ -649,13 +641,11 @@ void NetScope::evaluate_parameters(Design*des)
|
|||
cerr << ":0" << ": debug: "
|
||||
<< "Evaluate parameters in " << scope_path(this) << endl;
|
||||
|
||||
is_param_expr = true;
|
||||
for (param_ref_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; ++ cur) {
|
||||
|
||||
evaluate_parameter_(des, cur);
|
||||
}
|
||||
is_param_expr = false;
|
||||
}
|
||||
|
||||
void Design::residual_defparams()
|
||||
|
|
|
|||
17
netmisc.cc
17
netmisc.cc
|
|
@ -470,7 +470,8 @@ static const char*width_mode_name(PExpr::width_mode_t mode)
|
|||
}
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
int context_width, bool need_const)
|
||||
{
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
if ((context_width == -2) && !gn_strict_expr_width_flag)
|
||||
|
|
@ -510,7 +511,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
|
|||
}
|
||||
}
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, false);
|
||||
unsigned flags = PExpr::NO_FLAGS;
|
||||
if (need_const)
|
||||
flags |= PExpr::NEED_CONST;
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, flags);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
eval_expr(tmp, context_width);
|
||||
|
|
@ -524,7 +529,7 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, int context_width)
|
|||
}
|
||||
|
||||
NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
||||
unsigned arg_idx, PExpr*pe)
|
||||
unsigned arg_idx, PExpr*pe, bool need_const)
|
||||
{
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
pe->test_width(des, scope, mode);
|
||||
|
|
@ -539,7 +544,11 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
|||
<< ", mode=" << width_mode_name(mode) << endl;
|
||||
}
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, pe->expr_width(), true);
|
||||
unsigned flags = PExpr::SYS_TASK_ARG;
|
||||
if (need_const)
|
||||
flags |= PExpr::NEED_CONST;
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, pe->expr_width(), flags);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
eval_expr(tmp, -1);
|
||||
|
|
|
|||
22
netmisc.h
22
netmisc.h
|
|
@ -134,17 +134,6 @@ extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
|
|||
*/
|
||||
extern unsigned count_lval_width(const class NetAssign_*first);
|
||||
|
||||
/*
|
||||
* This is temporarily used to indicate that a user function elaboration
|
||||
* fail is likely the result of missing constant user function support.
|
||||
*/
|
||||
extern bool need_constant_expr;
|
||||
|
||||
/*
|
||||
* This is used to indicate that we are evaluating a parameter expression.
|
||||
*/
|
||||
extern bool is_param_expr;
|
||||
|
||||
/*
|
||||
* This function elaborates an expression, and tries to evaluate it
|
||||
* right away. If the expression can be evaluated, this returns a
|
||||
|
|
@ -160,14 +149,16 @@ extern bool is_param_expr;
|
|||
class PExpr;
|
||||
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
PExpr*pe, int context_width);
|
||||
PExpr*pe, int context_width,
|
||||
bool need_const =false);
|
||||
|
||||
/*
|
||||
* This function is a variant of elab_and_eval that elaborates and
|
||||
* evaluates the arguments of a system task.
|
||||
*/
|
||||
extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
||||
unsigned arg_idx, PExpr*pe);
|
||||
extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope,
|
||||
perm_string name, unsigned arg_idx,
|
||||
PExpr*pe, bool need_const =false);
|
||||
/*
|
||||
* This function elaborates an expression as if it is for the r-value
|
||||
* of an assignment, The lv_type and lv_width are the type and width
|
||||
|
|
@ -176,7 +167,8 @@ extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
|||
*/
|
||||
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width, PExpr*expr);
|
||||
unsigned lv_width, PExpr*expr,
|
||||
bool need_const =false);
|
||||
|
||||
/*
|
||||
* This procedure evaluates an expression and if the evaluation is
|
||||
|
|
|
|||
Loading…
Reference in New Issue