diff --git a/elab_expr.cc b/elab_expr.cc index f886e7197..d7d6c35de 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3514,8 +3514,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, // complicated task because we need to generate // expressions to convert calculated bit select // values to canonical values that are used internally. - assert(sig_packed.size() == 1); - mux = normalize_variable_base(mux, sig_packed, 1, true); + mux = normalize_variable_bit_base(prefix_indices, mux, net->sig()); NetESelect*ss = new NetESelect(net, mux, 1); ss->set_line(*this); diff --git a/elab_lval.cc b/elab_lval.cc index cf1aecb8b..b34143a80 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -408,7 +408,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des, // Non-constant bit mux. Correct the mux for the range // of the vector, then set the l-value part select // expression. - mux = normalize_variable_base(mux, reg->packed_dims(), 1, true); + mux = normalize_variable_bit_base(prefix_indices, mux, reg); lv->set_part(mux, 1); } else if (reg->vector_width() == 1 && reg->sb_is_valid(prefix_indices,lsb)) { diff --git a/netmisc.cc b/netmisc.cc index c6e94e881..d4285c82e 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -239,10 +239,13 @@ static unsigned num_bits(long arg) /* * This routine generates the normalization expression needed for a variable - * bit select or a variable base expression for an indexed part select. + * bit select or a variable base expression for an indexed part + * select. This function doesn't actually look at the variable + * dimensions, it just does the final calculation using msb/lsb of the + * last slice, and the off of the slice in the variable. */ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb, - unsigned long wid, bool is_up) + unsigned long wid, bool is_up, long soff) { long offset = lsb; @@ -275,13 +278,13 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb, base = tmp; } /* Normalize the expression. */ - base = make_sub_expr(offset, base); + base = make_sub_expr(offset+soff, base); } else { /* Correct the offset if needed. */ if (!is_up) offset += wid - 1; /* If the offset is zero then just return the base (index) * expression. */ - if (offset == 0) return base; + if ((soff-offset) == 0) return base; /* Calculate the space needed for the offset. */ unsigned min_wid = num_bits(-offset); /* We need enough space for the larger of the offset or the @@ -304,7 +307,7 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb, base = tmp; } /* Normalize the expression. */ - base = make_add_expr(base, -offset); + base = make_add_expr(base, soff-offset); } return base; @@ -325,6 +328,21 @@ NetExpr *normalize_variable_base(NetExpr *base, return normalize_variable_base(base, rng.msb, rng.lsb, wid, is_up); } +NetExpr *normalize_variable_bit_base(const list&indices, NetExpr*base, + const NetNet*reg) +{ + const list&packed_dims = reg->packed_dims(); + ivl_assert(*base, indices.size()+1 == packed_dims.size()); + + // Get the canonical offset of the slice within which we are + // addressing. We need that address as a slice offset to + // calculate the proper complete address + const NetNet::range_t&rng = packed_dims.back(); + long slice_off = reg->sb_to_idx(indices, rng.lsb); + + return normalize_variable_base(base, rng.msb, rng.lsb, 1, true, slice_off); +} + NetExpr *normalize_variable_slice_base(const list&indices, NetExpr*base, const NetNet*reg, unsigned long&lwid) { diff --git a/netmisc.h b/netmisc.h index 91d1fcfd9..45b9238c2 100644 --- a/netmisc.h +++ b/netmisc.h @@ -99,10 +99,15 @@ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w); * the provided vector/array information. */ extern NetExpr*normalize_variable_base(NetExpr *base, long msb, long lsb, - unsigned long wid, bool is_up); + unsigned long wid, bool is_up, + long slice_off =0); extern NetExpr*normalize_variable_base(NetExpr *base, const list&dims, unsigned long wid, bool is_up); + +extern NetExpr*normalize_variable_bit_base(const list&indices, NetExpr *base, + const NetNet*reg); + extern NetExpr*normalize_variable_slice_base(const list&indices, NetExpr *base, const NetNet*reg, unsigned long&lwid); extern NetExpr*normalize_variable_array_base(NetExpr *base, long offset,