From dcbd824f3bb0a2f5a7cb74a13d4ddd5eefc44307 Mon Sep 17 00:00:00 2001 From: Pierre-Henri Horrein Date: Tue, 20 Apr 2021 17:01:41 +0200 Subject: [PATCH 1/4] Preliminary unpacked support for localparam --- PExpr.h | 6 ++ design_dump.cc | 16 +++++ dup_expr.cc | 11 ++++ elab_expr.cc | 140 ++++++++++++++++++++++++++++++++++++++--- emit.cc | 5 ++ ivl_target.h | 7 ++- net_design.cc | 45 +++++++++++-- net_expr.cc | 23 +++++++ netlist.h | 24 ++++++- netmisc.cc | 81 ++++++++++++++---------- netparray.cc | 5 ++ netparray.h | 5 ++ parse.y | 41 ++++++++++-- t-dll.cc | 8 +++ tgt-stub/stub.c | 3 + tgt-stub/types.c | 6 ++ tgt-vlog95/logic_lpm.c | 1 + tgt-vvp/draw_vpi.c | 3 + 18 files changed, 374 insertions(+), 56 deletions(-) diff --git a/PExpr.h b/PExpr.h index 627e3183d2..c7f6ae222b 100644 --- a/PExpr.h +++ b/PExpr.h @@ -456,6 +456,12 @@ class PEIdent : public PExpr { NetScope*found_in, ivl_type_t par_type, bool need_const) const; + NetExpr*elaborate_expr_param_word_(Design*des, + NetScope*scope, + const NetExpr*par, + NetScope*found_in, + ivl_type_t par_type, + bool need_const) const; NetExpr*elaborate_expr_param_part_(Design*des, NetScope*scope, const NetExpr*par, diff --git a/design_dump.cc b/design_dump.cc index 67b41a7745..1492d16c2e 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -109,6 +109,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val) case IVL_VT_STRING: o << "string"; break; + case IVL_VT_UARRAY: + o << "uarray"; + break; case IVL_VT_DARRAY: o << "darray"; break; @@ -1673,6 +1676,19 @@ void NetEArrayPattern::dump(ostream&fd) const fd << "}"; } +void NetEArrayPatternParam::dump(ostream&fd) const +{ + fd << "'{"; + if (items_.size() >= 1) { + if (items_[0]) fd << *items_[0]; + } + for (size_t idx = 1 ; idx < items_.size() ; idx += 1) { + fd << ", "; + if (items_[idx]) fd << *items_[idx]; + } + fd << "}"; +} + void NetEBinary::dump(ostream&o) const { if (op_ == 'm' || op_ == 'M') { diff --git a/dup_expr.cc b/dup_expr.cc index c1c2246db4..b613f5bc55 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -43,6 +43,17 @@ NetEArrayPattern*NetEArrayPattern::dup_expr() const return res; } +NetEArrayPatternParam*NetEArrayPatternParam::dup_expr() const +{ + vectortmp (items_.size()); + for (size_t idx = 0 ; idx < tmp.size() ; idx += 1) + tmp[idx] = items_[idx]->dup_expr(); + + NetEArrayPatternParam*res = new NetEArrayPatternParam(scope_, name_, net_type(), tmp); + res->set_line(*this); + return res; +} + NetEBinary* NetEBinary::dup_expr() const { ivl_assert(*this, 0); diff --git a/elab_expr.cc b/elab_expr.cc index c80cf223bd..06fcbdd083 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -109,6 +109,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type, int context_wid = -1; switch (lv_type) { case IVL_VT_DARRAY: + case IVL_VT_UARRAY: case IVL_VT_QUEUE: case IVL_VT_CLASS: // For these types, use a different elab_and_eval that @@ -186,11 +187,11 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const */ unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&) { - expr_type_ = IVL_VT_DARRAY; - expr_width_ = 1; - min_width_ = 1; + expr_type_ = IVL_VT_UARRAY; + expr_width_ = parms_.size(); + min_width_ = expr_width_; signed_flag_= false; - return 1; + return expr_width_; } NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, @@ -208,7 +209,8 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, } if (ntype->base_type()==IVL_VT_DARRAY || - ntype->base_type()==IVL_VT_QUEUE) + ntype->base_type()==IVL_VT_QUEUE || + ntype->base_type()==IVL_VT_UARRAY) return elaborate_expr_darray_(des, scope, ntype, flags); cerr << get_fileline() << ": sorry: I don't know how to elaborate " @@ -222,7 +224,7 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, NetExpr*PEAssignPattern::elaborate_expr_darray_(Design*des, NetScope*scope, ivl_type_t ntype, unsigned flags) const { - const netdarray_t*array_type = dynamic_cast (ntype); + const netarray_t*array_type = dynamic_cast (ntype); ivl_assert(*this, array_type); // This is an array pattern, so run through the elements of @@ -3558,6 +3560,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, switch (ntype->base_type()) { case IVL_VT_QUEUE: // FIXME: Does a DARRAY support a zero size? + case IVL_VT_UARRAY: case IVL_VT_DARRAY: if (parms_.size() == 0) { NetENull*tmp = new NetENull; @@ -3728,6 +3731,7 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net, switch (net->data_type()) { case IVL_VT_STRING: case IVL_VT_DARRAY: + case IVL_VT_UARRAY: case IVL_VT_QUEUE: dimensions += 1; default: @@ -4061,6 +4065,27 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) return expr_width_; } + if (par != 0 && par->expr_type() == IVL_VT_UARRAY) { + const netuarray_t*array = dynamic_cast (par->net_type()); + ivl_assert(*this, array); + switch (use_sel) { + case index_component_t::SEL_BIT: + case index_component_t::SEL_BIT_LAST: + expr_type_ = array->element_type()->base_type(); + expr_width_ = array->element_type()->packed_width(); + min_width_ = expr_width_; + signed_flag_ = array->element_type()->get_signed(); + break; + default: + expr_type_ = array->base_type(); + expr_width_ = array->static_dimensions()[0].width(); + min_width_ = expr_width_; + signed_flag_ = false; + break; + } + return expr_width_; + } + // Look for a class property. if (gn_system_verilog() && cls_val) { expr_type_ = cls_val->base_type(); @@ -4255,6 +4280,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, symbol_search(this, des, use_scope, path_, net, par, eve, par_type, cls_val); + if (par != 0) { + return (NetExpr *)par; + } + if (net == 0 && gn_system_verilog() && path_.size() >= 2) { // NOTE: this is assuming the member_path is only one // component long, and that the use_path will wind up @@ -4615,9 +4644,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in, par_type, expr_wid, flags); - if (!tmp) return 0; + if (!tmp) return 0; - return pad_to_width(tmp, expr_wid, signed_flag_, *this); + return pad_to_width(tmp, expr_wid, signed_flag_, *this); } // If the identifier names a signal (a variable or a net) @@ -5132,6 +5161,78 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope, return tmp; } +NetExpr* PEIdent::elaborate_expr_param_word_(Design*des, NetScope*scope, + const NetExpr*par, + NetScope*found_in, + ivl_type_t par_type, + bool need_const) const +{ + const NetEArrayPattern*par_ex = dynamic_cast (par); + ivl_assert(*this, par_ex); + const netuarray_t*array = dynamic_cast (par->net_type()); + if (!array) { + cerr << get_fileline() << "tried to get a word from non-array expression" << endl; + return 0; + } + + long par_msv, par_lsv; + if(! calculate_param_range(*this, par_type, par_msv, par_lsv, + par_ex->item_size())) return 0; + + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, !name_tail.index.empty()); + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.msb); + ivl_assert(*this, !index_tail.lsb); + + NetExpr*sel = elab_and_eval(des, scope, index_tail.msb, -1, need_const); + if (sel == 0) return 0; + + if (debug_elaborate) + cerr << get_fileline() << ": debug: Calculate bit select " + << "[" << *sel << "] from range " + << "[" << par_msv << ":" << par_lsv << "]." << endl; + + perm_string name = peek_tail_name(path_); + + // Handle the special case that the selection is constant. In this + // case, just precalculate the entire constant result. + NetEConst*sel_c = dynamic_cast (sel); + if (!sel_c) { + cerr << get_fileline() << "tried to get a word with non constant selector" << endl; + return 0; + } + // Special case: If the bit select is constant and not fully + // defined, then we know that the result must be 1'bx. + if (! sel_c->value().is_defined()) { + if (warn_ob_select) { + cerr << get_fileline() << ": warning: " + "Constant undefined bit select [" + << sel_c->value() << "] for parameter '" + << name << "'." << endl; + cerr << get_fileline() << ": : " + "Replacing select with a constant 1'bx." + << endl; + } + + // This is a convenience function for getting the width of an + // element. Strictly speaking it's not necessary. + NetEConst*res = make_const_x(array->element_type()->packed_width()); + res->set_line(*this); + return res; + } + // Calculate the canonical index value. + long sel_v = sel_c->value().as_long(); + if (par_msv >= par_lsv) sel_v = par_msv - sel_v - par_lsv; + else sel_v -= par_msv; + + // Select a bit from the parameter. + NetExpr*res = (NetExpr *)(par_ex->item(sel_v)->dup_expr()); + //NetEConst*res = new NetEConst(rtn); + res->set_line(*this); + return res; +} + NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope, const NetExpr*par, NetScope*, @@ -5458,6 +5559,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, const name_component_t&name_tail = path_.back(); index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; + // FIXME: this won't work with multidimensional array if (!name_tail.index.empty()) use_sel = name_tail.index.back().sel; @@ -5473,8 +5575,13 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST); if (use_sel == index_component_t::SEL_BIT) - return elaborate_expr_param_bit_(des, scope, par, found_in, - par_type, need_const); + if (par->expr_type() == IVL_VT_UARRAY) { + return elaborate_expr_param_word_(des, scope, par, found_in, + par_type, need_const); + } else { + return elaborate_expr_param_bit_(des, scope, par, found_in, + par_type, need_const); + } if (use_sel == index_component_t::SEL_PART) return elaborate_expr_param_part_(des, scope, par, found_in, @@ -5530,6 +5637,19 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, << "Elaborate parameter <" << name << "> as constant " << *tmp << endl; } + + const NetEArrayPattern*atmp = dynamic_cast(par); + if (atmp) { + std::vector items(atmp->item_size()); + for (unsigned i = 0; i < atmp->item_size(); i++) { + items[i] = (NetExpr*)atmp->item(i)->dup_expr(); + } + tmp = new NetEArrayPatternParam(found_in, name, atmp->net_type(), items); + if (debug_elaborate) + cerr << get_fileline() << ": debug: " + << "Elaborate parameter <" << name + << "> as constant " << *tmp << endl; + } /* The numeric parameter value needs to have the file and line * information for the actual parameter not the expression. */ assert(tmp); diff --git a/emit.cc b/emit.cc index 26360c4f7e..755cc08470 100644 --- a/emit.cc +++ b/emit.cc @@ -593,6 +593,11 @@ void NetEArrayPattern::expr_scan(struct expr_scan_t*tgt) const tgt->expr_array_pattern(this); } +void NetEArrayPatternParam::expr_scan(struct expr_scan_t*tgt) const +{ + tgt->expr_array_pattern(this); +} + void NetEBinary::expr_scan(struct expr_scan_t*tgt) const { tgt->expr_binary(this); diff --git a/ivl_target.h b/ivl_target.h index 7e41f6ecd0..42eecc19ac 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -460,9 +460,10 @@ typedef enum ivl_variable_type_e ENUM_UNSIGNED_INT { IVL_VT_BOOL = 3, IVL_VT_LOGIC = 4, IVL_VT_STRING = 5, - IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */ - IVL_VT_CLASS = 7, /* SystemVerilog class instances */ - IVL_VT_QUEUE = 8, /* SystemVerilog queue instances */ + IVL_VT_UARRAY = 6, /* Array (esp. unpacked array) */ + IVL_VT_DARRAY = 7, /* Array (esp. dynamic array) */ + IVL_VT_CLASS = 8, /* SystemVerilog class instances */ + IVL_VT_QUEUE = 9, /* SystemVerilog queue instances */ IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */ } ivl_variable_type_t; diff --git a/net_design.cc b/net_design.cc index f6a7c15e9f..1144c66487 100644 --- a/net_design.cc +++ b/net_design.cc @@ -508,6 +508,31 @@ void Design::evaluate_parameters() } } +void NetScope::evaluate_parameter_array_(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_logic_(Design*des, param_ref_t cur) { /* Evaluate the parameter expression. */ @@ -840,7 +865,7 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) if (cur->second.val_expr == 0) return; - // Guess the varaiable type of the parameter. If the parameter has no + // Guess the variable type of the parameter. If the parameter has no // given type, then guess the type from the expression and use that to // evaluate. ivl_variable_type_t use_type; @@ -849,6 +874,14 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) else use_type = cur->second.val_expr->expr_type(); + if (debug_elaborate) { + cerr << cur->second.get_fileline() << ": evaluating parameter " << cur->first + << ", param_type: " << param_type; + if (param_type) + cerr << "(base type: " << param_type->base_type() << ")"; + cerr << ", use_type: " << use_type + << "." << endl; + } if (cur->second.solving) { cerr << cur->second.get_fileline() << ": error: " << "Recursive parameter reference found involving " @@ -868,9 +901,13 @@ 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; + case IVL_VT_UARRAY: + evaluate_parameter_array_(des, cur); + break; + + case IVL_VT_STRING: + evaluate_parameter_string_(des, cur); + break; default: cerr << cur->second.get_fileline() << ": internal error: " diff --git a/net_expr.cc b/net_expr.cc index 525dd9bf70..b99a079fdb 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -73,6 +73,11 @@ const netenum_t*NetExpr::enumeration() const return 0; } +NetEArrayPattern::NetEArrayPattern(unsigned w, vector&items) +: NetExpr(w), items_(items) +{ +} + NetEArrayPattern::NetEArrayPattern(ivl_type_t lv_type, vector&items) : NetExpr(lv_type), items_(items) { @@ -83,6 +88,24 @@ NetEArrayPattern::~NetEArrayPattern() for (size_t idx = 0 ; idx < items_.size() ; idx += 1) delete items_[idx]; } +NetEArrayPatternParam::NetEArrayPatternParam(NetScope*s, perm_string n, ivl_type_t lv_type, vector&items) +: NetEArrayPattern(lv_type, items), scope_(s), name_(n) +{ +} + +NetEArrayPatternParam::~NetEArrayPatternParam() +{ +} + +perm_string NetEArrayPatternParam::name() const +{ + return name_; +} + +const NetScope* NetEArrayPatternParam::scope() const +{ + return scope_; +} /* * Create an add/sub node from the two operands. diff --git a/netlist.h b/netlist.h index 7827470c62..3db5adf553 100644 --- a/netlist.h +++ b/netlist.h @@ -1251,6 +1251,7 @@ class NetScope : public Definitions, public Attrib { std::map loop_index_tmp; private: + void evaluate_parameter_array_(Design*des, param_ref_t cur); 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); @@ -2094,6 +2095,7 @@ class NetExpr : public LineInfo { class NetEArrayPattern : public NetExpr { public: + NetEArrayPattern(unsigned w, std::vector&items); NetEArrayPattern(ivl_type_t lv_type, std::vector&items); ~NetEArrayPattern(); @@ -2107,10 +2109,30 @@ class NetEArrayPattern : public NetExpr { NexusSet* nex_input(bool rem_out = true, bool always_sens = false, bool nested_func = false) const; - private: + protected: std::vector items_; }; +class NetEArrayPatternParam : public NetEArrayPattern { + + public: + explicit NetEArrayPatternParam(NetScope*scope, perm_string name, + ivl_type_t lv_type, std::vector&items); + ~NetEArrayPatternParam(); + + perm_string name() const; + const NetScope*scope() const; + + virtual void expr_scan(struct expr_scan_t*) const; + virtual void dump(ostream&) const; + + virtual NetEArrayPatternParam* dup_expr() const; + + private: + NetScope*scope_; + perm_string name_; +}; + /* * The expression constant is slightly special, and is sometimes * returned from other classes that can be evaluated at compile diff --git a/netmisc.cc b/netmisc.cc index 4f21eeca72..e9e50e3ceb 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1023,10 +1023,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, // Catch some special cases. switch (cast_type) { case IVL_VT_DARRAY: + case IVL_VT_UARRAY: case IVL_VT_QUEUE: if (NetESignal*net = dynamic_cast(tmp)) { ivl_variable_type_t type = net->expr_type(); - if ((type == IVL_VT_DARRAY) || (type == IVL_VT_QUEUE)) + if ((type == IVL_VT_UARRAY) || (type == IVL_VT_DARRAY) || (type == IVL_VT_QUEUE)) return tmp; } if (dynamic_cast(pe)) @@ -1826,36 +1827,52 @@ void check_for_inconsistent_delays(NetScope*scope) bool calculate_param_range(const LineInfo&line, ivl_type_t par_type, long&par_msv, long&par_lsv, long length) { - const netvector_t*vector_type = dynamic_cast (par_type); - if (vector_type == 0) { - // If the parameter doesn't have an explicit range, then - // just return range values of [length-1:0]. - par_msv = length-1; - par_lsv = 0; - return true; - } - - ivl_assert(line, vector_type->packed()); - const std::vector& packed_dims = vector_type->packed_dims(); - - // This is a netvector_t with 0 dimensions, then the parameter was - // declared with a statement like this: - // - // parameter signed foo = ; - // - // The netvector_t is just here to carry the signed-ness, which we don't - // even need here. So act like the type is defined by the r-value - // length. - if (packed_dims.size() == 0) { - par_msv = length-1; - par_lsv = 0; - return true; + switch(par_type->base_type()) { + case IVL_VT_VECTOR: { + const netvector_t*vector_type = dynamic_cast (par_type); + + ivl_assert(line, vector_type->packed()); + const std::vector& packed_dims = vector_type->packed_dims(); + + // This is a netvector_t with 0 dimensions, then the parameter was + // declared with a statement like this: + // + // parameter signed foo = ; + // + // The netvector_t is just here to carry the signed-ness, which we don't + // even need here. So act like the type is defined by the r-value + // length. + if (packed_dims.size() == 0) { + par_msv = length-1; + par_lsv = 0; + return true; + } + ivl_assert(line, packed_dims.size() == 1); + + netrange_t use_range = packed_dims[0]; + par_msv = use_range.get_msb(); + par_lsv = use_range.get_lsb(); + + return true; + } + case IVL_VT_UARRAY: { + const netsarray_t*array_type = dynamic_cast (par_type); + + ivl_assert(line, array_type); + const std::vector& unpacked_dims = array_type->static_dimensions(); + ivl_assert(line, unpacked_dims.size() == 1); + + netrange_t use_range = unpacked_dims[0]; + par_msv = use_range.get_msb(); + par_lsv = use_range.get_lsb(); + return true; + } + + default: + // If the parameter doesn't have an explicit range, then + // just return range values of [length-1:0]. + par_msv = length-1; + par_lsv = 0; + return true; } - ivl_assert(line, packed_dims.size() == 1); - - netrange_t use_range = packed_dims[0]; - par_msv = use_range.get_msb(); - par_lsv = use_range.get_lsb(); - - return true; } diff --git a/netparray.cc b/netparray.cc index 0c0181c0c1..5db231635c 100644 --- a/netparray.cc +++ b/netparray.cc @@ -76,3 +76,8 @@ vector netuarray_t::slice_dimensions() const { return static_dimensions(); } + +ivl_variable_type_t netuarray_t::base_type(void) const +{ + return IVL_VT_UARRAY; +} diff --git a/netparray.h b/netparray.h index 6be2da4d0e..c545a42759 100644 --- a/netparray.h +++ b/netparray.h @@ -86,6 +86,11 @@ class netuarray_t : public netsarray_t { ivl_type_t etype); ~netuarray_t(); + // This is the "base_type()" virtual method of the + // nettype_base_t. The ivl_target api expects this to return + // IVL_VT_DARRAY for dynamic arrays? + ivl_variable_type_t base_type() const; + public: // Virtual methods from the ivl_type_s type... std::vector slice_dimensions() const; diff --git a/parse.y b/parse.y index 21d0e090dc..d403924a96 100644 --- a/parse.y +++ b/parse.y @@ -746,6 +746,21 @@ assertion_item /* IEEE1800-2012: A.6.10 */ | deferred_immediate_assertion_item ; +array_pattern_item_list + : array_pattern_item_list ',' array_pattern_key ':' expression + | array_pattern_key ':' expression + ; + +array_pattern_key + : expression + | assignment_pattern_key + ; + +assignment_pattern_key + : simple_type_or_string + | K_default + ; + assignment_pattern /* IEEE1800-2005: A.6.7.1 */ : K_LP expression_list_proper '}' { PEAssignPattern*tmp = new PEAssignPattern(*$2); @@ -753,6 +768,10 @@ assignment_pattern /* IEEE1800-2005: A.6.7.1 */ delete $2; $$ = tmp; } + | K_LP array_pattern_item_list '}' + { yyerror(@1, "Unsupported array pattern list");} + | K_LP expr_primary '{' expression_list_proper '}' '}' + { yyerror(@1, "Unsupported concatenation");} | K_LP '}' { PEAssignPattern*tmp = new PEAssignPattern; FILE_NAME(tmp, @1); @@ -5668,17 +5687,27 @@ localparam_assign_list ; parameter_assign - : IDENTIFIER '=' expression parameter_value_ranges_opt - { PExpr*tmp = $3; - pform_set_parameter(@1, lex_strings.make($1), param_data_type, tmp, $4); + : IDENTIFIER dimensions_opt '=' expression parameter_value_ranges_opt + { PExpr*tmp = $4; + if ($2) { + uarray_type_t *array_type = new uarray_type_t(param_data_type, $2); + pform_set_parameter(@1, lex_strings.make($1), array_type, tmp, $5); + } else { + pform_set_parameter(@1, lex_strings.make($1), param_data_type, tmp, $5); + } delete[]$1; } ; localparam_assign - : IDENTIFIER '=' expression - { PExpr*tmp = $3; - pform_set_localparam(@1, lex_strings.make($1), param_data_type, tmp); + : IDENTIFIER dimensions_opt '=' expression + { PExpr*tmp = $4; + if ($2) { + uarray_type_t *array_type = new uarray_type_t(param_data_type, $2); + pform_set_localparam(@1, lex_strings.make($1), array_type, tmp); + } else { + pform_set_localparam(@1, lex_strings.make($1), param_data_type, tmp); + } delete[]$1; } ; diff --git a/t-dll.cc b/t-dll.cc index 1ad5d8f5c7..bc4f8fcac3 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -559,6 +559,14 @@ void dll_target::make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp) assert(expr_->type_ == IVL_EX_REALNUM); expr_->u_.real_.parameter = cur_par; + } else if (const NetEArrayPattern*ea = dynamic_cast(etmp)) { + + return; + //expr_uarray(er); + //assert(expr_); + //assert(expr_->type_ == IVL_EX_ARRAY_PATTERN); + //expr_->u_.array_pattern_.parameter = cur_par; + } if (expr_ == 0) { diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 670962f7a8..e569b78f8a 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -169,6 +169,9 @@ const char*data_type_string(ivl_variable_type_t vtype) case IVL_VT_STRING: vt = "string"; break; + case IVL_VT_UARRAY: + vt = "uarray"; + break; case IVL_VT_DARRAY: vt = "darray"; break; diff --git a/tgt-stub/types.c b/tgt-stub/types.c index 38a6b38c6a..0291a836b6 100644 --- a/tgt-stub/types.c +++ b/tgt-stub/types.c @@ -60,6 +60,9 @@ void show_net_type(ivl_type_t net_type) case IVL_VT_STRING: fprintf(out, "string"); break; + case IVL_VT_UARRAY: + fprintf(out, "uarray"); + break; case IVL_VT_DARRAY: show_net_type_darray(net_type); break; @@ -118,6 +121,9 @@ void show_type_of_signal(ivl_signal_t net) case IVL_VT_STRING: fprintf(out, "string"); break; + case IVL_VT_UARRAY: + fprintf(out, "uarray"); + break; case IVL_VT_DARRAY: /* The DARRAY type MUST be described by an ivl_signal_net_type object. */ diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 24dfdc1469..8fbfcdcb0e 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -2507,6 +2507,7 @@ void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex) case IVL_VT_LOGIC: fprintf(stderr, " logic"); break; case IVL_VT_STRING: fprintf(stderr, " string"); break; case IVL_VT_DARRAY: fprintf(stderr, " dynamic array"); break; + case IVL_VT_UARRAY: fprintf(stderr, " unpacked array"); break; case IVL_VT_CLASS: fprintf(stderr, " class"); break; case IVL_VT_QUEUE: fprintf(stderr, " queue"); break; } diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index bbe6b542d6..6f9311ebaa 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -427,6 +427,9 @@ static void draw_vpi_taskfunc_args(const char*call_string, str_stack_need += 1; buffer[0] = 0; break; + case IVL_VT_UARRAY: + case IVL_VT_DARRAY: + fprintf(stderr, "%s:%u: Unsupported array argument\n", ivl_expr_file(expr), ivl_expr_lineno(expr)); default: fprintf(stderr, "%s:%u: Sorry, cannot generate code for argument %u.\n", ivl_expr_file(expr), ivl_expr_lineno(expr), idx+1); From d0564d66484bec89a4042439efffac907f687a7a Mon Sep 17 00:00:00 2001 From: Pierre-Henri Horrein Date: Sun, 2 May 2021 12:30:18 +0200 Subject: [PATCH 2/4] Removing useless IVL_VT_UARRAY type --- PExpr.h | 10 -- design_dump.cc | 3 - elab_expr.cc | 276 +++++++++++++++++------------------------ ivl_target.h | 7 +- net_design.cc | 53 ++++---- netlist.h | 1 - netmisc.cc | 92 +++++++------- netparray.cc | 5 - netparray.h | 5 - tgt-stub/stub.c | 3 - tgt-stub/types.c | 6 - tgt-vlog95/logic_lpm.c | 1 - tgt-vvp/draw_vpi.c | 1 - 13 files changed, 180 insertions(+), 283 deletions(-) diff --git a/PExpr.h b/PExpr.h index c7f6ae222b..b2d1d64304 100644 --- a/PExpr.h +++ b/PExpr.h @@ -221,10 +221,6 @@ class PEAssignPattern : public PExpr { virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, unsigned expr_wid, unsigned flags) const; - private: - NetExpr* elaborate_expr_darray_(Design*des, NetScope*scope, - ivl_type_t type, unsigned flags) const; - private: std::vectorparms_; }; @@ -456,12 +452,6 @@ class PEIdent : public PExpr { NetScope*found_in, ivl_type_t par_type, bool need_const) const; - NetExpr*elaborate_expr_param_word_(Design*des, - NetScope*scope, - const NetExpr*par, - NetScope*found_in, - ivl_type_t par_type, - bool need_const) const; NetExpr*elaborate_expr_param_part_(Design*des, NetScope*scope, const NetExpr*par, diff --git a/design_dump.cc b/design_dump.cc index 1492d16c2e..1f16f918ee 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -109,9 +109,6 @@ ostream& operator << (ostream&o, ivl_variable_type_t val) case IVL_VT_STRING: o << "string"; break; - case IVL_VT_UARRAY: - o << "uarray"; - break; case IVL_VT_DARRAY: o << "darray"; break; diff --git a/elab_expr.cc b/elab_expr.cc index 06fcbdd083..017ae36a06 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -109,7 +109,6 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type, int context_wid = -1; switch (lv_type) { case IVL_VT_DARRAY: - case IVL_VT_UARRAY: case IVL_VT_QUEUE: case IVL_VT_CLASS: // For these types, use a different elab_and_eval that @@ -185,12 +184,20 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const * supported, can assign to packed arrays and structs, unpacked arrays * and dynamic arrays. */ -unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&) +unsigned PEAssignPattern::test_width(Design*des, NetScope*scope, width_mode_t&mode) { - expr_type_ = IVL_VT_UARRAY; - expr_width_ = parms_.size(); - min_width_ = expr_width_; - signed_flag_= false; + if (parms_.size() > 0) { + parms_[0]->test_width(des, scope, mode); + expr_type_ = parms_[0]->expr_type(); + expr_width_ = parms_.size(); + min_width_ = expr_width_; + signed_flag_= parms_[0]->has_sign(); + } else { + expr_type_ = IVL_VT_DARRAY; + expr_width_ = 1; + min_width_ = 1; + signed_flag_= false; + } return expr_width_; } @@ -208,10 +215,23 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, return tmp; } - if (ntype->base_type()==IVL_VT_DARRAY || - ntype->base_type()==IVL_VT_QUEUE || - ntype->base_type()==IVL_VT_UARRAY) - return elaborate_expr_darray_(des, scope, ntype, flags); + const netarray_t*array_type = dynamic_cast (ntype); + if (array_type) { + + // This is an array pattern, so run through the elements of + // the expression and elaborate each as if they are + // element_type expressions. + ivl_type_t elem_type = array_type->element_type(); + vector elem_exprs (parms_.size()); + for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) { + NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope, elem_type, flags); + elem_exprs[idx] = tmp; + } + + NetEArrayPattern*res = new NetEArrayPattern(array_type, elem_exprs); + res->set_line(*this); + return res; + } cerr << get_fileline() << ": sorry: I don't know how to elaborate " << "assignment_pattern expressions yet." << endl; @@ -221,27 +241,6 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, return 0; } -NetExpr*PEAssignPattern::elaborate_expr_darray_(Design*des, NetScope*scope, - ivl_type_t ntype, unsigned flags) const -{ - const netarray_t*array_type = dynamic_cast (ntype); - ivl_assert(*this, array_type); - - // This is an array pattern, so run through the elements of - // the expression and elaborate each as if they are - // element_type expressions. - ivl_type_t elem_type = array_type->element_type(); - vector elem_exprs (parms_.size()); - for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) { - NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope, elem_type, flags); - elem_exprs[idx] = tmp; - } - - NetEArrayPattern*res = new NetEArrayPattern(array_type, elem_exprs); - res->set_line(*this); - return res; -} - NetExpr* PEAssignPattern::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const { cerr << get_fileline() << ": sorry: I do not know how to" @@ -3560,7 +3559,6 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, switch (ntype->base_type()) { case IVL_VT_QUEUE: // FIXME: Does a DARRAY support a zero size? - case IVL_VT_UARRAY: case IVL_VT_DARRAY: if (parms_.size() == 0) { NetENull*tmp = new NetENull; @@ -3731,7 +3729,6 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net, switch (net->data_type()) { case IVL_VT_STRING: case IVL_VT_DARRAY: - case IVL_VT_UARRAY: case IVL_VT_QUEUE: dimensions += 1; default: @@ -4065,26 +4062,27 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) return expr_width_; } - if (par != 0 && par->expr_type() == IVL_VT_UARRAY) { + if (par != 0) { const netuarray_t*array = dynamic_cast (par->net_type()); - ivl_assert(*this, array); - switch (use_sel) { - case index_component_t::SEL_BIT: - case index_component_t::SEL_BIT_LAST: - expr_type_ = array->element_type()->base_type(); - expr_width_ = array->element_type()->packed_width(); - min_width_ = expr_width_; - signed_flag_ = array->element_type()->get_signed(); - break; - default: - expr_type_ = array->base_type(); - expr_width_ = array->static_dimensions()[0].width(); - min_width_ = expr_width_; - signed_flag_ = false; - break; - } - return expr_width_; - } + if (array) { + switch (use_sel) { + case index_component_t::SEL_BIT: + case index_component_t::SEL_BIT_LAST: + expr_type_ = array->element_type()->base_type(); + expr_width_ = array->element_type()->packed_width(); + min_width_ = expr_width_; + signed_flag_ = array->element_type()->get_signed(); + break; + default: + expr_type_ = array->base_type(); + expr_width_ = array->static_dimensions()[0].width(); + min_width_ = expr_width_; + signed_flag_ = false; + break; + } + return expr_width_; + } + } // Look for a class property. if (gn_system_verilog() && cls_val) { @@ -5073,12 +5071,25 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope, ivl_type_t par_type, bool need_const) const { - const NetEConst*par_ex = dynamic_cast (par); - ivl_assert(*this, par_ex); - long par_msv, par_lsv; - if(! calculate_param_range(*this, par_type, par_msv, par_lsv, - par_ex->value().len())) return 0; + const NetEArrayPattern*par_aex; + const NetEConst*par_cex = dynamic_cast (par); + if(!par_cex) { + par_aex = dynamic_cast (par); + if (par_aex) { + const netuarray_t*array = dynamic_cast (par->net_type()); + if (!array) { + cerr << get_fileline() << "tried to get a word from non-array expression" << endl; + return 0; + } + } else { + cerr << get_fileline() << "cannot select element from provided expression" << endl; + } + } + int par_len = par_cex ? par_cex->value().len() : par_aex->item_size(); + + if(! calculate_param_range(*this, par_type, par_msv, par_lsv, par_len)) + return 0; const name_component_t&name_tail = path_.back(); ivl_assert(*this, !name_tail.index.empty()); @@ -5116,43 +5127,55 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope, return res; } // Calculate the canonical index value. - long sel_v = sel_c->value().as_long(); - if (par_msv >= par_lsv) sel_v -= par_lsv; - else sel_v = par_lsv - sel_v; - - // Select a bit from the parameter. - verinum par_v = par_ex->value(); - verinum::V rtn = verinum::Vx; - - // A constant in range select. - if ((sel_v >= 0) && ((unsigned long) sel_v < par_v.len())) { - rtn = par_v[sel_v]; - // An unsized after select. - } else if ((sel_v >= 0) && (! par_v.has_len())) { - if (par_v.has_sign()) rtn = par_v[par_v.len()-1]; - else rtn = verinum::V0; - } else if (warn_ob_select) { - cerr << get_fileline() << ": warning: " - "Constant bit select [" << sel_c->value().as_long() - << "] is "; - if (sel_v < 0) cerr << "before "; - else cerr << "after "; - cerr << name << "["; - if (par_v.has_len()) cerr << par_msv; - else cerr << ""; - cerr << ":" << par_lsv << "]." << endl; - cerr << get_fileline() << ": : " - "Replacing select with a constant 1'bx." << endl; + if (par_cex) { + long sel_v = sel_c->value().as_long(); + if (par_msv >= par_lsv) sel_v -= par_lsv; + else sel_v = par_lsv - sel_v; + + // Select a bit from the parameter. + verinum par_v = par_cex->value(); + verinum::V rtn = verinum::Vx; + + // A constant in range select. + if ((sel_v >= 0) && ((unsigned long) sel_v < par_v.len())) { + rtn = par_v[sel_v]; + // An unsized after select. + } else if ((sel_v >= 0) && (! par_v.has_len())) { + if (par_v.has_sign()) rtn = par_v[par_v.len()-1]; + else rtn = verinum::V0; + } else if (warn_ob_select) { + cerr << get_fileline() << ": warning: " + "Constant bit select [" << sel_c->value().as_long() + << "] is "; + if (sel_v < 0) cerr << "before "; + else cerr << "after "; + cerr << name << "["; + if (par_v.has_len()) cerr << par_msv; + else cerr << ""; + cerr << ":" << par_lsv << "]." << endl; + cerr << get_fileline() << ": : " + "Replacing select with a constant 1'bx." << endl; + } + NetEConst*res = new NetEConst(verinum(rtn, 1)); + res->set_line(*this); + return res; + } else { + long sel_v = sel_c->value().as_long(); + if (par_msv >= par_lsv) sel_v = par_msv - sel_v - par_lsv; + else sel_v -= par_msv; + + // Select a bit from the parameter. + NetExpr*res = (NetExpr *)(par_aex->item(sel_v)->dup_expr()); + //NetEConst*res = new NetEConst(rtn); + res->set_line(*this); + return res; } - NetEConst*res = new NetEConst(verinum(rtn, 1)); - res->set_line(*this); - return res; } sel = normalize_variable_base(sel, par_msv, par_lsv, 1, true); /* Create a parameter reference for the variable select. */ - NetEConstParam*ptmp = new NetEConstParam(found_in, name, par_ex->value()); + NetEConstParam*ptmp = new NetEConstParam(found_in, name, par_cex->value()); NetScope::param_ref_t pref = found_in->find_parameter(name); ptmp->set_line((*pref).second); @@ -5161,78 +5184,6 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope, return tmp; } -NetExpr* PEIdent::elaborate_expr_param_word_(Design*des, NetScope*scope, - const NetExpr*par, - NetScope*found_in, - ivl_type_t par_type, - bool need_const) const -{ - const NetEArrayPattern*par_ex = dynamic_cast (par); - ivl_assert(*this, par_ex); - const netuarray_t*array = dynamic_cast (par->net_type()); - if (!array) { - cerr << get_fileline() << "tried to get a word from non-array expression" << endl; - return 0; - } - - long par_msv, par_lsv; - if(! calculate_param_range(*this, par_type, par_msv, par_lsv, - par_ex->item_size())) return 0; - - const name_component_t&name_tail = path_.back(); - ivl_assert(*this, !name_tail.index.empty()); - const index_component_t&index_tail = name_tail.index.back(); - ivl_assert(*this, index_tail.msb); - ivl_assert(*this, !index_tail.lsb); - - NetExpr*sel = elab_and_eval(des, scope, index_tail.msb, -1, need_const); - if (sel == 0) return 0; - - if (debug_elaborate) - cerr << get_fileline() << ": debug: Calculate bit select " - << "[" << *sel << "] from range " - << "[" << par_msv << ":" << par_lsv << "]." << endl; - - perm_string name = peek_tail_name(path_); - - // Handle the special case that the selection is constant. In this - // case, just precalculate the entire constant result. - NetEConst*sel_c = dynamic_cast (sel); - if (!sel_c) { - cerr << get_fileline() << "tried to get a word with non constant selector" << endl; - return 0; - } - // Special case: If the bit select is constant and not fully - // defined, then we know that the result must be 1'bx. - if (! sel_c->value().is_defined()) { - if (warn_ob_select) { - cerr << get_fileline() << ": warning: " - "Constant undefined bit select [" - << sel_c->value() << "] for parameter '" - << name << "'." << endl; - cerr << get_fileline() << ": : " - "Replacing select with a constant 1'bx." - << endl; - } - - // This is a convenience function for getting the width of an - // element. Strictly speaking it's not necessary. - NetEConst*res = make_const_x(array->element_type()->packed_width()); - res->set_line(*this); - return res; - } - // Calculate the canonical index value. - long sel_v = sel_c->value().as_long(); - if (par_msv >= par_lsv) sel_v = par_msv - sel_v - par_lsv; - else sel_v -= par_msv; - - // Select a bit from the parameter. - NetExpr*res = (NetExpr *)(par_ex->item(sel_v)->dup_expr()); - //NetEConst*res = new NetEConst(rtn); - res->set_line(*this); - return res; -} - NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope, const NetExpr*par, NetScope*, @@ -5575,13 +5526,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST); if (use_sel == index_component_t::SEL_BIT) - if (par->expr_type() == IVL_VT_UARRAY) { - return elaborate_expr_param_word_(des, scope, par, found_in, - par_type, need_const); - } else { return elaborate_expr_param_bit_(des, scope, par, found_in, par_type, need_const); - } if (use_sel == index_component_t::SEL_PART) return elaborate_expr_param_part_(des, scope, par, found_in, diff --git a/ivl_target.h b/ivl_target.h index 42eecc19ac..7e41f6ecd0 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -460,10 +460,9 @@ typedef enum ivl_variable_type_e ENUM_UNSIGNED_INT { IVL_VT_BOOL = 3, IVL_VT_LOGIC = 4, IVL_VT_STRING = 5, - IVL_VT_UARRAY = 6, /* Array (esp. unpacked array) */ - IVL_VT_DARRAY = 7, /* Array (esp. dynamic array) */ - IVL_VT_CLASS = 8, /* SystemVerilog class instances */ - IVL_VT_QUEUE = 9, /* SystemVerilog queue instances */ + IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */ + IVL_VT_CLASS = 7, /* SystemVerilog class instances */ + IVL_VT_QUEUE = 8, /* SystemVerilog queue instances */ IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */ } ivl_variable_type_t; diff --git a/net_design.cc b/net_design.cc index 1144c66487..69b960e3ac 100644 --- a/net_design.cc +++ b/net_design.cc @@ -31,6 +31,7 @@ # include "netlist.h" # include "netscalar.h" # include "netvector.h" +# include "netparray.h" # include "util.h" # include "compiler.h" # include "netmisc.h" @@ -508,31 +509,6 @@ void Design::evaluate_parameters() } } -void NetScope::evaluate_parameter_array_(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_logic_(Design*des, param_ref_t cur) { /* Evaluate the parameter expression. */ @@ -543,6 +519,29 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur) // this case, we'll try to take our type from the r-value. ivl_type_t param_type = cur->second.ivl_type; + // If this parameter is an array, then we need to process it directly + // with the new method + const netuarray_t* param_array = dynamic_cast(param_type); + if (param_array) { + ivl_assert(cur->second, val_expr); + + 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; + } + return; + } + // Most parameter declarations are packed vectors, of the form: // parameter [H:L] foo == bar; // so get the netvector_t. Note that this may also be the special @@ -901,10 +900,6 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) evaluate_parameter_real_(des, cur); break; - case IVL_VT_UARRAY: - evaluate_parameter_array_(des, cur); - break; - case IVL_VT_STRING: evaluate_parameter_string_(des, cur); break; diff --git a/netlist.h b/netlist.h index 3db5adf553..0637ae98af 100644 --- a/netlist.h +++ b/netlist.h @@ -1251,7 +1251,6 @@ class NetScope : public Definitions, public Attrib { std::map loop_index_tmp; private: - void evaluate_parameter_array_(Design*des, param_ref_t cur); 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); diff --git a/netmisc.cc b/netmisc.cc index e9e50e3ceb..17494acfda 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1023,11 +1023,10 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe, // Catch some special cases. switch (cast_type) { case IVL_VT_DARRAY: - case IVL_VT_UARRAY: case IVL_VT_QUEUE: if (NetESignal*net = dynamic_cast(tmp)) { ivl_variable_type_t type = net->expr_type(); - if ((type == IVL_VT_UARRAY) || (type == IVL_VT_DARRAY) || (type == IVL_VT_QUEUE)) + if ((type == IVL_VT_DARRAY) || (type == IVL_VT_QUEUE)) return tmp; } if (dynamic_cast(pe)) @@ -1827,52 +1826,45 @@ void check_for_inconsistent_delays(NetScope*scope) bool calculate_param_range(const LineInfo&line, ivl_type_t par_type, long&par_msv, long&par_lsv, long length) { - switch(par_type->base_type()) { - case IVL_VT_VECTOR: { - const netvector_t*vector_type = dynamic_cast (par_type); - - ivl_assert(line, vector_type->packed()); - const std::vector& packed_dims = vector_type->packed_dims(); - - // This is a netvector_t with 0 dimensions, then the parameter was - // declared with a statement like this: - // - // parameter signed foo = ; - // - // The netvector_t is just here to carry the signed-ness, which we don't - // even need here. So act like the type is defined by the r-value - // length. - if (packed_dims.size() == 0) { - par_msv = length-1; - par_lsv = 0; - return true; - } - ivl_assert(line, packed_dims.size() == 1); - - netrange_t use_range = packed_dims[0]; - par_msv = use_range.get_msb(); - par_lsv = use_range.get_lsb(); - - return true; - } - case IVL_VT_UARRAY: { - const netsarray_t*array_type = dynamic_cast (par_type); - - ivl_assert(line, array_type); - const std::vector& unpacked_dims = array_type->static_dimensions(); - ivl_assert(line, unpacked_dims.size() == 1); - - netrange_t use_range = unpacked_dims[0]; - par_msv = use_range.get_msb(); - par_lsv = use_range.get_lsb(); - return true; - } - - default: - // If the parameter doesn't have an explicit range, then - // just return range values of [length-1:0]. - par_msv = length-1; - par_lsv = 0; - return true; - } + const netvector_t*vector_type = dynamic_cast (par_type); + if (vector_type) { + ivl_assert(line, vector_type->packed()); + const std::vector& packed_dims = vector_type->packed_dims(); + // This is a netvector_t with 0 dimensions, then the parameter was + // declared with a statement like this: + // + // parameter signed foo = ; + // + // The netvector_t is just here to carry the signed-ness, which we don't + // even need here. So act like the type is defined by the r-value + // length. + if (packed_dims.size() == 0) { + par_msv = length-1; + par_lsv = 0; + return true; + } + ivl_assert(line, packed_dims.size() == 1); + + netrange_t use_range = packed_dims[0]; + par_msv = use_range.get_msb(); + par_lsv = use_range.get_lsb(); + + return true; + } + const netsarray_t*array_type = dynamic_cast (par_type); + if (array_type) { + ivl_assert(line, array_type); + const std::vector& unpacked_dims = array_type->static_dimensions(); + ivl_assert(line, unpacked_dims.size() == 1); + + netrange_t use_range = unpacked_dims[0]; + par_msv = use_range.get_msb(); + par_lsv = use_range.get_lsb(); + return true; + } + // If the parameter doesn't have an explicit range, then + // just return range values of [length-1:0]. + par_msv = length-1; + par_lsv = 0; + return true; } diff --git a/netparray.cc b/netparray.cc index 5db231635c..0c0181c0c1 100644 --- a/netparray.cc +++ b/netparray.cc @@ -76,8 +76,3 @@ vector netuarray_t::slice_dimensions() const { return static_dimensions(); } - -ivl_variable_type_t netuarray_t::base_type(void) const -{ - return IVL_VT_UARRAY; -} diff --git a/netparray.h b/netparray.h index c545a42759..6be2da4d0e 100644 --- a/netparray.h +++ b/netparray.h @@ -86,11 +86,6 @@ class netuarray_t : public netsarray_t { ivl_type_t etype); ~netuarray_t(); - // This is the "base_type()" virtual method of the - // nettype_base_t. The ivl_target api expects this to return - // IVL_VT_DARRAY for dynamic arrays? - ivl_variable_type_t base_type() const; - public: // Virtual methods from the ivl_type_s type... std::vector slice_dimensions() const; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index e569b78f8a..670962f7a8 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -169,9 +169,6 @@ const char*data_type_string(ivl_variable_type_t vtype) case IVL_VT_STRING: vt = "string"; break; - case IVL_VT_UARRAY: - vt = "uarray"; - break; case IVL_VT_DARRAY: vt = "darray"; break; diff --git a/tgt-stub/types.c b/tgt-stub/types.c index 0291a836b6..38a6b38c6a 100644 --- a/tgt-stub/types.c +++ b/tgt-stub/types.c @@ -60,9 +60,6 @@ void show_net_type(ivl_type_t net_type) case IVL_VT_STRING: fprintf(out, "string"); break; - case IVL_VT_UARRAY: - fprintf(out, "uarray"); - break; case IVL_VT_DARRAY: show_net_type_darray(net_type); break; @@ -121,9 +118,6 @@ void show_type_of_signal(ivl_signal_t net) case IVL_VT_STRING: fprintf(out, "string"); break; - case IVL_VT_UARRAY: - fprintf(out, "uarray"); - break; case IVL_VT_DARRAY: /* The DARRAY type MUST be described by an ivl_signal_net_type object. */ diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 8fbfcdcb0e..24dfdc1469 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -2507,7 +2507,6 @@ void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex) case IVL_VT_LOGIC: fprintf(stderr, " logic"); break; case IVL_VT_STRING: fprintf(stderr, " string"); break; case IVL_VT_DARRAY: fprintf(stderr, " dynamic array"); break; - case IVL_VT_UARRAY: fprintf(stderr, " unpacked array"); break; case IVL_VT_CLASS: fprintf(stderr, " class"); break; case IVL_VT_QUEUE: fprintf(stderr, " queue"); break; } diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 6f9311ebaa..c64320a9f4 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -427,7 +427,6 @@ static void draw_vpi_taskfunc_args(const char*call_string, str_stack_need += 1; buffer[0] = 0; break; - case IVL_VT_UARRAY: case IVL_VT_DARRAY: fprintf(stderr, "%s:%u: Unsupported array argument\n", ivl_expr_file(expr), ivl_expr_lineno(expr)); default: From 8f8aa3c17bb284d2eed2087c450f2481daa7433a Mon Sep 17 00:00:00 2001 From: Pierre-Henri Horrein Date: Sun, 2 May 2021 22:57:14 +0200 Subject: [PATCH 3/4] fixup: minor fixes (error messages + real unpacked arrays) --- elab_expr.cc | 63 ++++++++++++++++++++++++++------------------------- net_design.cc | 24 ++++++++++++++++++++ 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 017ae36a06..66840c4727 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -215,9 +215,16 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, return tmp; } - const netarray_t*array_type = dynamic_cast (ntype); + const netsarray_t*array_type = dynamic_cast (ntype); if (array_type) { + if (array_type->static_dimensions().size() > 1) { + des->errors += 1; + cerr << get_fileline() << ": sorry: I don't know how to elaborate " + << "multi-dimensions assignment patterns." << endl; + return 0; + } + // This is an array pattern, so run through the elements of // the expression and elaborate each as if they are // element_type expressions. @@ -686,12 +693,12 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope, NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, flags); if (lp && debug_elaborate) { cerr << get_fileline() << ": PEBComp::elaborate_expr: " - << "Elaborated left_: " << *lp << endl; + << "Elaborated left_: " << *lp << ", width_: " << l_width_ << endl; } NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, flags); if (rp && debug_elaborate) { cerr << get_fileline() << ": PEBComp::elaborate_expr: " - << "Elaborated right_: " << *rp << endl; + << "Elaborated right_: " << *rp << ", width_: " << r_width_ << endl; } if ((lp == 0) || (rp == 0)) { @@ -4065,24 +4072,28 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) if (par != 0) { const netuarray_t*array = dynamic_cast (par->net_type()); if (array) { - switch (use_sel) { - case index_component_t::SEL_BIT: - case index_component_t::SEL_BIT_LAST: - expr_type_ = array->element_type()->base_type(); - expr_width_ = array->element_type()->packed_width(); - min_width_ = expr_width_; - signed_flag_ = array->element_type()->get_signed(); - break; - default: - expr_type_ = array->base_type(); - expr_width_ = array->static_dimensions()[0].width(); - min_width_ = expr_width_; - signed_flag_ = false; - break; - } - return expr_width_; - } - } + switch (use_sel) { + case index_component_t::SEL_BIT: + case index_component_t::SEL_BIT_LAST: + expr_type_ = array->element_type()->base_type(); + if (expr_type_ == IVL_VT_STRING) { + des->errors += 1; + cerr << get_fileline() << ": sorry, I do not yet support string array parameters properly" << endl; + } + expr_width_ = array->element_type()->packed_width(); + min_width_ = expr_width_; + signed_flag_ = array->element_type()->get_signed(); + break; + default: + expr_type_ = array->base_type(); + expr_width_ = array->static_dimensions()[0].width(); + min_width_ = expr_width_; + signed_flag_ = false; + break; + } + return expr_width_; + } + } // Look for a class property. if (gn_system_verilog() && cls_val) { @@ -5166,7 +5177,6 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope, // Select a bit from the parameter. NetExpr*res = (NetExpr *)(par_aex->item(sel_v)->dup_expr()); - //NetEConst*res = new NetEConst(rtn); res->set_line(*this); return res; } @@ -5514,15 +5524,6 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, if (!name_tail.index.empty()) use_sel = name_tail.index.back().sel; - if (par->expr_type() == IVL_VT_REAL && - use_sel != index_component_t::SEL_NONE) { - perm_string name = peek_tail_name(path_); - cerr << get_fileline() << ": error: " - << "can not select part of real parameter: " << name << endl; - des->errors += 1; - return 0; - } - ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST); if (use_sel == index_component_t::SEL_BIT) diff --git a/net_design.cc b/net_design.cc index 69b960e3ac..4c018d9a12 100644 --- a/net_design.cc +++ b/net_design.cc @@ -731,7 +731,31 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur) NetScope*val_scope = (*cur).second.val_scope; ivl_type_t param_type = cur->second.ivl_type; + ivl_assert(cur->second, val_expr); ivl_assert(*val_expr, param_type); + + // If this parameter is an array, then we need to process it directly + // with the new method + const netuarray_t* param_array = dynamic_cast(param_type); + if (param_array) { + + 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; + } + return; + } + NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true, cur->second.is_annotatable, param_type->base_type()); From b8dc6b8fd52406dbf83d46a3320d406c875da0f1 Mon Sep 17 00:00:00 2001 From: Pierre-Henri Horrein Date: Mon, 3 May 2021 00:59:21 +0200 Subject: [PATCH 4/4] fixup: readding inadvertently removed test when selecting a bit --- elab_expr.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 66840c4727..66ea49d112 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -215,10 +215,10 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, return tmp; } - const netsarray_t*array_type = dynamic_cast (ntype); + const netarray_t*array_type = dynamic_cast (ntype); if (array_type) { - if (array_type->static_dimensions().size() > 1) { + if (array_type->slice_dimensions().size() > 1) { des->errors += 1; cerr << get_fileline() << ": sorry: I don't know how to elaborate " << "multi-dimensions assignment patterns." << endl; @@ -5520,10 +5520,19 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, const name_component_t&name_tail = path_.back(); index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; - // FIXME: this won't work with multidimensional array if (!name_tail.index.empty()) use_sel = name_tail.index.back().sel; + if (par->expr_type() == IVL_VT_REAL && + use_sel != index_component_t::SEL_NONE && + dynamic_cast(par) == 0) { + perm_string name = peek_tail_name(path_); + cerr << get_fileline() << ": error: " + << "can not select part of real parameter: " << name << endl; + des->errors += 1; + return 0; + } + ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST); if (use_sel == index_component_t::SEL_BIT)