Rework PEIdent::elaborate_expr() to use new-style symbol_search().

This commit is contained in:
Martin Whitaker 2021-07-31 13:19:12 +01:00
parent b9863b4fde
commit e547a8355d
1 changed files with 66 additions and 97 deletions

View File

@ -4516,13 +4516,7 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const unsigned expr_wid, unsigned flags) const
{ {
assert(scope); ivl_assert(*this, scope);
NetNet* net = 0;
ivl_type_t cls_val = 0;
const NetExpr*par = 0;
ivl_type_t par_type = 0;
NetEvent* eve = 0;
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: " cerr << get_fileline() << ": PEIdent::elaborate_expr: "
@ -4567,53 +4561,27 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
ivl_assert(*this, use_scope); ivl_assert(*this, use_scope);
} }
// Find the net/parameter/event object that this name refers // Find the net/parameter/event object that this name refers
// to. The path_ may be a scoped path, and may include method // to. The path_ may be a scoped path, and may include method
// or member name parts. For example, main.a.b.c may refer to // or member name parts. For example, main.a.b.c may refer to
// a net called "b" in the scope "main.a" and with a member // a net called "b" in the scope "main.a" and with a member
// named "c". This loop tries to figure that out and the // named "c". symbol_search() handles this for us.
// result is the complete path_ split into a base_path (that symbol_search_results sr;
// locates the object) and the member_path that selects parts symbol_search(this, des, use_scope, path_, &sr);
// in the object.
pform_name_t base_path = path_;
pform_name_t member_path;
NetScope*found_in = 0;
while (net==0 && par==0 && eve==0 && !base_path.empty()) {
found_in = symbol_search(this, des, use_scope, base_path,
net, par, eve, par_type, cls_val);
if (net) break;
if (par) break;
if (eve) break;
// Not found. Try to pop another name off the base_path
// and push it to the front of the member path.
member_path.push_front( base_path.back() );
base_path.pop_back();
}
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Symbol search found base_path=" << base_path
<< ", member_path=" << member_path
<< ", par=" << par
<< ", net=" << net
<< ", eve=" << eve
<< endl;
}
// If the identifier name is a parameter name, then return // If the identifier name is a parameter name, then return
// the parameter value. // the parameter value.
if (par != 0) { if (sr.par_val != 0) {
if (!member_path.empty()) { if (!sr.path_tail.empty()) {
cerr << get_fileline() << ": error: Paramater name " << base_path cerr << get_fileline() << ": error: Parameter name "
<< " can't have member names (member_path=" << member_path << ")." << sr.path_head << " can't have member names ("
<< endl; << sr.path_tail << ")." << endl;
des->errors += 1; des->errors += 1;
} }
NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in, NetExpr*tmp = elaborate_expr_param_(des, scope, sr.par_val, sr.scope,
par_type, expr_wid, flags); sr.par_type, expr_wid, flags);
if (!tmp) return 0; if (!tmp) return 0;
@ -4622,7 +4590,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// If the identifier names a signal (a variable or a net) // If the identifier names a signal (a variable or a net)
// then create a NetESignal node to handle it. // then create a NetESignal node to handle it.
if (net != 0) { if (sr.net != 0) {
if (NEED_CONST & flags) { if (NEED_CONST & flags) {
cerr << get_fileline() << ": error: A reference to a wire " cerr << get_fileline() << ": error: A reference to a wire "
"or reg (`" << path_ << "') is not allowed in " "or reg (`" << path_ << "') is not allowed in "
@ -4630,7 +4598,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
if (net->scope()->type() == NetScope::MODULE) { if (sr.net->scope()->type() == NetScope::MODULE) {
if (scope->need_const_func()) { if (scope->need_const_func()) {
cerr << get_fileline() << ": error: A reference to a " cerr << get_fileline() << ": error: A reference to a "
"non-local wire or reg (`" << path_ << "') is " "non-local wire or reg (`" << path_ << "') is "
@ -4644,39 +4612,39 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// If this is a struct, and there are members in the // If this is a struct, and there are members in the
// member_path, then generate an expression that // member_path, then generate an expression that
// reflects the member selection. // reflects the member selection.
if (net->struct_type() && !member_path.empty()) { if (sr.net->struct_type() && !sr.path_tail.empty()) {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: " cerr << get_fileline() << ": PEIdent::elaborate_expr: "
"Ident " << base_path "Ident " << sr.path_head
<< " look for struct member " << member_path << " look for struct member " << sr.path_tail
<< endl; << endl;
} }
NetExpr*tmp = check_for_struct_members(this, des, use_scope, NetExpr*tmp = check_for_struct_members(this, des, use_scope,
net, base_path.back().index, sr.net, sr.path_head.back().index,
member_path); sr.path_tail);
if (!tmp) return 0; if (!tmp) return 0;
else return pad_to_width(tmp, expr_wid, signed_flag_, *this); else return pad_to_width(tmp, expr_wid, signed_flag_, *this);
} }
// If this is an array object, and there are members in // If this is an array object, and there are members in
// the member_path, check for array properties. // the sr.path_tail, check for array properties.
if (net->darray_type() && !member_path.empty()) { if (sr.net->darray_type() && !sr.path_tail.empty()) {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: " cerr << get_fileline() << ": PEIdent::elaborate_expr: "
"Ident " << base_path "Ident " << sr.path_head
<< " looking for array property " << member_path << " looking for array property " << sr.path_tail
<< endl; << endl;
} }
ivl_assert(*this, member_path.size() == 1); ivl_assert(*this, sr.path_tail.size() == 1);
const name_component_t member_comp = member_path.front(); const name_component_t member_comp = sr.path_tail.front();
if (member_comp.name == "size") { if (member_comp.name == "size") {
NetESFunc*fun = new NetESFunc("$size", IVL_VT_BOOL, 32, 1); NetESFunc*fun = new NetESFunc("$size", IVL_VT_BOOL, 32, 1);
fun->set_line(*this); fun->set_line(*this);
NetESignal*arg = new NetESignal(net); NetESignal*arg = new NetESignal(sr.net);
arg->set_line(*net); arg->set_line(*sr.net);
fun->parm(0, arg); fun->parm(0, arg);
return fun; return fun;
@ -4776,18 +4744,18 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
} }
// If this is a queue object, and there are members in // If this is a queue object, and there are members in
// the member_path, check for array properties. // the sr.path_tail, check for array properties.
if (net->queue_type() && !member_path.empty()) { if (sr.net->queue_type() && !sr.path_tail.empty()) {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: " cerr << get_fileline() << ": PEIdent::elaborate_expr: "
<< "Ident " << base_path << "Ident " << sr.path_head
<< " looking for queue property " << member_path << " looking for queue property " << sr.path_tail
<< endl; << endl;
} }
ivl_assert(*this, member_path.size() == 1); ivl_assert(*this, sr.path_tail.size() == 1);
const name_component_t member_comp = member_path.front(); const name_component_t member_comp = sr.path_tail.front();
const netqueue_t*queue = net->queue_type(); const netqueue_t*queue = sr.net->queue_type();
ivl_variable_type_t qelem_type = queue->element_base_type(); ivl_variable_type_t qelem_type = queue->element_base_type();
unsigned qelem_width = queue->element_width(); unsigned qelem_width = queue->element_width();
if (member_comp.name == "pop_back") { if (member_comp.name == "pop_back") {
@ -4795,8 +4763,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
qelem_type, qelem_width, 1); qelem_type, qelem_width, 1);
fun->set_line(*this); fun->set_line(*this);
NetESignal*arg = new NetESignal(net); NetESignal*arg = new NetESignal(sr.net);
arg->set_line(*net); arg->set_line(*sr.net);
fun->parm(0, arg); fun->parm(0, arg);
return fun; return fun;
@ -4807,24 +4775,24 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
qelem_type, qelem_width, 1); qelem_type, qelem_width, 1);
fun->set_line(*this); fun->set_line(*this);
NetESignal*arg = new NetESignal(net); NetESignal*arg = new NetESignal(sr.net);
arg->set_line(*net); arg->set_line(*sr.net);
fun->parm(0, arg); fun->parm(0, arg);
return fun; return fun;
} }
} }
if ((net->data_type() == IVL_VT_STRING) && !member_path.empty()) { if ((sr.net->data_type() == IVL_VT_STRING) && !sr.path_tail.empty()) {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: " cerr << get_fileline() << ": PEIdent::elaborate_expr: "
"Ident " << base_path "Ident " << sr.path_head
<< " looking for string property " << member_path << " looking for string property " << sr.path_tail
<< endl; << endl;
} }
ivl_assert(*this, member_path.size() == 1); ivl_assert(*this, sr.path_tail.size() == 1);
const name_component_t member_comp = member_path.front(); const name_component_t member_comp = sr.path_tail.front();
cerr << get_fileline() << ": sorry: String method '" cerr << get_fileline() << ": sorry: String method '"
<< member_comp.name << "' currently requires ()." << member_comp.name << "' currently requires ()."
<< endl; << endl;
@ -4832,41 +4800,42 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return 0; return 0;
} }
if (net->class_type() && !member_path.empty()) { if (sr.net->class_type() && !sr.path_tail.empty()) {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: " cerr << get_fileline() << ": PEIdent::elaborate_expr: "
"Ident " << base_path "Ident " << sr.path_head
<< " look for class property " << member_path << " look for class property " << sr.path_tail
<< endl; << endl;
} }
ivl_assert(*this, member_path.size() == 1); ivl_assert(*this, sr.path_tail.size() == 1);
const name_component_t member_comp = member_path.front(); const name_component_t member_comp = sr.path_tail.front();
return check_for_class_property(this, des, use_scope, return check_for_class_property(this, des, use_scope,
net, member_comp); sr.net, member_comp);
} }
if (net->enumeration() && !member_path.empty()) { if (sr.net->enumeration() && !sr.path_tail.empty()) {
const netenum_t*netenum = net->enumeration(); const netenum_t*netenum = sr.net->enumeration();
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_expr: " cerr << get_fileline() << ": PEIdent::elaborate_expr: "
"Ident " << base_path "Ident " << sr.path_head
<< " look for enumeration method " << member_path << " look for enumeration method " << sr.path_tail
<< endl; << endl;
} }
NetESignal*expr = new NetESignal(net); NetESignal*expr = new NetESignal(sr.net);
expr->set_line(*this); expr->set_line(*this);
ivl_assert(*this, member_path.size() == 1); ivl_assert(*this, sr.path_tail.size() == 1);
const name_component_t member_comp = member_path.front(); const name_component_t member_comp = sr.path_tail.front();
ivl_assert(*this, member_comp.index.empty()); ivl_assert(*this, member_comp.index.empty());
return check_for_enum_methods(this, des, use_scope, return check_for_enum_methods(this, des, use_scope,
netenum, base_path, member_comp.name, netenum, sr.path_head,
member_comp.name,
expr, expr_wid, NULL, 0); expr, expr_wid, NULL, 0);
} }
ivl_assert(*this, member_path.empty()); ivl_assert(*this, sr.path_tail.empty());
NetExpr*tmp = elaborate_expr_net(des, scope, net, found_in, NetExpr*tmp = elaborate_expr_net(des, scope, sr.net, sr.scope,
expr_wid, flags); expr_wid, flags);
if (!tmp) return 0; if (!tmp) return 0;
@ -4883,7 +4852,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// If the identifier is a named event // If the identifier is a named event
// then create a NetEEvent node to handle it. // then create a NetEEvent node to handle it.
if (eve != 0) { if (sr.eve != 0) {
if (NEED_CONST & flags) { if (NEED_CONST & flags) {
cerr << get_fileline() << ": error: A reference to a named " cerr << get_fileline() << ": error: A reference to a named "
"event (`" << path_ << "') is not allowed in a " "event (`" << path_ << "') is not allowed in a "
@ -4891,7 +4860,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
if (eve->scope() != scope) { if (sr.eve->scope() != scope) {
if (scope->need_const_func()) { if (scope->need_const_func()) {
cerr << get_fileline() << ": error: A reference to a " cerr << get_fileline() << ": error: A reference to a "
"non-local named event (`" << path_ << "') is " "non-local named event (`" << path_ << "') is "
@ -4902,14 +4871,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
scope->is_const_func(false); scope->is_const_func(false);
} }
if (!member_path.empty()) { if (!sr.path_tail.empty()) {
cerr << get_fileline() << ": error: Event name " << base_path cerr << get_fileline() << ": error: Event name "
<< " can't have member names (member_path=" << member_path << ")" << sr.path_head << " can't have member names ("
<< endl; << sr.path_tail << ")" << endl;
des->errors += 1; des->errors += 1;
} }
NetEEvent*tmp = new NetEEvent(eve); NetEEvent*tmp = new NetEEvent(sr.eve);
tmp->set_line(*this); tmp->set_line(*this);
return tmp; return tmp;
} }