Add support for implict this in class methods
This commit is contained in:
parent
d16a9dcfc6
commit
d85096c56a
3
PExpr.h
3
PExpr.h
|
|
@ -936,7 +936,8 @@ class PECallFunction : public PExpr {
|
||||||
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
|
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid, unsigned flags)const;
|
unsigned expr_wid, unsigned flags)const;
|
||||||
NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
|
NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid) const;
|
unsigned expr_wid,
|
||||||
|
bool add_this_flag = false) const;
|
||||||
#if 0
|
#if 0
|
||||||
NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
|
NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const;
|
||||||
NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope,
|
NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope,
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,8 @@ class PCallTask : public Statement {
|
||||||
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
||||||
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
NetProc*elaborate_method_(Design*des, NetScope*scope) const;
|
NetProc*elaborate_method_(Design*des, NetScope*scope,
|
||||||
|
bool add_this_flag = false) const;
|
||||||
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
|
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
|
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
|
||||||
|
|
|
||||||
28
elab_expr.cc
28
elab_expr.cc
|
|
@ -2064,11 +2064,24 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ivl_assert(*this, def);
|
|
||||||
|
|
||||||
|
ivl_assert(*this, def);
|
||||||
NetScope*dscope = def->scope();
|
NetScope*dscope = def->scope();
|
||||||
ivl_assert(*this, dscope);
|
ivl_assert(*this, dscope);
|
||||||
|
|
||||||
|
/* In SystemVerilog a method calling another method in the
|
||||||
|
* current class needs to be elaborated as a method with an
|
||||||
|
* implicit this added. */
|
||||||
|
if (gn_system_verilog() && (path_.size() == 1)) {
|
||||||
|
const NetScope *c_scope = scope->get_class_scope();
|
||||||
|
if (c_scope && (c_scope == dscope->get_class_scope())) {
|
||||||
|
NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid,
|
||||||
|
true);
|
||||||
|
assert(tmp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool need_const = NEED_CONST & flags;
|
bool need_const = NEED_CONST & flags;
|
||||||
|
|
||||||
// It is possible to get here before the called function has been
|
// It is possible to get here before the called function has been
|
||||||
|
|
@ -2262,17 +2275,22 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
unsigned expr_wid) const
|
unsigned expr_wid,
|
||||||
|
bool add_this_flag) const
|
||||||
{
|
{
|
||||||
pform_name_t use_path = path_;
|
pform_name_t use_path = path_;
|
||||||
perm_string method_name = peek_tail_name(use_path);
|
perm_string method_name = peek_tail_name(use_path);
|
||||||
use_path.pop_back();
|
use_path.pop_back();
|
||||||
|
|
||||||
|
/* Add the implicit this reference when requested. */
|
||||||
|
if (add_this_flag) {
|
||||||
|
assert(use_path.empty());
|
||||||
|
use_path.push_front(name_component_t(perm_string::literal("@")));
|
||||||
|
}
|
||||||
|
|
||||||
// If there is no object to the left of the method name, then
|
// If there is no object to the left of the method name, then
|
||||||
// give up on the idea of looking for an object method.
|
// give up on the idea of looking for an object method.
|
||||||
if (use_path.empty()) {
|
if (use_path.empty()) return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetNet *net = 0;
|
NetNet *net = 0;
|
||||||
const NetExpr *par;
|
const NetExpr *par;
|
||||||
|
|
|
||||||
20
elaborate.cc
20
elaborate.cc
|
|
@ -3439,6 +3439,17 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||||
}
|
}
|
||||||
assert(def);
|
assert(def);
|
||||||
|
|
||||||
|
/* In SystemVerilog a method calling another method in the
|
||||||
|
* current class needs to be elaborated as a method with an
|
||||||
|
* implicit this added. */
|
||||||
|
if (gn_system_verilog() && (path_.size() == 1)) {
|
||||||
|
const NetScope *c_scope = scope->get_class_scope();
|
||||||
|
if (c_scope && (c_scope == task->get_class_scope())) {
|
||||||
|
NetProc *tmp = elaborate_method_(des, scope, true);
|
||||||
|
assert(tmp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned parm_count = def->port_count();
|
unsigned parm_count = def->port_count();
|
||||||
|
|
||||||
|
|
@ -3490,7 +3501,8 @@ NetProc* PCallTask::elaborate_sys_task_method_(Design*des, NetScope*scope,
|
||||||
return sys;
|
return sys;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
|
NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
|
bool add_this_flag) const
|
||||||
{
|
{
|
||||||
pform_name_t use_path = path_;
|
pform_name_t use_path = path_;
|
||||||
perm_string method_name = peek_tail_name(use_path);
|
perm_string method_name = peek_tail_name(use_path);
|
||||||
|
|
@ -3501,6 +3513,12 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope) const
|
||||||
NetEvent *eve;
|
NetEvent *eve;
|
||||||
const NetExpr *ex1, *ex2;
|
const NetExpr *ex1, *ex2;
|
||||||
|
|
||||||
|
/* Add the implicit this reference when requested. */
|
||||||
|
if (add_this_flag) {
|
||||||
|
assert(use_path.empty());
|
||||||
|
use_path.push_front(name_component_t(perm_string::literal("@")));
|
||||||
|
}
|
||||||
|
|
||||||
// There is no signal to search for so this cannot be a method.
|
// There is no signal to search for so this cannot be a method.
|
||||||
if (use_path.empty()) return 0;
|
if (use_path.empty()) return 0;
|
||||||
|
|
||||||
|
|
|
||||||
26
net_scope.cc
26
net_scope.cc
|
|
@ -691,6 +691,32 @@ const NetScope* NetScope::child(const hname_t&name) const
|
||||||
return cur->second;
|
return cur->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function to see if the given scope is defined in a class and if
|
||||||
|
* so return the class scope. */
|
||||||
|
const NetScope* NetScope::get_class_scope() const
|
||||||
|
{
|
||||||
|
const NetScope*scope = this;
|
||||||
|
while (scope) {
|
||||||
|
switch(scope->type()) {
|
||||||
|
case NetScope::CLASS:
|
||||||
|
return scope;
|
||||||
|
case NetScope::TASK:
|
||||||
|
case NetScope::FUNC:
|
||||||
|
case NetScope::BEGIN_END:
|
||||||
|
case NetScope::FORK_JOIN:
|
||||||
|
break;
|
||||||
|
case NetScope::MODULE:
|
||||||
|
case NetScope::GENBLOCK:
|
||||||
|
case NetScope::PACKAGE:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
scope = scope->parent();
|
||||||
|
}
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
const NetScope* NetScope::child_byname(perm_string name) const
|
const NetScope* NetScope::child_byname(perm_string name) const
|
||||||
{
|
{
|
||||||
hname_t hname (name);
|
hname_t hname (name);
|
||||||
|
|
|
||||||
|
|
@ -995,6 +995,9 @@ class NetScope : public Definitions, public Attrib {
|
||||||
const NetScope* parent() const { return up_; }
|
const NetScope* parent() const { return up_; }
|
||||||
const NetScope* child(const hname_t&name) const;
|
const NetScope* child(const hname_t&name) const;
|
||||||
|
|
||||||
|
/* A helper function to find the enclosing class scope. */
|
||||||
|
const NetScope* get_class_scope() const;
|
||||||
|
|
||||||
// Look for a child scope by name. This ignores the number
|
// Look for a child scope by name. This ignores the number
|
||||||
// part of the child scope name, so there may be multiple
|
// part of the child scope name, so there may be multiple
|
||||||
// matches. Only return one. This function is only really
|
// matches. Only return one. This function is only really
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue