diff --git a/elab_expr.cc b/elab_expr.cc index b41c43741..b8020cab7 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2238,7 +2238,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, } // Special case: The net is an enum, and the - // method name is "first". + // method name is "first" or "last". These + // evaluate to constant values. if (netenum && method_name == "first") { netenum_t::iterator item = netenum->first_name(); NetEConstEnum*tmp = new NetEConstEnum(scope, item->first, @@ -2254,10 +2255,18 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, return tmp; } - const char*func_name = 0; - if (method_name == "name") { - func_name = "$ivl_method$name"; + NetExpr*expr = elaborate_expr_net(des, scope, net, found_in, false); + NetESFunc*sys_expr = 0; + if (method_name == "name") { + sys_expr = new NetESFunc("$ivl_method$name", IVL_VT_STRING,0, 1); + sys_expr->parm(0, expr); + } else if (method_name == "next") { + sys_expr = new NetESFunc("$ivl_method$next", netenum, 1); + sys_expr->parm(0, expr); + } else if (method_name == "prev") { + sys_expr = new NetESFunc("$ivl_method$prev", netenum, 1); + sys_expr->parm(0, expr); } else { cerr << get_fileline() << ": error: " << "Unknown method name `" << method_name << "'" @@ -2266,14 +2275,12 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, return elaborate_expr_net(des, scope, net, found_in, false); } - NetESFunc*tmp = new NetESFunc(func_name, IVL_VT_STRING, 0, 1); - tmp->parm(0, elaborate_expr_net(des, scope, net, found_in, false)); - tmp->set_line(*this); + sys_expr->set_line(*this); if (debug_elaborate) cerr << get_fileline() << ": debug: Generate " - << func_name << "(" << use_path << ")" << endl; - return tmp; + << sys_expr->name() << "(" << use_path << ")" << endl; + return sys_expr; } } diff --git a/expr_synth.cc b/expr_synth.cc index d8dc402ee..86f75e9fa 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1359,12 +1359,12 @@ NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root) } NetEvWait*trigger = 0; - if (nparms_ == 0) { + if (parms_.size() == 0) { trigger = make_func_trigger(des, scope, root); } NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(), - def, 1+nparms_, trigger); + def, 1+parms_.size(), trigger); net->set_line(*this); des->add_node(net); @@ -1378,7 +1378,7 @@ NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root) connect(net->pin(0), osig->pin(0)); unsigned errors = 0; - for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) { + for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { NetNet*tmp = parms_[idx]->synthesize(des, scope, root); if (tmp == 0) { cerr << get_fileline() << ": error: Unable to elaborate " diff --git a/net_expr.cc b/net_expr.cc index d0a667c16..e27e23ab5 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -19,6 +19,7 @@ # include "config.h" # include "netlist.h" +# include "netenum.h" # include "compiler.h" # include "netmisc.h" # include @@ -586,22 +587,24 @@ bool NetESelect::has_width() const NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t, unsigned width, unsigned np) -: name_(0), type_(t) +: name_(0), type_(t), enum_type_(0), parms_(np) { name_ = lex_strings.add(n); expr_width(width); - nparms_ = np; - parms_ = new NetExpr*[np]; - for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) - parms_[idx] = 0; +} + +NetESFunc::NetESFunc(const char*n, netenum_t*enum_type, unsigned np) +: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np) +{ + name_ = lex_strings.add(n); + expr_width(enum_type->base_width()); } NetESFunc::~NetESFunc() { - for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) + for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) if (parms_[idx]) delete parms_[idx]; - delete[]parms_; /* name_ string ls lex_strings allocated. */ } @@ -612,12 +615,12 @@ const char* NetESFunc::name() const unsigned NetESFunc::nparms() const { - return nparms_; + return parms_.size(); } void NetESFunc::parm(unsigned idx, NetExpr*v) { - assert(idx < nparms_); + assert(idx < parms_.size()); if (parms_[idx]) delete parms_[idx]; parms_[idx] = v; @@ -625,13 +628,13 @@ void NetESFunc::parm(unsigned idx, NetExpr*v) const NetExpr* NetESFunc::parm(unsigned idx) const { - assert(idx < nparms_); + assert(idx < parms_.size()); return parms_[idx]; } NetExpr* NetESFunc::parm(unsigned idx) { - assert(idx < nparms_); + assert(idx < parms_.size()); return parms_[idx]; } @@ -640,6 +643,11 @@ ivl_variable_type_t NetESFunc::expr_type() const return type_; } +netenum_t* NetESFunc::enumeration() const +{ + return enum_type_; +} + NetEAccess::NetEAccess(NetBranch*br, ivl_nature_t nat) : branch_(br), nature_(nat) { diff --git a/net_nex_input.cc b/net_nex_input.cc index 2da521912..5c7d7a27a 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -125,11 +125,11 @@ NexusSet* NetESelect::nex_input(bool rem_out) NexusSet* NetESFunc::nex_input(bool rem_out) { - if (nparms_ == 0) + if (parms_.size() == 0) return new NexusSet; NexusSet*result = parms_[0]->nex_input(rem_out); - for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) { + for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) { NexusSet*tmp = parms_[idx]->nex_input(rem_out); result->add(*tmp); delete tmp; diff --git a/netlist.h b/netlist.h index 02479052a..6304b75fa 100644 --- a/netlist.h +++ b/netlist.h @@ -3748,6 +3748,7 @@ class NetESFunc : public NetExpr { public: NetESFunc(const char*name, ivl_variable_type_t t, unsigned width, unsigned nprms); + NetESFunc(const char*name, netenum_t*enum_type, unsigned nprms); ~NetESFunc(); const char* name() const; @@ -3762,6 +3763,7 @@ class NetESFunc : public NetExpr { virtual ivl_variable_type_t expr_type() const; virtual NexusSet* nex_input(bool rem_out = true); virtual bool set_width(unsigned, bool last_chance); + virtual netenum_t* enumeration() const; virtual void dump(ostream&) const; virtual void expr_scan(struct expr_scan_t*) const; @@ -3771,8 +3773,8 @@ class NetESFunc : public NetExpr { private: const char* name_; ivl_variable_type_t type_; - unsigned nparms_; - NetExpr**parms_; + netenum_t*enum_type_; + std::vectorparms_; private: // not implemented NetESFunc(const NetESFunc&);