diff --git a/PExpr.h b/PExpr.h index 97aa1ef97..304975050 100644 --- a/PExpr.h +++ b/PExpr.h @@ -935,11 +935,12 @@ class PECallFunction : public PExpr { NetExpr*elaborate_expr_method_(Design*des, NetScope*scope, unsigned expr_wid, bool add_this_flag = false) const; -#if 0 - NetExpr*elaborate_expr_string_method_(Design*des, NetScope*scope) const; - NetExpr*elaborate_expr_enum_method_(Design*des, NetScope*scope, - unsigned expr_wid) const; -#endif + NetExpr*elaborate_expr_method_net_(Design*des, NetScope*scope, + NetNet*net, unsigned expr_wid) const; + NetExpr*elaborate_expr_method_par_(Design*des, NetScope*scope, + const NetExpr *par, ivl_type_t par_type, + unsigned expr_wid) const; + NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, unsigned expr_wid, diff --git a/design_dump.cc b/design_dump.cc index 6e6c098d0..fbdbda160 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -31,6 +31,7 @@ # include "netclass.h" # include "netdarray.h" # include "netqueue.h" +# include "netscalar.h" # include "netvector.h" # include "ivl_assert.h" # include "PExpr.h" @@ -238,6 +239,17 @@ ostream& netqueue_t::debug_dump(ostream&fd) const return fd; } +ostream& netreal_t::debug_dump(ostream&fd) const +{ + fd << "real"; + return fd; +} +ostream& netstring_t::debug_dump(ostream&fd) const +{ + fd << "string"; + return fd; +} + ostream& netvector_t::debug_dump(ostream&o) const { o << "netvector_t:" << type_ << (signed_? " signed" : " unsigned") << packed_dims_; diff --git a/elab_expr.cc b/elab_expr.cc index b38dcfcb3..8ddd26cb1 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2640,6 +2640,15 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, use_path.push_front(name_component_t(perm_string::literal(THIS_TOKEN))); } + if (debug_elaborate) { + cerr << get_fileline() << ": " << __func__ << ": " + << "use_path: " << use_path << endl; + cerr << get_fileline() << ": " << __func__ << ": " + << "method_name: " << method_name << endl; + cerr << get_fileline() << ": " << __func__ << ": " + << "expr_wid: " << expr_wid << endl; + } + // If there is no object to the left of the method name, then // give up on the idea of looking for an object method. if (use_path.empty()) return 0; @@ -2651,8 +2660,38 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, symbol_search(this, des, scope, use_path, net, par, eve, par_type); - if (net == 0) - return 0; + if (debug_elaborate) { + if (net) { + cerr << get_fileline() << ": " << __func__ << ": " + << "net: " << net->name() << endl; + } + if (par) { + cerr << get_fileline() << ": " << __func__ << ": " + << "par: " << *par << endl; + } + if (par_type) { + cerr << get_fileline() << ": " << __func__ << ": " + << "par_type: " << *par_type << endl; + } + } + + // If we found a net with a method... + if (net) + return elaborate_expr_method_net_(des, scope, net, expr_wid); + + // If we found a parameter with a method... + if (par) + return elaborate_expr_method_par_(des, scope, par, par_type, expr_wid); + + return 0; +} + +NetExpr* PECallFunction::elaborate_expr_method_net_(Design*des, NetScope*scope, + NetNet*net, unsigned expr_wid) const +{ + pform_name_t use_path = path_; + perm_string method_name = peek_tail_name(use_path); + use_path.pop_back(); if (net->data_type() == IVL_VT_STRING) { @@ -2812,6 +2851,70 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, return 0; } +NetExpr* PECallFunction::elaborate_expr_method_par_(Design*, NetScope*scope, + const NetExpr*par, + ivl_type_t par_type, + unsigned expr_wid) const +{ + pform_name_t use_path = path_; + perm_string method_name = peek_tail_name(use_path); + use_path.pop_back(); + + // If the parameter is of type string, then look for the standard string + // method. Return an error if not found. Since we are assured that the + // expression is a constant string, it should be able to calculate the + // result at compile time. + if (dynamic_cast(par_type)) { + + const NetECString*par_string = dynamic_cast(par); + ivl_assert(*par, par_string); + string par_value = par_string->value().as_string(); + + if (method_name == "len") { + NetEConst*use_val = make_const_val(par_value.size()); + use_val->set_line(*this); + return pad_to_width(use_val, expr_wid, *this); + } + + if (method_name == "atoi") { + NetEConst*use_val = make_const_val(atoi(par_value.c_str())); + use_val->set_line(*this); + return pad_to_width(use_val, expr_wid, true, *this); + } + + if (method_name == "atoreal") { + NetECReal*use_val = new NetECReal(verireal(par_value.c_str())); + use_val->set_line(*this); + return use_val; + } + + if (method_name == "atohex") { + NetEConst*use_val = make_const_val(strtoul(par_value.c_str(),0,16)); + use_val->set_line(*this); + return pad_to_width(use_val, expr_wid, true, *this); + } + + // Returning 0 here will cause the caller to print an error + // message and increment the error count, so there is no need to + // increment des->error_count here. + cerr << get_fileline() << ": error: " + << "Unknown or unsupport string method: " << method_name + << endl; + return 0; + } + + // If we haven't figured out what to do with this method by now, + // something went wrong. + cerr << get_fileline() << ": sorry: Don't know how to handle methods of parameters of type:" << endl; + cerr << get_fileline() << ": : " << *par_type << endl; + cerr << get_fileline() << ": : in scope " << scope_path(scope) << endl; + + // Returning 0 here will cause the caller to print an error message and + // increment the error count, so there is no need to increment + // des->error_count here. + return 0; +} + unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&) { ivl_assert(*this, size_); @@ -4821,6 +4924,13 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, { bool need_const = NEED_CONST & flags; + if (debug_elaborate) { + cerr << get_fileline() << ": " << __func__ << ": " + << "Parameter: " << path_ << endl; + cerr << get_fileline() << ": " << __func__ << ": " + << "par_type: " << *par_type << endl; + } + if (need_const && !(ANNOTATABLE & flags)) { perm_string name = peek_tail_name(path_); if (found_in->make_parameter_unannotatable(name)) { @@ -6034,16 +6144,19 @@ unsigned PEString::test_width(Design*, NetScope*, width_mode_t&) return expr_width_; } -NetEConst* PEString::elaborate_expr(Design*, NetScope*, ivl_type_t, unsigned)const +NetEConst* PEString::elaborate_expr(Design*, NetScope*, ivl_type_t, unsigned) const { - verinum val(value()); - NetEConst*tmp = new NetEConst(val); + NetECString*tmp = new NetECString(value()); tmp->cast_signed(signed_flag_); tmp->set_line(*this); return tmp; } +/* + * When the expression is being elaborated with a width, then we are trying to + * make a vector, so create a NetEConst with the basic types. + */ NetEConst* PEString::elaborate_expr(Design*, NetScope*, unsigned expr_wid, unsigned) const { diff --git a/net_design.cc b/net_design.cc index cbfc55507..cd0efabdb 100644 --- a/net_design.cc +++ b/net_design.cc @@ -789,6 +789,41 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur) } } +/* + * Evaluate a parameter that is forced to type string. This comes to pass when + * the input is something like this: + * + * parameter string foo = ; + * + * The param_type should be netstring_t, the val_expr is the pform of the + * input , and we try to elaborate/evaluate down to a IVL_VT_STRING + * expression. + */ +void NetScope::evaluate_parameter_string_(Design*des, param_ref_t cur) +{ + PExpr*val_expr = (*cur).second.val_expr; + NetScope*val_scope = (*cur).second.val_scope; + ivl_type_t param_type = cur->second.ivl_type; + + ivl_assert(cur->second, val_expr); + ivl_assert(cur->second, param_type); + + NetExpr*expr = elab_and_eval(des, val_scope, val_expr, param_type, true); + if (! expr) + return; + + cur->second.val = expr; + + if (debug_elaborate) { + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Parameter type: " << *param_type << endl; + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Parameter value: " << *val_expr << endl; + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Elaborated value: " << *expr << endl; + } +} + void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) { ivl_type_t param_type = cur->second.ivl_type; @@ -832,12 +867,19 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) evaluate_parameter_real_(des, cur); break; + case IVL_VT_STRING: + evaluate_parameter_string_(des, cur); + break; + default: cerr << cur->second.get_fileline() << ": internal error: " - << "Unexpected expression type " << use_type + << "Unexpected parameter type " << use_type << "." << endl; cerr << cur->second.get_fileline() << ": : " << "Parameter name: " << cur->first << endl; + if (param_type) + cerr << cur->second.get_fileline() << ": : " + << "Parameter ivl_type: " << *param_type << endl; cerr << cur->second.get_fileline() << ": : " << "Expression is: " << *cur->second.val_expr << endl; ivl_assert(cur->second, 0); diff --git a/net_expr.cc b/net_expr.cc index 804fae96d..2a6a1faee 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -320,6 +320,19 @@ const NetScope* NetECRealParam::scope() const return scope_; } +NetECString::NetECString(const std::string& val) +: NetEConst(verinum(val)) +{ +} + +NetECString::~NetECString() +{ +} + +ivl_variable_type_t NetECString::expr_type() const +{ + return IVL_VT_STRING; +} NetELast::NetELast(NetNet*s) : sig_(s) diff --git a/netlist.h b/netlist.h index 88fdb7a53..ccc33312a 100644 --- a/netlist.h +++ b/netlist.h @@ -1252,6 +1252,7 @@ class NetScope : public Definitions, public Attrib { private: void evaluate_parameter_logic_(Design*des, param_ref_t cur); void evaluate_parameter_real_(Design*des, param_ref_t cur); + void evaluate_parameter_string_(Design*des, param_ref_t cur); void evaluate_parameter_(Design*des, param_ref_t cur); private: @@ -2219,6 +2220,15 @@ class NetECReal : public NetExpr { verireal value_; }; +class NetECString : public NetEConst { + public: + explicit NetECString(const std::string& val); + ~NetECString(); + + // The type of a string is IVL_VT_STRING + ivl_variable_type_t expr_type() const; +}; + class NetECRealParam : public NetECReal { public: diff --git a/netmisc.cc b/netmisc.cc index 4f6ab426d..e4e96119f 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1004,7 +1004,7 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, ivl_type_t lv_net_type, bool need_const) { if (debug_elaborate) { - cerr << pe->get_fileline() << ": elab_and_eval: " + cerr << pe->get_fileline() << ": " << __func__ << ": " << "pe=" << *pe << ", lv_net_type=" << *lv_net_type << endl; } diff --git a/netscalar.h b/netscalar.h index ad63d404d..ba1ba7975 100644 --- a/netscalar.h +++ b/netscalar.h @@ -29,6 +29,8 @@ class netreal_t : public ivl_type_s { ivl_variable_type_t base_type() const; + std::ostream& debug_dump(std::ostream&) const; + public: static netreal_t type_real; static netreal_t type_shortreal; @@ -42,6 +44,8 @@ class netstring_t : public ivl_type_s { ivl_variable_type_t base_type() const; + std::ostream& debug_dump(std::ostream&) const; + public: static netstring_t type_string; };