From 77f168cf2850a9f8919322fff3d86d65d61501ba Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 12 Feb 2012 14:52:47 -0800 Subject: [PATCH] Support non-constant indexed part select of packed arrays. --- elab_expr.cc | 11 +++++------ elab_lval.cc | 16 +++++----------- netmisc.cc | 16 ++++++++++++++++ netmisc.h | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 79783a58f..63105d7f8 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -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); diff --git a/elab_lval.cc b/elab_lval.cc index 8171d5b0c..6376c05e1 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -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; } } diff --git a/netmisc.cc b/netmisc.cc index 8a08a48ff..504b58dcb 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -343,6 +343,22 @@ NetExpr *normalize_variable_bit_base(const list&indices, NetExpr*base, return normalize_variable_base(base, rng.msb, rng.lsb, 1, true, slice_off); } +NetExpr *normalize_variable_part_base(const list&indices, NetExpr*base, + const NetNet*reg, + unsigned long wid, bool is_up) +{ + const list&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&indices, NetExpr*base, const NetNet*reg, unsigned long&lwid) { diff --git a/netmisc.h b/netmisc.h index 45b9238c2..5e96d3c8d 100644 --- a/netmisc.h +++ b/netmisc.h @@ -105,11 +105,43 @@ extern NetExpr*normalize_variable_base(NetExpr *base, const list&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&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&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&indices, NetExpr *base, const NetNet*reg, unsigned long&lwid); + extern NetExpr*normalize_variable_array_base(NetExpr *base, long offset, unsigned count);