Support non-constant indexed part select of packed arrays.
This commit is contained in:
parent
5e067bd651
commit
77f168cf28
11
elab_expr.cc
11
elab_expr.cc
|
|
@ -3299,13 +3299,12 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||||
return ss;
|
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);
|
NetESelect*ss = new NetESelect(net, base, wid, IVL_SEL_IDX_UP);
|
||||||
ss->set_line(*this);
|
ss->set_line(*this);
|
||||||
|
|
|
||||||
16
elab_lval.cc
16
elab_lval.cc
|
|
@ -598,22 +598,16 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (reg->packed_dims().size() > 1) {
|
ivl_assert(*this, prefix_indices.size()+1 == reg->packed_dims().size());
|
||||||
cerr << get_fileline() << ": sorry: "
|
|
||||||
<< "Indexed part select of packed arrays not supported nere." << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Correct the mux for the range of the vector. */
|
/* Correct the mux for the range of the vector. */
|
||||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||||
base = normalize_variable_base(base, reg->packed_dims(),
|
base = normalize_variable_part_base(prefix_indices, base,
|
||||||
wid, true);
|
reg, wid, true);
|
||||||
sel_type = IVL_SEL_IDX_UP;
|
sel_type = IVL_SEL_IDX_UP;
|
||||||
} else {
|
} else {
|
||||||
// This is assumed to be a SEL_IDX_DO.
|
// This is assumed to be a SEL_IDX_DO.
|
||||||
base = normalize_variable_base(base, reg->packed_dims(),
|
base = normalize_variable_part_base(prefix_indices, base,
|
||||||
wid, false);
|
reg, wid, false);
|
||||||
sel_type = IVL_SEL_IDX_DOWN;
|
sel_type = IVL_SEL_IDX_DOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
netmisc.cc
16
netmisc.cc
|
|
@ -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);
|
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,
|
NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
|
||||||
const NetNet*reg, unsigned long&lwid)
|
const NetNet*reg, unsigned long&lwid)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
32
netmisc.h
32
netmisc.h
|
|
@ -105,11 +105,43 @@ 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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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,
|
extern NetExpr*normalize_variable_bit_base(const list<long>&indices, NetExpr *base,
|
||||||
const NetNet*reg);
|
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,
|
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,
|
||||||
unsigned count);
|
unsigned count);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue