Handle indexed bit select of packed arrays.

This handles a few cases where the non-constant bit selects are
in the final index. This doesn't handle all the cases of packed
arrays, but it handles some common cases.
This commit is contained in:
Stephen Williams 2012-02-12 10:13:20 -08:00
parent 4287fc4b50
commit 6eeef8311f
4 changed files with 31 additions and 9 deletions

View File

@ -3514,8 +3514,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
// complicated task because we need to generate // complicated task because we need to generate
// expressions to convert calculated bit select // expressions to convert calculated bit select
// values to canonical values that are used internally. // values to canonical values that are used internally.
assert(sig_packed.size() == 1); mux = normalize_variable_bit_base(prefix_indices, mux, net->sig());
mux = normalize_variable_base(mux, sig_packed, 1, true);
NetESelect*ss = new NetESelect(net, mux, 1); NetESelect*ss = new NetESelect(net, mux, 1);
ss->set_line(*this); ss->set_line(*this);

View File

@ -408,7 +408,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
// Non-constant bit mux. Correct the mux for the range // Non-constant bit mux. Correct the mux for the range
// of the vector, then set the l-value part select // of the vector, then set the l-value part select
// expression. // 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); lv->set_part(mux, 1);
} else if (reg->vector_width() == 1 && reg->sb_is_valid(prefix_indices,lsb)) { } else if (reg->vector_width() == 1 && reg->sb_is_valid(prefix_indices,lsb)) {

View File

@ -239,10 +239,13 @@ static unsigned num_bits(long arg)
/* /*
* This routine generates the normalization expression needed for a variable * 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, 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; long offset = lsb;
@ -275,13 +278,13 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb,
base = tmp; base = tmp;
} }
/* Normalize the expression. */ /* Normalize the expression. */
base = make_sub_expr(offset, base); base = make_sub_expr(offset+soff, base);
} else { } else {
/* Correct the offset if needed. */ /* Correct the offset if needed. */
if (!is_up) offset += wid - 1; if (!is_up) offset += wid - 1;
/* If the offset is zero then just return the base (index) /* If the offset is zero then just return the base (index)
* expression. */ * expression. */
if (offset == 0) return base; if ((soff-offset) == 0) return base;
/* Calculate the space needed for the offset. */ /* Calculate the space needed for the offset. */
unsigned min_wid = num_bits(-offset); unsigned min_wid = num_bits(-offset);
/* We need enough space for the larger of the offset or the /* 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; base = tmp;
} }
/* Normalize the expression. */ /* Normalize the expression. */
base = make_add_expr(base, -offset); base = make_add_expr(base, soff-offset);
} }
return base; return base;
@ -325,6 +328,21 @@ NetExpr *normalize_variable_base(NetExpr *base,
return normalize_variable_base(base, rng.msb, rng.lsb, wid, is_up); return normalize_variable_base(base, rng.msb, rng.lsb, wid, is_up);
} }
NetExpr *normalize_variable_bit_base(const list<long>&indices, NetExpr*base,
const NetNet*reg)
{
const list<NetNet::range_t>&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<long>&indices, NetExpr*base, NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
const NetNet*reg, unsigned long&lwid) const NetNet*reg, unsigned long&lwid)
{ {

View File

@ -99,10 +99,15 @@ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
* the provided vector/array information. * the provided vector/array information.
*/ */
extern NetExpr*normalize_variable_base(NetExpr *base, long msb, long lsb, 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, extern NetExpr*normalize_variable_base(NetExpr *base,
const list<NetNet::range_t>&dims, const list<NetNet::range_t>&dims,
unsigned long wid, bool is_up); unsigned long wid, bool is_up);
extern NetExpr*normalize_variable_bit_base(const list<long>&indices, NetExpr *base,
const NetNet*reg);
extern NetExpr*normalize_variable_slice_base(const list<long>&indices, NetExpr *base, extern NetExpr*normalize_variable_slice_base(const list<long>&indices, NetExpr *base,
const NetNet*reg, unsigned long&lwid); const NetNet*reg, unsigned long&lwid);
extern NetExpr*normalize_variable_array_base(NetExpr *base, long offset, extern NetExpr*normalize_variable_array_base(NetExpr *base, long offset,