From 0ecb71625bad184016ec624d973500232a47df3b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 5 Jul 2025 18:02:40 +0100 Subject: [PATCH] Support assignment of parray slices (issue #1256) The existing elaboration code only allowed assignments from/to individual elements and either failed an assertion (when assigning the entire array) or failed to compile (when assigning an array slice). --- elab_expr.cc | 21 +++++++++++++-------- elab_lval.cc | 18 ++++++++++-------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 8b77b9c76..73fa40048 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2024 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -2585,14 +2585,21 @@ static NetExpr* check_for_struct_members(const LineInfo*li, // variable, then stepping to the element type to // possibly iterate through more of the member_path. ivl_assert(*li, array->packed()); - ivl_assert(*li, !member_comp.index.empty()); + + // We only need to process this if there are any + // index expressions. If not, then the packed + // array can be handled atomically. + if (member_comp.index.empty()) { + struct_type = 0; + continue; + } // These are the dimensions defined by the type const netranges_t&mem_packed_dims = array->static_dimensions(); - if (member_comp.index.size() != mem_packed_dims.size()) { + if (member_comp.index.size() > mem_packed_dims.size()) { cerr << li->get_fileline() << ": error: " - << "Incorrect number of index expressions for member " + << "Too many index expressions for member " << member_name << "." << endl; des->errors += 1; return 0; @@ -2634,11 +2641,9 @@ static NetExpr* check_for_struct_members(const LineInfo*li, // The width and offset calculated from the // indices is actually in elements, and not - // bits. In fact, in this context, the lwid should - // come down to 1 (one element). + // bits. off += loff * element_width; - ivl_assert(*li, lwid==1); - use_width = element_width; + use_width = lwid * element_width; // To move on to the next component in the member // path, get the element type. For example, for diff --git a/elab_lval.cc b/elab_lval.cc index 96aad5545..e1c88dab8 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2024 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2025 Stephen Williams (steve@icarus.com) * Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1445,14 +1445,18 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, // possibly iterate through more of the member_path. ivl_assert(*this, array->packed()); - ivl_assert(*this, !member_comp.index.empty()); + + if (member_comp.index.empty()) { + struct_type = 0; + continue; + } // These are the dimensions defined by the type const netranges_t&mem_packed_dims = array->static_dimensions(); - if (member_comp.index.size() != mem_packed_dims.size()) { + if (member_comp.index.size() > mem_packed_dims.size()) { cerr << get_fileline() << ": error: " - << "Incorrect number of index expressions for member " + << "Too many index expressions for member " << member_name << "." << endl; des->errors += 1; return false; @@ -1502,11 +1506,9 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, // The width and offset calculated from the // indices is actually in elements, and not - // bits. In fact, in this context, the lwid should - // come down to 1 (one element). + // bits. off += loff * element_width; - ivl_assert(*this, lwid==1); - use_width = element_width; + use_width = lwid * element_width; // To move on to the next component in the member // path, get the element type. For example, for