Support indexed part selects that index sub-arrays (issue #497)
(cherry picked from commit 4af830187e)
This commit is contained in:
parent
cccf36d76f
commit
c0c46dc173
54
elab_expr.cc
54
elab_expr.cc
|
|
@ -5243,19 +5243,36 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||||
NetExpr*ex;
|
NetExpr*ex;
|
||||||
if (base_c->value().is_defined()) {
|
if (base_c->value().is_defined()) {
|
||||||
long lsv = base_c->value().as_long();
|
long lsv = base_c->value().as_long();
|
||||||
long offset = 0;
|
long rel_base = 0;
|
||||||
// Get the signal range.
|
// Get the signal range.
|
||||||
const vector<netrange_t>&packed = net->sig()->packed_dims();
|
const vector<netrange_t>&packed = net->sig()->packed_dims();
|
||||||
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
|
if (prefix_indices.size()+1 < net->sig()->packed_dims().size()) {
|
||||||
|
// Here we are selecting one or more sub-arrays.
|
||||||
|
// Make this work by finding the indexed sub-arrays and
|
||||||
|
// creating a generated slice that spans the whole range.
|
||||||
|
long loff, moff;
|
||||||
|
unsigned long lwid, mwid;
|
||||||
|
bool lrc;
|
||||||
|
lrc = net->sig()->sb_to_slice(prefix_indices, lsv, moff, mwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
lrc = net->sig()->sb_to_slice(prefix_indices, lsv+(wid/mwid)-1, loff, lwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
ivl_assert(*this, lwid == mwid);
|
||||||
|
|
||||||
|
if (moff > loff) {
|
||||||
|
rel_base = loff;
|
||||||
|
} else {
|
||||||
|
rel_base = moff;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
long offset = 0;
|
||||||
// We want the last range, which is where we work.
|
// We want the last range, which is where we work.
|
||||||
const netrange_t&rng = packed.back();
|
const netrange_t&rng = packed.back();
|
||||||
if (rng.get_msb() < rng.get_lsb()) {
|
if (rng.get_msb() < rng.get_lsb()) {
|
||||||
offset = -wid + 1;
|
offset = -wid + 1;
|
||||||
}
|
}
|
||||||
|
rel_base = net->sig()->sb_to_idx(prefix_indices, lsv) + offset;
|
||||||
long rel_base = net->sig()->sb_to_idx(prefix_indices, lsv);
|
}
|
||||||
rel_base += offset;
|
|
||||||
|
|
||||||
// If the part select covers exactly the entire
|
// If the part select covers exactly the entire
|
||||||
// vector, then do not bother with it. Return the
|
// vector, then do not bother with it. Return the
|
||||||
|
|
@ -5347,19 +5364,36 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||||
NetExpr*ex;
|
NetExpr*ex;
|
||||||
if (base_c->value().is_defined()) {
|
if (base_c->value().is_defined()) {
|
||||||
long lsv = base_c->value().as_long();
|
long lsv = base_c->value().as_long();
|
||||||
long offset = 0;
|
long rel_base = 0;
|
||||||
// Get the signal range.
|
// Get the signal range.
|
||||||
const vector<netrange_t>&packed = net->sig()->packed_dims();
|
const vector<netrange_t>&packed = net->sig()->packed_dims();
|
||||||
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
|
if (prefix_indices.size()+1 < net->sig()->packed_dims().size()) {
|
||||||
|
// Here we are selecting one or more sub-arrays.
|
||||||
|
// Make this work by finding the indexed sub-arrays and
|
||||||
|
// creating a generated slice that spans the whole range.
|
||||||
|
long loff, moff;
|
||||||
|
unsigned long lwid, mwid;
|
||||||
|
bool lrc;
|
||||||
|
lrc = net->sig()->sb_to_slice(prefix_indices, lsv, moff, mwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
lrc = net->sig()->sb_to_slice(prefix_indices, lsv-(wid/mwid)+1, loff, lwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
ivl_assert(*this, lwid == mwid);
|
||||||
|
|
||||||
|
if (moff > loff) {
|
||||||
|
rel_base = loff;
|
||||||
|
} else {
|
||||||
|
rel_base = moff;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
long offset = 0;
|
||||||
// We want the last range, which is where we work.
|
// We want the last range, which is where we work.
|
||||||
const netrange_t&rng = packed.back();
|
const netrange_t&rng = packed.back();
|
||||||
if (rng.get_msb() > rng.get_lsb()) {
|
if (rng.get_msb() > rng.get_lsb()) {
|
||||||
offset = -wid + 1;
|
offset = -wid + 1;
|
||||||
}
|
}
|
||||||
|
rel_base = net->sig()->sb_to_idx(prefix_indices, lsv) + offset;
|
||||||
long rel_base = net->sig()->sb_to_idx(prefix_indices, lsv);
|
}
|
||||||
rel_base += offset;
|
|
||||||
|
|
||||||
// If the part select covers exactly the entire
|
// If the part select covers exactly the entire
|
||||||
// vector, then do not bother with it. Return the
|
// vector, then do not bother with it. Return the
|
||||||
|
|
|
||||||
30
elab_lval.cc
30
elab_lval.cc
|
|
@ -938,11 +938,34 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||||
// we will handle it in the code generator.
|
// we will handle it in the code generator.
|
||||||
if (base_c->value().is_defined()) {
|
if (base_c->value().is_defined()) {
|
||||||
long lsv = base_c->value().as_long();
|
long lsv = base_c->value().as_long();
|
||||||
long offset = 0;
|
long rel_base = 0;
|
||||||
// Get the signal range.
|
// Get the signal range.
|
||||||
const vector<netrange_t>&packed = reg->packed_dims();
|
const vector<netrange_t>&packed = reg->packed_dims();
|
||||||
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
|
if (prefix_indices.size()+1 < reg->packed_dims().size()) {
|
||||||
|
// Here we are selecting one or more sub-arrays.
|
||||||
|
// Make this work by finding the indexed sub-arrays and
|
||||||
|
// creating a generated slice that spans the whole range.
|
||||||
|
long loff, moff;
|
||||||
|
unsigned long lwid, mwid;
|
||||||
|
bool lrc;
|
||||||
|
lrc = reg->sb_to_slice(prefix_indices, lsv, moff, mwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||||
|
lrc = reg->sb_to_slice(prefix_indices, lsv+wid-1, loff, lwid);
|
||||||
|
else
|
||||||
|
lrc = reg->sb_to_slice(prefix_indices, lsv-wid+1, loff, lwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
ivl_assert(*this, lwid == mwid);
|
||||||
|
|
||||||
|
if (moff > loff) {
|
||||||
|
rel_base = loff;
|
||||||
|
wid = moff + mwid - loff;
|
||||||
|
} else {
|
||||||
|
rel_base = moff;
|
||||||
|
wid = loff + lwid - moff;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
long offset = 0;
|
||||||
// We want the last range, which is where we work.
|
// We want the last range, which is where we work.
|
||||||
const netrange_t&rng = packed.back();
|
const netrange_t&rng = packed.back();
|
||||||
if (((rng.get_msb() < rng.get_lsb()) &&
|
if (((rng.get_msb() < rng.get_lsb()) &&
|
||||||
|
|
@ -951,8 +974,9 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||||
use_sel == index_component_t::SEL_IDX_DO)) {
|
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||||
offset = -wid + 1;
|
offset = -wid + 1;
|
||||||
}
|
}
|
||||||
|
rel_base = reg->sb_to_idx(prefix_indices,lsv) + offset;
|
||||||
|
}
|
||||||
delete base;
|
delete base;
|
||||||
long rel_base = reg->sb_to_idx(prefix_indices,lsv) + offset;
|
|
||||||
/* If we cover the entire lvalue just skip the select. */
|
/* If we cover the entire lvalue just skip the select. */
|
||||||
if (rel_base == 0 && wid == reg->vector_width()) return true;
|
if (rel_base == 0 && wid == reg->vector_width()) return true;
|
||||||
base = new NetEConst(verinum(rel_base));
|
base = new NetEConst(verinum(rel_base));
|
||||||
|
|
|
||||||
27
elab_net.cc
27
elab_net.cc
|
|
@ -262,8 +262,32 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
}
|
}
|
||||||
|
|
||||||
long midx_val = tmp->value().as_long();
|
long midx_val = tmp->value().as_long();
|
||||||
midx = sig->sb_to_idx(prefix_indices, midx_val);
|
|
||||||
delete tmp_ex;
|
delete tmp_ex;
|
||||||
|
if (prefix_indices.size()+1 < sig->packed_dims().size()) {
|
||||||
|
// Here we are selecting one or more sub-arrays.
|
||||||
|
// Make this work by finding the indexed sub-arrays and
|
||||||
|
// creating a generated slice that spans the whole range.
|
||||||
|
long loff, moff;
|
||||||
|
unsigned long lwid, mwid;
|
||||||
|
bool lrc;
|
||||||
|
lrc = sig->sb_to_slice(prefix_indices, midx_val, moff, mwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||||
|
lrc = sig->sb_to_slice(prefix_indices, midx_val+wid-1, loff, lwid);
|
||||||
|
else
|
||||||
|
lrc = sig->sb_to_slice(prefix_indices, midx_val-wid+1, loff, lwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
ivl_assert(*this, lwid == mwid);
|
||||||
|
|
||||||
|
if (moff > loff) {
|
||||||
|
lidx = loff;
|
||||||
|
midx = moff + mwid - 1;
|
||||||
|
} else {
|
||||||
|
lidx = moff;
|
||||||
|
midx = loff + lwid - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
midx = sig->sb_to_idx(prefix_indices, midx_val);
|
||||||
|
|
||||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||||
lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
|
lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
|
||||||
|
|
@ -306,6 +330,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
if (lidx >= (long)sig->vector_width() || midx < 0) {
|
if (lidx >= (long)sig->vector_width() || midx < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue