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:
parent
cc304ef0db
commit
e1344745f8
25
elab_expr.cc
25
elab_expr.cc
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 "
|
||||||
|
|
|
||||||
30
net_expr.cc
30
net_expr.cc
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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&);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue