Handle system functions that return enumerations.

There are a few internal system functions that return enumeration
values, and the type checker needs to properly account for that.
This commit is contained in:
Stephen Williams 2010-11-07 15:02:42 -08:00
parent cc304ef0db
commit e1344745f8
5 changed files with 44 additions and 27 deletions

View File

@ -2238,7 +2238,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
} }
// Special case: The net is an enum, and the // 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") { if (netenum && method_name == "first") {
netenum_t::iterator item = netenum->first_name(); netenum_t::iterator item = netenum->first_name();
NetEConstEnum*tmp = new NetEConstEnum(scope, item->first, NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
@ -2254,10 +2255,18 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return tmp; return tmp;
} }
const char*func_name = 0; NetExpr*expr = elaborate_expr_net(des, scope, net, found_in, false);
if (method_name == "name") { NetESFunc*sys_expr = 0;
func_name = "$ivl_method$name";
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 { } else {
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
<< "Unknown method name `" << method_name << "'" << "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); return elaborate_expr_net(des, scope, net, found_in, false);
} }
NetESFunc*tmp = new NetESFunc(func_name, IVL_VT_STRING, 0, 1); sys_expr->set_line(*this);
tmp->parm(0, elaborate_expr_net(des, scope, net, found_in, false));
tmp->set_line(*this);
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: Generate " cerr << get_fileline() << ": debug: Generate "
<< func_name << "(" << use_path << ")" << endl; << sys_expr->name() << "(" << use_path << ")" << endl;
return tmp; return sys_expr;
} }
} }

View File

@ -1359,12 +1359,12 @@ NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
} }
NetEvWait*trigger = 0; NetEvWait*trigger = 0;
if (nparms_ == 0) { if (parms_.size() == 0) {
trigger = make_func_trigger(des, scope, root); trigger = make_func_trigger(des, scope, root);
} }
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(), NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
def, 1+nparms_, trigger); def, 1+parms_.size(), trigger);
net->set_line(*this); net->set_line(*this);
des->add_node(net); des->add_node(net);
@ -1378,7 +1378,7 @@ NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
connect(net->pin(0), osig->pin(0)); connect(net->pin(0), osig->pin(0));
unsigned errors = 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); NetNet*tmp = parms_[idx]->synthesize(des, scope, root);
if (tmp == 0) { if (tmp == 0) {
cerr << get_fileline() << ": error: Unable to elaborate " cerr << get_fileline() << ": error: Unable to elaborate "

View File

@ -19,6 +19,7 @@
# include "config.h" # include "config.h"
# include "netlist.h" # include "netlist.h"
# include "netenum.h"
# include "compiler.h" # include "compiler.h"
# include "netmisc.h" # include "netmisc.h"
# include <iostream> # include <iostream>
@ -586,22 +587,24 @@ bool NetESelect::has_width() const
NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t, NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
unsigned width, unsigned np) unsigned width, unsigned np)
: name_(0), type_(t) : name_(0), type_(t), enum_type_(0), parms_(np)
{ {
name_ = lex_strings.add(n); name_ = lex_strings.add(n);
expr_width(width); expr_width(width);
nparms_ = np; }
parms_ = new NetExpr*[np];
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) NetESFunc::NetESFunc(const char*n, netenum_t*enum_type, unsigned np)
parms_[idx] = 0; : 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() 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]; if (parms_[idx]) delete parms_[idx];
delete[]parms_;
/* name_ string ls lex_strings allocated. */ /* name_ string ls lex_strings allocated. */
} }
@ -612,12 +615,12 @@ const char* NetESFunc::name() const
unsigned NetESFunc::nparms() const unsigned NetESFunc::nparms() const
{ {
return nparms_; return parms_.size();
} }
void NetESFunc::parm(unsigned idx, NetExpr*v) void NetESFunc::parm(unsigned idx, NetExpr*v)
{ {
assert(idx < nparms_); assert(idx < parms_.size());
if (parms_[idx]) if (parms_[idx])
delete parms_[idx]; delete parms_[idx];
parms_[idx] = v; parms_[idx] = v;
@ -625,13 +628,13 @@ void NetESFunc::parm(unsigned idx, NetExpr*v)
const NetExpr* NetESFunc::parm(unsigned idx) const const NetExpr* NetESFunc::parm(unsigned idx) const
{ {
assert(idx < nparms_); assert(idx < parms_.size());
return parms_[idx]; return parms_[idx];
} }
NetExpr* NetESFunc::parm(unsigned idx) NetExpr* NetESFunc::parm(unsigned idx)
{ {
assert(idx < nparms_); assert(idx < parms_.size());
return parms_[idx]; return parms_[idx];
} }
@ -640,6 +643,11 @@ ivl_variable_type_t NetESFunc::expr_type() const
return type_; return type_;
} }
netenum_t* NetESFunc::enumeration() const
{
return enum_type_;
}
NetEAccess::NetEAccess(NetBranch*br, ivl_nature_t nat) NetEAccess::NetEAccess(NetBranch*br, ivl_nature_t nat)
: branch_(br), nature_(nat) : branch_(br), nature_(nat)
{ {

View File

@ -125,11 +125,11 @@ NexusSet* NetESelect::nex_input(bool rem_out)
NexusSet* NetESFunc::nex_input(bool rem_out) NexusSet* NetESFunc::nex_input(bool rem_out)
{ {
if (nparms_ == 0) if (parms_.size() == 0)
return new NexusSet; return new NexusSet;
NexusSet*result = parms_[0]->nex_input(rem_out); 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); NexusSet*tmp = parms_[idx]->nex_input(rem_out);
result->add(*tmp); result->add(*tmp);
delete tmp; delete tmp;

View File

@ -3748,6 +3748,7 @@ class NetESFunc : public NetExpr {
public: public:
NetESFunc(const char*name, ivl_variable_type_t t, NetESFunc(const char*name, ivl_variable_type_t t,
unsigned width, unsigned nprms); unsigned width, unsigned nprms);
NetESFunc(const char*name, netenum_t*enum_type, unsigned nprms);
~NetESFunc(); ~NetESFunc();
const char* name() const; const char* name() const;
@ -3762,6 +3763,7 @@ class NetESFunc : public NetExpr {
virtual ivl_variable_type_t expr_type() const; virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true); virtual NexusSet* nex_input(bool rem_out = true);
virtual bool set_width(unsigned, bool last_chance); virtual bool set_width(unsigned, bool last_chance);
virtual netenum_t* enumeration() const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
@ -3771,8 +3773,8 @@ class NetESFunc : public NetExpr {
private: private:
const char* name_; const char* name_;
ivl_variable_type_t type_; ivl_variable_type_t type_;
unsigned nparms_; netenum_t*enum_type_;
NetExpr**parms_; std::vector<NetExpr*>parms_;
private: // not implemented private: // not implemented
NetESFunc(const NetESFunc&); NetESFunc(const NetESFunc&);