Merge pull request #459 from steveicarus/steveicarus/string-name-method
Implement the enum.name() method
This commit is contained in:
commit
407627f4e6
136
elab_expr.cc
136
elab_expr.cc
|
|
@ -1205,8 +1205,8 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
|||
signed_flag_ = false;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: test_width"
|
||||
<< " of " << name << " returns test_width"
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "test_width of " << name << " returns test_width"
|
||||
<< " of compiler integer." << endl;
|
||||
|
||||
return expr_width_;
|
||||
|
|
@ -1228,8 +1228,8 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
|||
signed_flag_ = false;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: test_width"
|
||||
<< " of $is_signed returns test_width"
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "test_width of $is_signed returns test_width"
|
||||
<< " of 1." << endl;
|
||||
|
||||
return expr_width_;
|
||||
|
|
@ -1247,8 +1247,8 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
|||
is_overridden_ = sfunc_info->override_flag;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: test_width "
|
||||
<< "of system function " << name
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "test_width of system function " << name
|
||||
<< " returns wid=" << expr_width_
|
||||
<< ", type=" << expr_type_ << "." << endl;
|
||||
|
||||
|
|
@ -1279,16 +1279,16 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope,
|
|||
|
||||
if (test_width_method_(des, scope, mode)) {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: test_width "
|
||||
<< "of method returns width " << expr_width_
|
||||
cerr << get_fileline() << ": PECallFunction::" << __func__ << ": "
|
||||
<< "test_width of method returns width " << expr_width_
|
||||
<< ", type=" << expr_type_
|
||||
<< "." << endl;
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: test_width "
|
||||
<< "cannot find definition of " << path_
|
||||
cerr << get_fileline() << ": PECallFunction::" << __func__ << ": "
|
||||
<< "test_width cannot find definition of " << path_
|
||||
<< " in " << scope_path(scope) << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1303,8 +1303,8 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope,
|
|||
signed_flag_ = res->get_signed();
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: test_width "
|
||||
<< "of function returns width " << expr_width_
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "test_width of function returns width " << expr_width_
|
||||
<< ", type=" << expr_type_
|
||||
<< "." << endl;
|
||||
|
||||
|
|
@ -1331,6 +1331,13 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
|||
perm_string method_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "use_path=" << use_path
|
||||
<< ", method_name=" << method_name
|
||||
<< endl;
|
||||
}
|
||||
|
||||
NetNet *net = 0;
|
||||
const NetExpr *par;
|
||||
ivl_type_t par_type = 0;
|
||||
|
|
@ -1338,6 +1345,16 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
|||
|
||||
symbol_search(this, des, scope, use_path, net, par, eve, par_type);
|
||||
|
||||
if (debug_elaborate && net!=0) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "net=" << net->name() << endl;
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "net->data_type()=" << net->data_type() << endl;
|
||||
if (net->net_type())
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "net->net_type()=" << *net->net_type() << endl;
|
||||
}
|
||||
|
||||
const netdarray_t*use_darray = 0;
|
||||
|
||||
if (net != 0)
|
||||
|
|
@ -1421,6 +1438,33 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
// If the net is an enumeration, and the method is one of the standard
|
||||
// methods, then we know the size.
|
||||
if (const netenum_t*enum_type = net->enumeration()) {
|
||||
if (method_name=="first" || method_name=="last"
|
||||
|| method_name=="prev" || method_name=="next") {
|
||||
expr_type_ = IVL_VT_BOOL;
|
||||
expr_width_ = enum_type->packed_width();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_= enum_type->get_signed();
|
||||
return expr_width_;
|
||||
}
|
||||
if (method_name=="num") {
|
||||
expr_type_ = IVL_VT_BOOL;
|
||||
expr_width_ = 32;
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_= true;
|
||||
return expr_width_;
|
||||
}
|
||||
if (method_name=="name") {
|
||||
expr_type_ = IVL_VT_STRING;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
signed_flag_= false;
|
||||
return expr_width_;
|
||||
}
|
||||
}
|
||||
|
||||
if (const netclass_t*class_type = net->class_type()) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
|
||||
|
|
@ -1733,8 +1777,27 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
unsigned rtn_wid,
|
||||
PExpr*parg, unsigned args)
|
||||
{
|
||||
// The "num()" method returns the number of elements.
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": " << __func__ << ": "
|
||||
<< "Check for method " << method_name
|
||||
<< " of enumeration at " << netenum->get_fileline()
|
||||
<< endl;
|
||||
cerr << li->get_fileline() << ": " << __func__ << ": "
|
||||
<< "use_path=" << use_path << endl;
|
||||
cerr << li->get_fileline() << ": " << __func__ << ": "
|
||||
<< "rtn_wid=" << rtn_wid << endl;
|
||||
cerr << li->get_fileline() << ": " << __func__ << ": "
|
||||
<< "expr=" << *expr << endl;
|
||||
}
|
||||
|
||||
// First, look for some special methods that can be replace with
|
||||
// constant literals. These get properties of the enumeration type, and
|
||||
// so can be fully evaluated at compile time.
|
||||
|
||||
if (method_name == "num") {
|
||||
// The "num()" method returns the number of elements. This is
|
||||
// actually a static constant, and can be replaced at compile time
|
||||
// with a constant value.
|
||||
if (args != 0) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".num() does not "
|
||||
|
|
@ -1747,8 +1810,10 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
// The "first()" method returns the first enumeration value.
|
||||
if (method_name == "first") {
|
||||
// The "first()" method returns the first enumeration value. This
|
||||
// doesn't actually care about the constant value, and instead
|
||||
// returns as a constant literal the first value of the enumeration.
|
||||
if (args != 0) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".first() does not "
|
||||
|
|
@ -1763,8 +1828,10 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
// The "last()" method returns the first enumeration value.
|
||||
if (method_name == "last") {
|
||||
// The "last()" method returns the first enumeration value. This
|
||||
// doesn't actually care about the constant value, and instead
|
||||
// returns as a constant literal the last value of the enumeration.
|
||||
if (args != 0) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".last() does not "
|
||||
|
|
@ -1801,32 +1868,27 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
}
|
||||
}
|
||||
|
||||
// The "name()" method returns the name of the current
|
||||
// enumeration value.
|
||||
if (method_name == "name") {
|
||||
// The "name()" method returns the name of the current enumeration
|
||||
// value. The generated system task takes the enumeration
|
||||
// definition and the enumeration value. The return value is the
|
||||
// string name of the enumeration.
|
||||
if (args != 0) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".name() does not "
|
||||
"take an argument." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
sys_expr = new NetESFunc("$ivl_enum_method$name", IVL_VT_STRING,
|
||||
rtn_wid, 2);
|
||||
|
||||
// Generate the internal system function. Make sure the return
|
||||
// value is "string" type.
|
||||
sys_expr = new NetESFunc("$ivl_enum_method$name",
|
||||
&netstring_t::type_string, 2);
|
||||
sys_expr->parm(0, new NetENetenum(netenum));
|
||||
sys_expr->parm(1, expr);
|
||||
|
||||
/* The compiler/code generators need to be fixed to support a
|
||||
* string return value. In some contexts we could use the
|
||||
* expression width, but that doesn't always work. */
|
||||
if (rtn_wid == 0) {
|
||||
cerr << li->get_fileline() << ": sorry: Enumeration method "
|
||||
"name() is not currently supported in this context "
|
||||
"(self-determined)." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// The "next()" method returns the next enumeration value.
|
||||
} else if (method_name == "next") {
|
||||
// The "next()" method returns the next enumeration value.
|
||||
if (args > 1) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".next() take at "
|
||||
|
|
@ -1839,8 +1901,8 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
sys_expr->parm(1, expr);
|
||||
if (args != 0) sys_expr->parm(2, count);
|
||||
|
||||
// The "prev()" method returns the previous enumeration value.
|
||||
} else if (method_name == "prev") {
|
||||
// The "prev()" method returns the previous enumeration value.
|
||||
if (args > 1) {
|
||||
cerr << li->get_fileline() << ": error: enumeration "
|
||||
"method " << use_path << ".prev() take at "
|
||||
|
|
@ -1853,8 +1915,8 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
sys_expr->parm(1, expr);
|
||||
if (args != 0) sys_expr->parm(2, count);
|
||||
|
||||
// This is an unknown enumeration method.
|
||||
} else {
|
||||
// This is an unknown enumeration method.
|
||||
cerr << li->get_fileline() << ": error: Unknown enumeration "
|
||||
"method " << use_path << "." << method_name << "()."
|
||||
<< endl;
|
||||
|
|
@ -1865,7 +1927,7 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
sys_expr->set_line(*li);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": debug: Generate "
|
||||
cerr << li->get_fileline() << ": " << __func__ << ": Generate "
|
||||
<< sys_expr->name() << "(" << use_path << ")" << endl;
|
||||
}
|
||||
|
||||
|
|
@ -4927,8 +4989,12 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Parameter: " << path_ << endl;
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "par_type: " << *par_type << endl;
|
||||
if (par_type)
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "par_type: " << *par_type << endl;
|
||||
else
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "par_type: <nil>" << endl;
|
||||
}
|
||||
|
||||
if (need_const && !(ANNOTATABLE & flags)) {
|
||||
|
|
|
|||
18
elab_lval.cc
18
elab_lval.cc
|
|
@ -222,13 +222,23 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
ivl_assert(*this, reg);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Found l-value path_=" << path_
|
||||
<< " as reg=" << reg->name()
|
||||
<< ", reg->type()=" << reg->type()
|
||||
<< " as reg=" << reg->name() << endl;
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "reg->type()=" << reg->type()
|
||||
<< ", reg->unpacked_dimensions()=" << reg->unpacked_dimensions()
|
||||
<< endl;
|
||||
if (reg->net_type())
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "reg->net_type()=" << *reg->net_type() << endl;
|
||||
else
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "reg->net_type()=<nil>" << endl;
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< " base_path=" << base_path
|
||||
<< ", member_path=" << member_path
|
||||
<< " unpacked_dimensions()=" << reg->unpacked_dimensions() << endl;
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// We are processing the tail of a string of names. For
|
||||
|
|
|
|||
26
elab_sig.cc
26
elab_sig.cc
|
|
@ -42,6 +42,7 @@
|
|||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netqueue.h"
|
||||
# include "netscalar.h"
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
|
@ -1231,7 +1232,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
const netenum_t*use_enum = base_type_scope->find_enumeration_for_name(des, sample_name->name);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Create signal " << wtype
|
||||
<< " enumeration "
|
||||
<< name_ << " in scope " << scope_path(scope)
|
||||
<< " with packed_dimensions=" << packed_dimensions
|
||||
|
|
@ -1245,7 +1247,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
} else if (netdarray) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Create signal " << wtype
|
||||
<< " dynamic array " << name_
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
|
|
@ -1255,6 +1257,20 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, unpacked_dimensions.empty());
|
||||
sig = new NetNet(scope, name_, wtype, netdarray);
|
||||
|
||||
} else if (dynamic_cast<string_type_t*>(set_data_type_)) {
|
||||
|
||||
// Signal declared as: string foo;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Create signal " << wtype
|
||||
<< " string "
|
||||
<< name_ << " in scope " << scope_path(scope)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions,
|
||||
&netstring_t::type_string);
|
||||
|
||||
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
|
||||
// The pform gives us a parray_type_t for packed arrays
|
||||
// that show up in type definitions. This can be handled
|
||||
|
|
@ -1279,7 +1295,9 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
} else {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Create signal " << wtype
|
||||
<< " data_type=" << data_type_;
|
||||
if (!get_scalar()) {
|
||||
cerr << " " << packed_dimensions;
|
||||
}
|
||||
|
|
@ -1291,7 +1309,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
cerr << get_fileline() << ": " << __func__ << ": "
|
||||
<< "Signal " << name_
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< " defaults to data type " << use_data_type << endl;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
# include "netenum.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netscalar.h"
|
||||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include <iostream>
|
||||
|
|
@ -495,6 +496,8 @@ NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np)
|
|||
type_ = IVL_VT_DARRAY;
|
||||
else if (dynamic_cast<const netclass_t*>(rtype))
|
||||
type_ = IVL_VT_CLASS;
|
||||
else if (dynamic_cast<const netstring_t*>(rtype))
|
||||
type_ = IVL_VT_STRING;
|
||||
else
|
||||
ivl_assert(*this, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1066,8 +1066,9 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
|||
pe->test_width(des, scope, mode);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << pe->get_fileline() << ": debug: test_width of "
|
||||
<< name << " argument " << (arg_idx+1) << " " << *pe << endl;
|
||||
cerr << pe->get_fileline() << ": " << __func__ << ": "
|
||||
<< "test_width of " << name
|
||||
<< " argument " << (arg_idx+1) << " " << *pe << endl;
|
||||
cerr << pe->get_fileline() << ": "
|
||||
<< "returns type=" << pe->expr_type()
|
||||
<< ", width=" << pe->expr_width()
|
||||
|
|
|
|||
Loading…
Reference in New Issue