Add support for array variables inside constant user functions.

This commit is contained in:
Martin Whitaker 2013-04-19 22:07:30 +01:00
parent a91840c15d
commit c4257ecfc9
2 changed files with 165 additions and 94 deletions

View File

@ -55,9 +55,9 @@ static NetExpr* fix_assign_value(const NetNet*lhs, NetExpr*rhs)
NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<NetExpr*>&args) const
{
// Make the context map;
map<perm_string,NetExpr*>::iterator ptr;
map<perm_string,NetExpr*>context_map;
// Make the context map.
map<perm_string,LocalVar>::iterator ptr;
map<perm_string,LocalVar>context_map;
if (debug_eval_tree) {
cerr << loc.get_fileline() << ": debug: "
@ -65,13 +65,17 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
}
// Put the return value into the map...
context_map[scope_->basename()] = 0;
LocalVar&return_var = context_map[scope_->basename()];
return_var.nwords = 0;
return_var.value = 0;
// Load the input ports into the map...
ivl_assert(loc, ports_.size() == args.size());
for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) {
perm_string aname = ports_[idx]->name();
context_map[aname] = fix_assign_value(ports_[idx], args[idx]);
LocalVar&input_var = context_map[aname];
input_var.nwords = 0;
input_var.value = fix_assign_value(ports_[idx], args[idx]);
if (debug_eval_tree) {
cerr << loc.get_fileline() << ": debug: "
@ -90,13 +94,22 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
// Extract the result...
ptr = context_map.find(scope_->basename());
NetExpr*res = ptr->second;
NetExpr*res = ptr->second.value;
context_map.erase(ptr);
// Cleanup the rest of the context.
for (ptr = context_map.begin() ; ptr != context_map.end() ; ++ptr) {
delete ptr->second;
unsigned nwords = ptr->second.nwords;
if (nwords > 0) {
NetExpr**array = ptr->second.array;
for (unsigned idx = 0 ; idx < nwords ; idx += 1) {
delete array[idx];
}
delete [] ptr->second.array;
} else {
delete ptr->second.value;
}
}
// Done.
@ -108,7 +121,7 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
}
void NetScope::evaluate_function_find_locals(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
for (map<perm_string,NetNet*>::const_iterator cur = signals_map_.begin()
; cur != signals_map_.end() ; ++cur) {
@ -118,17 +131,33 @@ void NetScope::evaluate_function_find_locals(const LineInfo&loc,
if (tmp->port_type() != NetNet::NOT_A_PORT)
continue;
context_map[tmp->name()] = 0;
unsigned nwords = 0;
if (tmp->unpacked_dimensions() > 0)
nwords = tmp->unpacked_count();
LocalVar&local_var = context_map[tmp->name()];
local_var.nwords = nwords;
if (nwords > 0) {
NetExpr**array = new NetExpr*[nwords];
for (unsigned idx = 0 ; idx < nwords ; idx += 1) {
array[idx] = 0;
}
local_var.array = array;
} else {
local_var.value = 0;
}
if (debug_eval_tree) {
cerr << loc.get_fileline() << ": debug: "
<< " (local) " << tmp->name() << endl;
<< " (local) " << tmp->name()
<< (nwords > 0 ? "[]" : "") << endl;
}
}
}
NetExpr* NetExpr::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&) const
map<perm_string,LocalVar>&) const
{
cerr << get_fileline() << ": sorry: I don't know how to evaluate this expression at compile time." << endl;
cerr << get_fileline() << ": : Expression type:" << typeid(*this).name() << endl;
@ -137,7 +166,7 @@ NetExpr* NetExpr::evaluate_function(const LineInfo&,
}
bool NetProc::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&) const
map<perm_string,LocalVar>&) const
{
cerr << get_fileline() << ": sorry: I don't know how to evaluate this statement at compile time." << endl;
cerr << get_fileline() << ": : Statement type:" << typeid(*this).name() << endl;
@ -146,14 +175,33 @@ bool NetProc::evaluate_function(const LineInfo&,
}
bool NetAssign::eval_func_lval_(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map,
map<perm_string,LocalVar>&context_map,
const NetAssign_*lval, NetExpr*rval_result) const
{
map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
map<perm_string,LocalVar>::iterator ptr = context_map.find(lval->name());
ivl_assert(*this, ptr != context_map.end());
// Do not support having l-values that are unpacked arrays.
ivl_assert(loc, lval->word() == 0);
NetExpr*old_lval;
unsigned word = 0;
if (ptr->second.nwords > 0) {
NetExpr*word_result = lval->word()->evaluate_function(loc, context_map);
if (word_result == 0) {
delete rval_result;
return false;
}
NetEConst*word_const = dynamic_cast<NetEConst*>(word_result);
ivl_assert(loc, word_const);
word = word_const->value().as_long();
if (word >= ptr->second.nwords)
return true;
old_lval = ptr->second.array[word];
} else {
old_lval = ptr->second.value;
}
if (const NetExpr*base_expr = lval->get_base()) {
NetExpr*base_result = base_expr->evaluate_function(loc, context_map);
@ -170,13 +218,13 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc,
list<long>prefix (0);
base = lval->sig()->sb_to_idx(prefix, base);
if (ptr->second == 0)
ptr->second = make_const_x(lval->sig()->vector_width());
if (old_lval == 0)
old_lval = make_const_x(lval->sig()->vector_width());
ivl_assert(loc, base + lval->lwidth() <= ptr->second->expr_width());
ivl_assert(loc, base + lval->lwidth() <= old_lval->expr_width());
NetEConst*ptr_const = dynamic_cast<NetEConst*>(ptr->second);
verinum lval_v = ptr_const->value();
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
verinum lval_v = lval_const->value();
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
verinum rval_v = cast_to_width(rval_const->value(), lval->lwidth());
@ -190,8 +238,8 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc,
rval_result = fix_assign_value(lval->sig(), rval_result);
}
if (ptr->second)
delete ptr->second;
if (old_lval)
delete old_lval;
if (debug_eval_tree) {
cerr << get_fileline() << ": debug: "
@ -199,13 +247,16 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc,
<< " = " << *rval_result << endl;
}
ptr->second = rval_result;
if (ptr->second.nwords > 0)
ptr->second.array[word] = rval_result;
else
ptr->second.value = rval_result;
return true;
}
bool NetAssign::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
// Evaluate the r-value expression.
NetExpr*rval_result = rval()->evaluate_function(loc, context_map);
@ -247,10 +298,12 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
* evaluating the statements in order.
*/
bool NetBlock::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
bool flag = true;
NetProc*cur = last_;
if (cur == 0) return true;
do {
cur = cur->next_;
bool cur_flag = cur->evaluate_function(loc, context_map);
@ -263,7 +316,7 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
}
bool NetCase::evaluate_function_vect_(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
NetExpr*case_expr = expr_->evaluate_function(loc, context_map);
if (case_expr == 0)
@ -325,7 +378,7 @@ bool NetCase::evaluate_function_vect_(const LineInfo&loc,
}
bool NetCase::evaluate_function_real_(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
NetExpr*case_expr = expr_->evaluate_function(loc, context_map);
if (case_expr == 0)
@ -369,7 +422,7 @@ bool NetCase::evaluate_function_real_(const LineInfo&loc,
}
bool NetCase::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
if (expr_->expr_type() == IVL_VT_REAL)
return evaluate_function_real_(loc, context_map);
@ -378,7 +431,7 @@ bool NetCase::evaluate_function(const LineInfo&loc,
}
bool NetCondit::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
NetExpr*cond = expr_->evaluate_function(loc, context_map);
if (cond == 0)
@ -399,14 +452,14 @@ bool NetCondit::evaluate_function(const LineInfo&loc,
}
bool NetDisable::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&) const
map<perm_string,LocalVar>&) const
{
disable = target_;
return true;
}
bool NetForever::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
bool flag = true;
@ -428,7 +481,7 @@ bool NetForever::evaluate_function(const LineInfo&loc,
}
bool NetRepeat::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
bool flag = true;
@ -462,14 +515,14 @@ bool NetRepeat::evaluate_function(const LineInfo&loc,
}
bool NetSTask::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&) const
map<perm_string,LocalVar>&) 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
map<perm_string,LocalVar>&context_map) const
{
bool flag = true;
@ -513,7 +566,7 @@ bool NetWhile::evaluate_function(const LineInfo&loc,
}
NetExpr* NetEBinary::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
NetExpr*lval = left_->evaluate_function(loc, context_map);
NetExpr*rval = right_->evaluate_function(loc, context_map);
@ -531,7 +584,7 @@ NetExpr* NetEBinary::evaluate_function(const LineInfo&loc,
}
NetExpr* NetEConcat::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
vector<NetExpr*>vals(parms_.size());
unsigned gap = 0;
@ -558,7 +611,7 @@ NetExpr* NetEConcat::evaluate_function(const LineInfo&loc,
}
NetExpr* NetEConst::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&) const
map<perm_string,LocalVar>&) const
{
NetEConst*res = new NetEConst(value_);
res->set_line(*this);
@ -566,7 +619,7 @@ NetExpr* NetEConst::evaluate_function(const LineInfo&,
}
NetExpr* NetECReal::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&) const
map<perm_string,LocalVar>&) const
{
NetECReal*res = new NetECReal(value_);
res->set_line(*this);
@ -574,7 +627,7 @@ NetExpr* NetECReal::evaluate_function(const LineInfo&,
}
NetExpr* NetESelect::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
NetExpr*sub_exp = expr_->evaluate_function(loc, context_map);
ivl_assert(loc, sub_exp);
@ -608,43 +661,53 @@ NetExpr* NetESelect::evaluate_function(const LineInfo&loc,
return res_const;
}
NetExpr* NetESignal::evaluate_function(const LineInfo&,
map<perm_string,NetExpr*>&context_map) const
NetExpr* NetESignal::evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&context_map) const
{
if (word_) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate signal word selects at compile time." << endl;
return 0;
}
map<perm_string,NetExpr*>::iterator ptr = context_map.find(name());
map<perm_string,LocalVar>::iterator ptr = context_map.find(name());
if (ptr == context_map.end()) {
cerr << get_fileline() << ": error: Cannot evaluate " << name()
<< " in this context." << endl;
return 0;
}
if (ptr->second == 0) {
NetExpr*value = 0;
if (ptr->second.nwords > 0) {
ivl_assert(loc, word_);
NetExpr*word_result = word_->evaluate_function(loc, context_map);
if (word_result == 0)
return 0;
NetEConst*word_const = dynamic_cast<NetEConst*>(word_result);
ivl_assert(loc, word_const);
unsigned word = word_const->value().as_long();
if (word < ptr->second.nwords)
value = ptr->second.array[word];
} else {
value = ptr->second.value;
}
if (value == 0) {
switch (expr_type()) {
case IVL_VT_REAL:
ptr->second = new NetECReal( verireal(0.0) );
break;
return new NetECReal( verireal(0.0) );
case IVL_VT_BOOL:
ptr->second = make_const_0(expr_width());
break;
return make_const_0(expr_width());
case IVL_VT_LOGIC:
ptr->second = make_const_x(expr_width());
break;
return make_const_x(expr_width());
default:
cerr << get_fileline() << ": sorry: I don't know how to initialize " << *this << endl;
return 0;
}
}
return ptr->second->dup_expr();
return value->dup_expr();
}
NetExpr* NetETernary::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
auto_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
@ -671,7 +734,7 @@ NetExpr* NetETernary::evaluate_function(const LineInfo&loc,
}
NetExpr* NetEUnary::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
NetExpr*val = expr_->evaluate_function(loc, context_map);
if (val == 0) return 0;
@ -682,7 +745,7 @@ NetExpr* NetEUnary::evaluate_function(const LineInfo&loc,
}
NetExpr* NetESFunc::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
ID id = built_in_id_();
ivl_assert(*this, id != NOT_BUILT_IN);
@ -712,7 +775,7 @@ NetExpr* NetESFunc::evaluate_function(const LineInfo&loc,
}
NetExpr* NetEUFunc::evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const
map<perm_string,LocalVar>&context_map) const
{
NetFuncDef*def = func_->func_def();
ivl_assert(*this, def);

View File

@ -755,6 +755,17 @@ class NetNet : public NetObj, public PortType {
int port_index_;
};
/*
* This object type is used for holding local variable values when
* evaluating constant user functions.
*/
struct LocalVar {
unsigned nwords; // zero for a simple variable
union {
NetExpr* value; // a simple variable
NetExpr** array; // an array variable
};
};
/*
* This object type is used to contain a logical scope within a
@ -867,7 +878,7 @@ class NetScope : public Attrib {
// This is used by the evaluate_function setup to collect
// local variables from the scope.
void evaluate_function_find_locals(const LineInfo&loc,
map<perm_string,NetExpr*>&context_map) const;
map<perm_string,LocalVar>&ctx) const;
void set_line(perm_string file, perm_string def_file,
unsigned lineno, unsigned def_lineno);
@ -1817,7 +1828,7 @@ class NetExpr : public LineInfo {
// allocated constant, or nil if the expression cannot be
// evaluated for any reason.
virtual NetExpr*evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
// Get the Nexus that are the input to this
// expression. Normally this descends down to the reference to
@ -1882,7 +1893,7 @@ class NetEConst : public NetExpr {
virtual NexusSet* nex_input(bool rem_out = true);
virtual NetExpr*evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
private:
verinum value_;
@ -1951,11 +1962,12 @@ class NetECReal : public NetExpr {
virtual void dump(ostream&) const;
virtual NetECReal* dup_expr() const;
virtual NetExpr*evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*);
virtual NexusSet* nex_input(bool rem_out = true);
virtual NetExpr*evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
private:
verireal value_;
};
@ -2361,7 +2373,7 @@ class NetProc : public virtual LineInfo {
// identifiers to values. The function returns true if the
// processing succeeds, or false otherwise.
virtual bool evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
// This method is called by functors that want to scan a
// process in search of matchable patterns.
@ -2576,11 +2588,11 @@ class NetAssign : public NetAssignBase {
virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
virtual bool evaluate_function(const LineInfo&loc, std::map<perm_string,NetExpr*>&context_map) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
private:
bool eval_func_lval_(const LineInfo&loc,
std::map<perm_string,NetExpr*>&context_map,
bool eval_func_lval_(const LineInfo&loc, map<perm_string,LocalVar>&ctx,
const NetAssign_*lval, NetExpr*rval_result) const;
char op_;
@ -2631,7 +2643,7 @@ class NetBlock : public NetProc {
const NetProc*proc_next(const NetProc*cur) const;
bool evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
// synthesize as asynchronous logic, and return true.
bool synth_async(Design*des, NetScope*scope,
@ -2697,13 +2709,13 @@ class NetCase : public NetProc {
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual bool evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
private:
bool evaluate_function_vect_(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
bool evaluate_function_real_(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
TYPE type_;
@ -2777,7 +2789,7 @@ class NetCondit : public NetProc {
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
private:
NetExpr* expr_;
@ -2844,11 +2856,10 @@ 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;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
private:
NetScope*target_;
@ -3094,7 +3105,7 @@ class NetForever : public NetProc {
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual bool evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
private:
NetProc*statement_;
@ -3217,7 +3228,7 @@ class NetRepeat : public NetProc {
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual bool evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
private:
NetExpr*expr_;
@ -3263,13 +3274,12 @@ 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;
virtual void dump(ostream&, unsigned ind) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
private:
const char* name_;
@ -3343,7 +3353,7 @@ class NetEUFunc : public NetExpr {
virtual NexusSet* nex_input(bool rem_out = true);
virtual NetExpr* eval_tree();
virtual NetExpr*evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
virtual NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root);
@ -3429,7 +3439,7 @@ class NetWhile : public NetProc {
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
private:
NetExpr* cond_;
@ -3559,7 +3569,7 @@ class NetEBinary : public NetExpr {
virtual NetEBinary* dup_expr() const;
virtual NetExpr* eval_tree();
virtual NetExpr* evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const;
@ -3818,7 +3828,7 @@ class NetEConcat : public NetExpr {
virtual NetEConcat* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetExpr* evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*root);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -3866,7 +3876,7 @@ class NetESelect : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEConst* eval_tree();
virtual NetExpr*evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
virtual NetESelect* dup_expr() const;
virtual NetNet*synthesize(Design*des, NetScope*scope, NetExpr*root);
virtual void dump(ostream&) const;
@ -4034,7 +4044,7 @@ class NetESFunc : public NetExpr {
virtual NetExpr* eval_tree();
virtual NetExpr* evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
@ -4108,10 +4118,8 @@ class NetETernary : public NetExpr {
virtual NetETernary* dup_expr() const;
virtual NetExpr* eval_tree();
virtual NetExpr*evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const;
@ -4164,7 +4172,7 @@ class NetEUnary : public NetExpr {
virtual NetEUnary* dup_expr() const;
virtual NetExpr* eval_tree();
virtual NetExpr* evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
virtual ivl_variable_type_t expr_type() const;
@ -4247,7 +4255,7 @@ class NetESignal : public NetExpr {
netenum_t*enumeration() const;
virtual NetExpr*evaluate_function(const LineInfo&loc,
std::map<perm_string,NetExpr*>&ctx) const;
map<perm_string,LocalVar>&ctx) const;
// This is the expression for selecting an array word, if this
// signal refers to an array.