Support indexed part selects that index sub-arrays (issue #497)
(cherry picked from commit 4af830187e)
This commit is contained in:
parent
cccf36d76f
commit
c0c46dc173
72
elab_expr.cc
72
elab_expr.cc
|
|
@ -5243,20 +5243,37 @@ 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);
|
||||||
|
|
||||||
// We want the last range, which is where we work.
|
if (moff > loff) {
|
||||||
const netrange_t&rng = packed.back();
|
rel_base = loff;
|
||||||
if (rng.get_msb() < rng.get_lsb()) {
|
} else {
|
||||||
offset = -wid + 1;
|
rel_base = moff;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
long offset = 0;
|
||||||
|
// We want the last range, which is where we work.
|
||||||
|
const netrange_t&rng = packed.back();
|
||||||
|
if (rng.get_msb() < rng.get_lsb()) {
|
||||||
|
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
|
||||||
// signal itself.
|
// signal itself.
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
// We want the last range, which is where we work.
|
if (moff > loff) {
|
||||||
const netrange_t&rng = packed.back();
|
rel_base = loff;
|
||||||
if (rng.get_msb() > rng.get_lsb()) {
|
} else {
|
||||||
offset = -wid + 1;
|
rel_base = moff;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
long rel_base = net->sig()->sb_to_idx(prefix_indices, lsv);
|
long offset = 0;
|
||||||
rel_base += offset;
|
// We want the last range, which is where we work.
|
||||||
|
const netrange_t&rng = packed.back();
|
||||||
|
if (rng.get_msb() > rng.get_lsb()) {
|
||||||
|
offset = -wid + 1;
|
||||||
|
}
|
||||||
|
rel_base = net->sig()->sb_to_idx(prefix_indices, lsv) + 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
|
||||||
|
|
|
||||||
44
elab_lval.cc
44
elab_lval.cc
|
|
@ -938,21 +938,45 @@ 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);
|
||||||
|
|
||||||
// We want the last range, which is where we work.
|
if (moff > loff) {
|
||||||
const netrange_t&rng = packed.back();
|
rel_base = loff;
|
||||||
if (((rng.get_msb() < rng.get_lsb()) &&
|
wid = moff + mwid - loff;
|
||||||
use_sel == index_component_t::SEL_IDX_UP) ||
|
} else {
|
||||||
((rng.get_msb() > rng.get_lsb()) &&
|
rel_base = moff;
|
||||||
use_sel == index_component_t::SEL_IDX_DO)) {
|
wid = loff + lwid - moff;
|
||||||
offset = -wid + 1;
|
}
|
||||||
|
} else {
|
||||||
|
long offset = 0;
|
||||||
|
// We want the last range, which is where we work.
|
||||||
|
const netrange_t&rng = packed.back();
|
||||||
|
if (((rng.get_msb() < rng.get_lsb()) &&
|
||||||
|
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||||
|
((rng.get_msb() > rng.get_lsb()) &&
|
||||||
|
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||||
|
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));
|
||||||
|
|
|
||||||
101
elab_net.cc
101
elab_net.cc
|
|
@ -262,49 +262,74 @@ 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 (index_tail.sel == index_component_t::SEL_IDX_UP)
|
if (moff > loff) {
|
||||||
lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
|
lidx = loff;
|
||||||
else
|
midx = moff + mwid - 1;
|
||||||
lidx = sig->sb_to_idx(prefix_indices, midx_val-wid+1);
|
|
||||||
|
|
||||||
if (midx < lidx) {
|
|
||||||
long tmpx = midx;
|
|
||||||
midx = lidx;
|
|
||||||
lidx = tmpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Warn about an indexed part select that is out of range. */
|
|
||||||
if (warn_ob_select && (lidx < 0)) {
|
|
||||||
cerr << get_fileline() << ": warning: " << sig->name();
|
|
||||||
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
|
||||||
cerr << "[" << midx_val;
|
|
||||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
|
||||||
cerr << "+:";
|
|
||||||
} else {
|
} else {
|
||||||
cerr << "-:";
|
lidx = moff;
|
||||||
|
midx = loff + lwid - 1;
|
||||||
}
|
}
|
||||||
cerr << wid << "] is selecting before vector." << endl;
|
} else {
|
||||||
}
|
midx = sig->sb_to_idx(prefix_indices, midx_val);
|
||||||
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
|
|
||||||
cerr << get_fileline() << ": warning: " << sig->name();
|
|
||||||
if (sig->unpacked_dimensions() > 0) {
|
|
||||||
cerr << "[]";
|
|
||||||
}
|
|
||||||
cerr << "[" << midx_val;
|
|
||||||
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
|
||||||
cerr << "+:";
|
|
||||||
} else {
|
|
||||||
cerr << "-:";
|
|
||||||
}
|
|
||||||
cerr << wid << "] is selecting after vector." << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is completely out side the signal so just skip it. */
|
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||||
if (lidx >= (long)sig->vector_width() || midx < 0) {
|
lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
|
||||||
return false;
|
else
|
||||||
|
lidx = sig->sb_to_idx(prefix_indices, midx_val-wid+1);
|
||||||
|
|
||||||
|
if (midx < lidx) {
|
||||||
|
long tmpx = midx;
|
||||||
|
midx = lidx;
|
||||||
|
lidx = tmpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Warn about an indexed part select that is out of range. */
|
||||||
|
if (warn_ob_select && (lidx < 0)) {
|
||||||
|
cerr << get_fileline() << ": warning: " << sig->name();
|
||||||
|
if (sig->unpacked_dimensions() > 0) cerr << "[]";
|
||||||
|
cerr << "[" << midx_val;
|
||||||
|
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||||
|
cerr << "+:";
|
||||||
|
} else {
|
||||||
|
cerr << "-:";
|
||||||
|
}
|
||||||
|
cerr << wid << "] is selecting before vector." << endl;
|
||||||
|
}
|
||||||
|
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
|
||||||
|
cerr << get_fileline() << ": warning: " << sig->name();
|
||||||
|
if (sig->unpacked_dimensions() > 0) {
|
||||||
|
cerr << "[]";
|
||||||
|
}
|
||||||
|
cerr << "[" << midx_val;
|
||||||
|
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||||
|
cerr << "+:";
|
||||||
|
} else {
|
||||||
|
cerr << "-:";
|
||||||
|
}
|
||||||
|
cerr << wid << "] is selecting after vector." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is completely out side the signal so just skip it. */
|
||||||
|
if (lidx >= (long)sig->vector_width() || midx < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue