Support disable statements and system task calls in constant functions.
This patch implements the evaluate_function method for the NetDisable and NetSTask classes. It also makes the checks for a function being constant work when the function contains nested scopes (named blocks).
This commit is contained in:
parent
09f90ab4e1
commit
1bcd3a97ad
|
|
@ -2767,7 +2767,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
if (net->scope() != scope) {
|
||||
if (net->scope()->type() == NetScope::MODULE) {
|
||||
if (scope->need_const_func()) {
|
||||
cerr << get_fileline() << ": error: A reference to a "
|
||||
"non-local wire or reg (`" << path_ << "') is "
|
||||
|
|
|
|||
16
elaborate.cc
16
elaborate.cc
|
|
@ -2784,6 +2784,20 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
|||
cur->append(tmp);
|
||||
}
|
||||
|
||||
// Update flags in parent scope.
|
||||
if (!nscope->is_const_func())
|
||||
scope->is_const_func(false);
|
||||
if (nscope->calls_sys_task())
|
||||
scope->calls_sys_task(true);
|
||||
|
||||
if (!wires.empty()) {
|
||||
if (scope->need_const_func()) {
|
||||
cerr << get_fileline() << ": sorry: Block variables inside "
|
||||
"a constant function are not yet supported." << endl;
|
||||
}
|
||||
scope->is_const_func(false);
|
||||
}
|
||||
|
||||
cur->set_line(*this);
|
||||
return cur;
|
||||
}
|
||||
|
|
@ -3010,6 +3024,8 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
|||
return noop;
|
||||
}
|
||||
|
||||
scope->calls_sys_task(true);
|
||||
|
||||
NetSTask*cur = new NetSTask(name, def_sfunc_as_task, eparms);
|
||||
cur->set_line(*this);
|
||||
return cur;
|
||||
|
|
|
|||
|
|
@ -1982,7 +1982,7 @@ NetExpr* NetEUFunc::eval_tree()
|
|||
{
|
||||
// If we know the function cannot be evaluated as a constant,
|
||||
// give up now.
|
||||
if (!func()->is_const_func())
|
||||
if (!func()->is_const_func() || (func()->calls_sys_task() && !need_const_))
|
||||
return 0;
|
||||
|
||||
// If we neither want nor need to evaluate the function at
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* We only evaluate one function at a time, so to support the disable
|
||||
* statement, we just need to record the target block and then early
|
||||
* terminate each enclosing block or loop statement until we get back
|
||||
* to the target block.
|
||||
*/
|
||||
static const NetScope*disable = 0;
|
||||
|
||||
static NetExpr* fix_assign_value(const NetNet*lhs, NetExpr*rhs)
|
||||
{
|
||||
NetEConst*ce = dynamic_cast<NetEConst*>(rhs);
|
||||
|
|
@ -221,7 +229,9 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
|
|||
cur = cur->next_;
|
||||
bool cur_flag = cur->evaluate_function(loc, context_map);
|
||||
flag = flag && cur_flag;
|
||||
} while (cur != last_);
|
||||
} while (cur != last_ && !disable);
|
||||
|
||||
if (disable == subscope_) disable = 0;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
|
@ -247,6 +257,20 @@ bool NetCondit::evaluate_function(const LineInfo&loc,
|
|||
return (else_ == 0) || else_->evaluate_function(loc, context_map);
|
||||
}
|
||||
|
||||
bool NetDisable::evaluate_function(const LineInfo&,
|
||||
map<perm_string,NetExpr*>&) const
|
||||
{
|
||||
disable = target_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetSTask::evaluate_function(const LineInfo&,
|
||||
map<perm_string,NetExpr*>&) const
|
||||
{
|
||||
// system tasks within a constant function are ignored
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetWhile::evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,NetExpr*>&context_map) const
|
||||
{
|
||||
|
|
@ -257,7 +281,7 @@ bool NetWhile::evaluate_function(const LineInfo&loc,
|
|||
<< "Start loop" << endl;
|
||||
}
|
||||
|
||||
while (flag) {
|
||||
while (flag && !disable) {
|
||||
// Evaluate the condition expression to try and get the
|
||||
// condition for the loop.
|
||||
NetExpr*cond = cond_->evaluate_function(loc, context_map);
|
||||
|
|
|
|||
|
|
@ -44,19 +44,22 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
|
|||
{
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
need_const_func_ = false;
|
||||
is_const_func_ = false;
|
||||
is_auto_ = false;
|
||||
is_cell_ = false;
|
||||
calls_stask_ = false;
|
||||
in_final_ = false;
|
||||
|
||||
if (up) {
|
||||
need_const_func_ = up->need_const_func_;
|
||||
is_const_func_ = up->is_const_func_;
|
||||
time_unit_ = up->time_unit();
|
||||
time_prec_ = up->time_precision();
|
||||
time_from_timescale_ = up->time_from_timescale();
|
||||
// Need to check for duplicate names?
|
||||
up_->children_[name_] = this;
|
||||
} else {
|
||||
need_const_func_ = false;
|
||||
is_const_func_ = false;
|
||||
time_unit_ = 0;
|
||||
time_prec_ = 0;
|
||||
time_from_timescale_ = false;
|
||||
|
|
|
|||
12
netlist.h
12
netlist.h
|
|
@ -909,6 +909,10 @@ class NetScope : public Attrib {
|
|||
void is_cell(bool is_cell__) { is_cell_ = is_cell__; };
|
||||
bool is_cell() const { return is_cell_; };
|
||||
|
||||
/* Is there a call to a system task in this scope. */
|
||||
void calls_sys_task(bool calls_stask__) { calls_stask_ = calls_stask__; };
|
||||
bool calls_sys_task() const { return calls_stask_; };
|
||||
|
||||
/* Is this scope elaborating a final procedure? */
|
||||
void in_final(bool in_final__) { in_final_ = in_final__; };
|
||||
bool in_final() const { return in_final_; };
|
||||
|
|
@ -1096,7 +1100,7 @@ class NetScope : public Attrib {
|
|||
map<hname_t,NetScope*> children_;
|
||||
|
||||
unsigned lcounter_;
|
||||
bool need_const_func_, is_const_func_, is_auto_, is_cell_;
|
||||
bool need_const_func_, is_const_func_, is_auto_, is_cell_, calls_stask_;
|
||||
|
||||
/* Final procedures sets this to notify statements that
|
||||
they are part of a final procedure. */
|
||||
|
|
@ -2827,6 +2831,9 @@ class NetDisable : public NetProc {
|
|||
|
||||
const NetScope*target() const;
|
||||
|
||||
bool evaluate_function(const LineInfo&loc,
|
||||
std::map<perm_string,NetExpr*>&ctx) const;
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
|
|
@ -3239,6 +3246,9 @@ class NetSTask : public NetProc {
|
|||
|
||||
const NetExpr* parm(unsigned idx) const;
|
||||
|
||||
virtual bool evaluate_function(const LineInfo&loc,
|
||||
map<perm_string,NetExpr*>&ctx) const;
|
||||
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
|
|
|
|||
Loading…
Reference in New Issue