Add better constant user functions are not supported messages.

This patch adds messages in various places to warn that constant
user functions are not supported. It uses a global variable to
indicate when we are in a constant context. This is a bit of a
kludge, but works well without needing to change a bunch of code.

It is interesting to note that ports are elaborated late enough
that if we had the constant function evaluation code they would
evaluate correctly. This also applies to the function return
range, the concatenation repeat, specparams and initial values.

Signal definitions are early enough that elaboration is what is
failing because the function body is not available (has not been
elaborated). The same thing applies to both parameters and
localparms.
This commit is contained in:
Cary R 2009-02-27 18:58:36 -08:00 committed by Stephen Williams
parent 82805b9351
commit d143597996
8 changed files with 68 additions and 8 deletions

View File

@ -1462,8 +1462,16 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
if (access_nature) if (access_nature)
return elaborate_access_func_(des, scope, access_nature); return elaborate_access_func_(des, scope, access_nature);
cerr << get_fileline() << ": error: No function " << path_ << // We do not currently support constant user function and
" in this context (" << scope_path(scope) << ")." << endl; // 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) {
cerr << get_fileline() << ": sorry: constant user "
"functions are not currently supported: "
<< path_ << "()." << endl << " or" << endl;
}
cerr << get_fileline() << ": error: No function " << path_
<< " in this context (" << scope_path(scope) << ")." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
@ -1611,13 +1619,17 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
if (repeat_expr_ == 0) { if (repeat_expr_ == 0) {
// If the expression has not yet been elaborated, // If the expression has not yet been elaborated,
// then try now. // then try now.
need_constant_expr = true;
tmp = elab_and_eval(des, scope, repeat_, -1); tmp = elab_and_eval(des, scope, repeat_, -1);
need_constant_expr = false;
assert(tmp); assert(tmp);
} else { } else {
// If it has been elaborated, make sure it is // If it has been elaborated, make sure it is
// fully evaluated. // fully evaluated.
tmp = repeat_expr_; tmp = repeat_expr_;
need_constant_expr = true;
eval_expr(tmp); eval_expr(tmp);
need_constant_expr = false;
} }
if (tmp->expr_type() == IVL_VT_REAL) { if (tmp->expr_type() == IVL_VT_REAL) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -438,15 +438,15 @@ NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
return rtn; return rtn;
} }
cerr << get_fileline() << ": error: this is not a constant " cerr << get_fileline() << ": error: " << nm << "() is not a "
"system function (" << *this << ")." << endl; "constant system function." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
/* Constant user function code goes here. */ /* Constant user function code goes here. */
cerr << get_fileline() << ": sorry: constant user functions are not " cerr << get_fileline() << ": sorry: constant user functions are not "
"currently supported." << endl; "currently supported: " << nm << "()." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -35,6 +35,14 @@
# include "util.h" # include "util.h"
# include "ivl_assert.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) static bool get_const_argument(NetExpr*exp, verinum&res)
{ {
switch (exp->expr_type()) { switch (exp->expr_type()) {
@ -562,12 +570,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
probe_expr_width(des, scope, (*return_type_.range)[0]); probe_expr_width(des, scope, (*return_type_.range)[0]);
probe_expr_width(des, scope, (*return_type_.range)[1]); probe_expr_width(des, scope, (*return_type_.range)[1]);
need_constant_expr = true;
NetExpr*me = elab_and_eval(des, scope, NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0], -1); (*return_type_.range)[0], -1);
assert(me); assert(me);
NetExpr*le = elab_and_eval(des, scope, NetExpr*le = elab_and_eval(des, scope,
(*return_type_.range)[1], -1); (*return_type_.range)[1], -1);
assert(le); assert(le);
need_constant_expr = false;
long mnum = 0, lnum = 0; long mnum = 0, lnum = 0;
if (NetEConst*tmp = dynamic_cast<NetEConst*>(me)) { if (NetEConst*tmp = dynamic_cast<NetEConst*>(me)) {
@ -856,7 +866,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
/* If they exist get the port definition MSB and LSB */ /* If they exist get the port definition MSB and LSB */
if (port_set_ && port_msb_ != 0) { if (port_set_ && port_msb_ != 0) {
probe_expr_width(des, scope, port_msb_); probe_expr_width(des, scope, port_msb_);
/* We do not currently support constant user function. */
need_constant_expr = true;
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1); NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
need_constant_expr = false;
if (! eval_as_long(pmsb, texpr)) { if (! eval_as_long(pmsb, texpr)) {
cerr << port_msb_->get_fileline() << ": error: " cerr << port_msb_->get_fileline() << ": error: "
@ -871,7 +884,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr; delete texpr;
probe_expr_width(des, scope, port_lsb_); probe_expr_width(des, scope, port_lsb_);
/* We do not currently support constant user function. */
need_constant_expr = true;
texpr = elab_and_eval(des, scope, port_lsb_, -1); texpr = elab_and_eval(des, scope, port_lsb_, -1);
need_constant_expr = false;
if (! eval_as_long(plsb, texpr)) { if (! eval_as_long(plsb, texpr)) {
cerr << port_lsb_->get_fileline() << ": error: " cerr << port_lsb_->get_fileline() << ": error: "
@ -894,7 +910,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
/* If they exist get the net/etc. definition MSB and LSB */ /* If they exist get the net/etc. definition MSB and LSB */
if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) { if (net_set_ && net_msb_ != 0 && !bad_msb && !bad_lsb) {
probe_expr_width(des, scope, net_msb_); probe_expr_width(des, scope, net_msb_);
/* We do not currently support constant user function. */
need_constant_expr = true;
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1); NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
need_constant_expr = false;
if (! eval_as_long(nmsb, texpr)) { if (! eval_as_long(nmsb, texpr)) {
cerr << net_msb_->get_fileline() << ": error: " cerr << net_msb_->get_fileline() << ": error: "
@ -909,7 +928,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete texpr; delete texpr;
probe_expr_width(des, scope, net_lsb_); probe_expr_width(des, scope, net_lsb_);
/* We do not currently support constant user function. */
need_constant_expr = true;
texpr = elab_and_eval(des, scope, net_lsb_, -1); texpr = elab_and_eval(des, scope, net_lsb_, -1);
need_constant_expr = false;
if (! eval_as_long(nlsb, texpr)) { if (! eval_as_long(nlsb, texpr)) {
cerr << net_lsb_->get_fileline() << ": error: " cerr << net_lsb_->get_fileline() << ": error: "
@ -1003,8 +1025,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
probe_expr_width(des, scope, lidx_); probe_expr_width(des, scope, lidx_);
probe_expr_width(des, scope, ridx_); probe_expr_width(des, scope, ridx_);
need_constant_expr = true;
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1); NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1); NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
need_constant_expr = false;
if ((lexp == 0) || (rexp == 0)) { if ((lexp == 0) || (rexp == 0)) {
cerr << get_fileline() << ": internal error: There is " cerr << get_fileline() << ": internal error: There is "

View File

@ -1787,7 +1787,9 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
{ {
ivl_assert(*this, rval_); ivl_assert(*this, rval_);
need_constant_expr = is_constant_;
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval()); NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval());
need_constant_expr = false;
if (!is_constant_ || !rv) return rv; if (!is_constant_ || !rv) return rv;
@ -3925,7 +3927,9 @@ bool Module::elaborate(Design*des, NetScope*scope) const
for (specparam_it_t cur = specparams.begin() for (specparam_it_t cur = specparams.begin()
; cur != specparams.end() ; cur ++ ) { ; cur != specparams.end() ; cur ++ ) {
need_constant_expr = true;
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1); NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1);
need_constant_expr = false;
NetScope::spec_val_t value; NetScope::spec_val_t value;
if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) { if (NetECReal*val_cr = dynamic_cast<NetECReal*> (val)) {

View File

@ -1973,3 +1973,15 @@ NetExpr* NetESFunc::eval_tree(int prune_to_width)
return rtn; return rtn;
} }
NetExpr* NetEUFunc::eval_tree(int prune_to_width)
{
if (need_constant_expr) {
cerr << get_fileline() << ": sorry: constant user "
"functions are not currently supported: "
<< func_->basename() << "()." << endl;
}
return 0;
}

View File

@ -3014,6 +3014,7 @@ class NetEUFunc : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEUFunc*dup_expr() const; virtual NetEUFunc*dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true); virtual NexusSet* nex_input(bool rem_out = true);
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root); virtual NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root);
private: private:

View File

@ -318,7 +318,7 @@ bool eval_as_long(long&value, NetExpr*expr)
bool eval_as_double(double&value, NetExpr*expr) bool eval_as_double(double&value, NetExpr*expr)
{ {
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr) ) { if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr) ) {
value = tmp->value().as_long(); value = tmp->value().as_double();
return true; return true;
} }

View File

@ -134,6 +134,12 @@ extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
*/ */
extern unsigned count_lval_width(const class NetAssign_*first); 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 function elaborates an expression, and tries to evaluate it * This function elaborates an expression, and tries to evaluate it
* right away. If the expression can be evaluated, this returns a * right away. If the expression can be evaluated, this returns a
@ -150,6 +156,7 @@ extern unsigned count_lval_width(const class NetAssign_*first);
* bound to the destination. * bound to the destination.
*/ */
class PExpr; class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope, extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid, const PExpr*pe, int expr_wid,
int prune_width =-1); int prune_width =-1);