From 6cc1010281782c579e17579090419c00e1d585c6 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Tue, 18 Dec 2012 10:43:07 -0800 Subject: [PATCH] Handle part select of packed struct members. This fixes the case of part select of struct members in continuous assignment l-values. --- elab_net.cc | 29 ++++++++++++++++++++++++++++- netmisc.h | 4 ++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/elab_net.cc b/elab_net.cc index abd98a62e..6cc0ed66c 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -490,7 +490,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, // (NetNet). We also know that sig is struct_type(), so // look for a method named method_name. if (debug_elaborate) - cerr << get_fileline() << ": debug: " + cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " << "Signal " << sig->name() << " is a structure, " << "try to match member " << method_name << endl; @@ -498,6 +498,14 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, const struct netstruct_t::member_t*member = struct_type->packed_member(method_name, member_off); ivl_assert(*this, member); + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " + << "Member " << method_name + << " has packed dimensions " << member->packed_dims << "." << endl; + cerr << get_fileline() << ": : " + << "Tail name has " << path_tail.index.size() << " indices." << endl; + } + // Rewrite a member select of a packed structure as a // part select of the base variable. lidx = member_off; @@ -540,6 +548,25 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, // Currently, only support const dimensions here. ivl_assert(*this, packed_base == 0); + // Now the lidx/midx values get us to the member. Next + // up, deal with bit/part selects from the member + // itself. + ivl_assert(*this, member->packed_dims.size() <= 1); + ivl_assert(*this, path_tail.index.size() <= 1); + if (path_tail.index.size() > 0) { + long tmp_off; + unsigned long tmp_wid; + const index_component_t&tail_sel = path_tail.index.back(); + ivl_assert(*this, tail_sel.sel == index_component_t::SEL_PART || tail_sel.sel == index_component_t::SEL_BIT); + bool rc = calculate_part(this, des, scope, tail_sel, tmp_off, tmp_wid); + ivl_assert(*this, rc); + if (debug_elaborate) + cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " + << "tmp_off=" << tmp_off << ", tmp_wid=" << tmp_wid << endl; + lidx += tmp_off; + midx = lidx + tmp_wid - 1; + } + } else if (sig->unpacked_dimensions() > 0) { // Make sure there are enough indices to address an array element. diff --git a/netmisc.h b/netmisc.h index 792f62ac8..d075ae40f 100644 --- a/netmisc.h +++ b/netmisc.h @@ -95,6 +95,10 @@ extern NetExpr*condition_reduce(NetExpr*expr); */ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w); +extern bool calculate_part(const LineInfo*li, Design*des, NetScope*scope, + const index_component_t&index, + long&off, unsigned long&wid); + /* * These functions generate an equation to normalize an expression using * the provided vector/array information.