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:
parent
4287fc4b50
commit
6eeef8311f
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)) {
|
||||||
|
|
|
||||||
28
netmisc.cc
28
netmisc.cc
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue