Handle l-value part select of packed arrays.
This commit is contained in:
parent
3e4f8b625f
commit
4287fc4b50
71
elab_lval.cc
71
elab_lval.cc
|
|
@ -456,42 +456,47 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
|||
ivl_assert(*this, reg);
|
||||
|
||||
const list<NetNet::range_t>&packed = reg->packed_dims();
|
||||
ivl_assert(*this, packed.size() == 1);
|
||||
const NetNet::range_t&rng = packed.back();
|
||||
|
||||
if (msb == rng.msb && lsb == rng.lsb) {
|
||||
|
||||
/* Part select covers the entire vector. Simplest case. */
|
||||
|
||||
} else {
|
||||
|
||||
/* Get the canonical offsets into the vector. */
|
||||
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||
long moff = reg->sb_to_idx(prefix_indices,msb);
|
||||
long wid = moff - loff + 1;
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_fileline() << ": error: part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extremes of the
|
||||
variable, then report an error. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if (loff < 0 || moff >= (signed)reg->vector_width()) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
// Part selects cannot select slices. So there must be enough
|
||||
// prefix_indices to get all the way to the final dimension.
|
||||
if (prefix_indices.size()+1 < packed.size()) {
|
||||
cerr << get_fileline() << ": error: Cannot select a range "
|
||||
<< "of slices from a packed array." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||
long moff = reg->sb_to_idx(prefix_indices,msb);
|
||||
long wid = moff - loff + 1;
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_fileline() << ": error: part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Special case: The range winds up selecting the entire
|
||||
// vector. Treat this as no part select at all.
|
||||
if (loff == 0 && moff == (reg->vector_width()-1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extremes of the
|
||||
variable, then report an error. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if (loff < 0 || moff >= (signed)reg->vector_width()) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
37
netlist.cc
37
netlist.cc
|
|
@ -794,12 +794,39 @@ bool NetNet::sb_is_valid(const list<long>&indices, long sb) const
|
|||
long NetNet::sb_to_idx(const list<long>&indices, long sb) const
|
||||
{
|
||||
ivl_assert(*this, indices.size()+1 == packed_dims_.size());
|
||||
assert(packed_dims_.size() == 1);
|
||||
const range_t&rng = packed_dims_.back();
|
||||
if (rng.msb >= rng.lsb)
|
||||
return sb - rng.lsb;
|
||||
|
||||
list<range_t>::const_iterator pcur = packed_dims_.end();
|
||||
-- pcur;
|
||||
|
||||
long acc_off;
|
||||
long acc_wid = pcur->width();
|
||||
if (pcur->msb >= pcur->lsb)
|
||||
acc_off = sb - pcur->lsb;
|
||||
else
|
||||
return rng.lsb - sb;
|
||||
acc_off = pcur->lsb - sb;
|
||||
|
||||
// The acc_off is the possition within the innermost
|
||||
// dimension. If this is a multi-dimension packed array then
|
||||
// we need to add in the canonical address of the current slice.
|
||||
if (indices.size() >= 1) {
|
||||
list<long>::const_iterator icur = indices.end();
|
||||
do {
|
||||
-- icur;
|
||||
-- pcur;
|
||||
|
||||
long tmp_off;
|
||||
if (pcur->msb >= pcur->lsb)
|
||||
tmp_off = *icur - pcur->lsb;
|
||||
else
|
||||
tmp_off = pcur->lsb - *icur;
|
||||
|
||||
acc_off += tmp_off * acc_wid;
|
||||
acc_wid *= pcur->width();
|
||||
|
||||
} while (icur != indices.begin());
|
||||
}
|
||||
|
||||
return acc_off;
|
||||
}
|
||||
|
||||
bool NetNet::sb_to_slice(const list<long>&indices, long sb, long&loff, unsigned long&lwid) const
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ class NetNet : public NetObj {
|
|||
reg/wire/whatever. Note that a canonical index of a
|
||||
multi-dimensioned packed array is a single dimension. For
|
||||
example, "reg [4:1][3:0]..." has the canonical dimension
|
||||
[15:0] and the sb_to_idx) method will convert [2][2] to
|
||||
[15:0] and the sb_to_idx() method will convert [2][2] to
|
||||
the canonical index [6]. */
|
||||
long sb_to_idx(const std::list<long>&prefix, long sb) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1288,11 +1288,14 @@ static void show_signal(ivl_signal_t net)
|
|||
for (idx = 0 ; idx < ivl_signal_array_count(net) ; idx += 1) {
|
||||
|
||||
ivl_nexus_t nex = ivl_signal_nex(net, idx);
|
||||
unsigned dim;
|
||||
|
||||
fprintf(out, " %s %s %s%s[%d:%d] %s[word=%u, adr=%d] "
|
||||
"<width=%u%s> <discipline=%s> ",
|
||||
type, sign, port, data_type,
|
||||
ivl_signal_msb(net), ivl_signal_lsb(net),
|
||||
fprintf(out, " %s %s %s%s", type, sign, port, data_type);
|
||||
for (dim = 0 ; dim < ivl_signal_packed_dimensions(net) ; dim += 1) {
|
||||
fprintf(out, "[%d:%d]", ivl_signal_packed_msb(net,dim),
|
||||
ivl_signal_packed_lsb(net,dim));
|
||||
}
|
||||
fprintf(out, " %s[word=%u, adr=%d] <width=%u%s> <discipline=%s> ",
|
||||
ivl_signal_basename(net),
|
||||
idx, ivl_signal_array_base(net)+idx,
|
||||
ivl_signal_width(net),
|
||||
|
|
|
|||
|
|
@ -425,8 +425,17 @@ const char*draw_input_from_net(ivl_nexus_t nex)
|
|||
*/
|
||||
static void draw_reg_in_scope(ivl_signal_t sig)
|
||||
{
|
||||
int msb = ivl_signal_msb(sig);
|
||||
int lsb = ivl_signal_lsb(sig);
|
||||
int msb;
|
||||
int lsb;
|
||||
if (ivl_signal_packed_dimensions(sig) > 1) {
|
||||
// FIX ME: Improve this when vvp becomes aware of packed
|
||||
// arrays.
|
||||
msb = ivl_signal_width(sig) - 1;
|
||||
lsb = 0;
|
||||
} else {
|
||||
msb = ivl_signal_msb(sig);
|
||||
lsb = ivl_signal_lsb(sig);
|
||||
}
|
||||
|
||||
const char*datatype_flag = ivl_signal_integer(sig) ? "/i" :
|
||||
ivl_signal_signed(sig)? "/s" : "";
|
||||
|
|
|
|||
Loading…
Reference in New Issue