Support non-constant indexed part select of packed arrays.

This commit is contained in:
Stephen Williams 2012-02-12 14:52:47 -08:00
parent 5e067bd651
commit 77f168cf28
4 changed files with 58 additions and 17 deletions

View File

@ -3299,13 +3299,12 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
return ss;
}
if (net->sig()->packed_dims().size() > 1) {
cerr << get_fileline() << ": sorry: Indexed part select of packed arrays not supported here." << endl;
des->errors += 1;
return net;
}
base = normalize_variable_base(base, net->msi(), net->lsi(), wid, true);
ivl_assert(*this, prefix_indices.size()+1 == net->sig()->packed_dims().size());
// Convert the non-constant part select index expression into
// an expression that returns a canonical base.
base = normalize_variable_part_base(prefix_indices, base, net->sig(), wid, true);
NetESelect*ss = new NetESelect(net, base, wid, IVL_SEL_IDX_UP);
ss->set_line(*this);

View File

@ -598,22 +598,16 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
}
}
} else {
if (reg->packed_dims().size() > 1) {
cerr << get_fileline() << ": sorry: "
<< "Indexed part select of packed arrays not supported nere." << endl;
des->errors += 1;
return false;
}
ivl_assert(*this, prefix_indices.size()+1 == reg->packed_dims().size());
/* Correct the mux for the range of the vector. */
if (use_sel == index_component_t::SEL_IDX_UP) {
base = normalize_variable_base(base, reg->packed_dims(),
wid, true);
base = normalize_variable_part_base(prefix_indices, base,
reg, wid, true);
sel_type = IVL_SEL_IDX_UP;
} else {
// This is assumed to be a SEL_IDX_DO.
base = normalize_variable_base(base, reg->packed_dims(),
wid, false);
base = normalize_variable_part_base(prefix_indices, base,
reg, wid, false);
sel_type = IVL_SEL_IDX_DOWN;
}
}

View File

@ -343,6 +343,22 @@ NetExpr *normalize_variable_bit_base(const list<long>&indices, NetExpr*base,
return normalize_variable_base(base, rng.msb, rng.lsb, 1, true, slice_off);
}
NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
const NetNet*reg,
unsigned long wid, bool is_up)
{
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, wid, is_up, slice_off);
}
NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
const NetNet*reg, unsigned long&lwid)
{

View File

@ -105,11 +105,43 @@ extern NetExpr*normalize_variable_base(NetExpr *base,
const list<NetNet::range_t>&dims,
unsigned long wid, bool is_up);
/*
* Calculate a canonicalizing expression for a bit select, when the
* base expression is the last index of an otherwise complete bit
* select. For example:
* reg [3:0][7:0] foo;
* ... foo[1][x] ...
* base is (x) and the generated expression will be (x+8).
*/
extern NetExpr*normalize_variable_bit_base(const list<long>&indices, NetExpr *base,
const NetNet*reg);
/*
* This is similar to normalize_variable_bit_base, but the tail index
* it a base and width, instead of a bit. This is used for handling
* indexed part selects:
* reg [3:0][7:0] foo;
* ... foo[1][x +: 2]
* base is (x), wid input is (2), and is_up is (true). The output
* expression is (x+8).
*/
extern NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
const NetNet*reg,
unsigned long wid, bool is_up);
/*
* Calculate a canonicalizing expression for a slice select. The
* indices array is less then needed to fully address a bit, so the
* result is a slice of the packed array. The return value is an
* expression that gets to the base of the slice, and (lwid) becomes
* the width of the slice, in bits. For example:
* reg [4:1][7:0] foo
* ...foo[x]...
* base is (x) and the generated expression will be (x*8 - 8), with
* lwid set to (8).
*/
extern NetExpr*normalize_variable_slice_base(const list<long>&indices, NetExpr *base,
const NetNet*reg, unsigned long&lwid);
extern NetExpr*normalize_variable_array_base(NetExpr *base, long offset,
unsigned count);