Elaborate dynamic array expressions (lval/rval) down to ivl_target.h

This commit is contained in:
Stephen Williams 2012-07-21 08:59:29 -07:00
parent 18714e2efd
commit fdc92ea464
8 changed files with 118 additions and 17 deletions

View File

@ -367,6 +367,8 @@ class PEIdent : public PExpr {
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
NetAssign_*,
const perm_string&) const;
bool elaborate_lval_darray_bit_(Design*, NetScope*,
NetAssign_*) const;
private:
NetExpr*elaborate_expr_param_(Design*des,

View File

@ -29,6 +29,7 @@
# include "netenum.h"
# include "discipline.h"
# include "netmisc.h"
# include "netdarray.h"
# include "netstruct.h"
# include "util.h"
# include "ivl_assert.h"
@ -2308,6 +2309,21 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
ivl_assert(*this, 0);
}
if (netdarray_t*darray = net? net->darray_type() : 0) {
if (use_sel == index_component_t::SEL_BIT) {
expr_type_ = darray->data_type();
expr_width_ = darray->vector_width();
min_width_ = expr_width_;
signed_flag_ = net->get_signed();
} else {
expr_type_ = net->data_type();
expr_width_ = net->vector_width();
min_width_ = expr_width_;
signed_flag_ = net->get_signed();
}
return expr_width_;
}
if (use_width != UINT_MAX) {
expr_type_ = IVL_VT_LOGIC; // Assume bit/parts selects are logic
expr_width_ = use_width;
@ -2322,8 +2338,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
expr_type_ = net->data_type();
expr_width_ = net->vector_width();
min_width_ = expr_width_;
signed_flag_ = net->get_signed();
signed_flag_ = net->get_signed();
return expr_width_;
}
@ -3739,6 +3754,20 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
return res;
}
if (netdarray_t*darray = net->sig()->darray_type()) {
// Special case: This is a select of a dynamic
// array. Generate a NetESelect ant attach it to
// the NetESignal. This should be interpreted as
// an array word select downstream.
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Bit select of a dynamic array becomes NetESelect." << endl;
}
NetESelect*res = new NetESelect(net, mux, darray->vector_width());
res->set_line(*net);
return res;
}
long idx = net->sig()->sb_to_idx(prefix_indices,msv);
if (idx >= (long)net->vector_width() || idx < 0) {

View File

@ -257,9 +257,15 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
if (use_sel == index_component_t::SEL_BIT) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_bit_(des, scope, lv);
return lv;
if (reg->darray_type()) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_darray_bit_(des, scope, lv);
return lv;
} else {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_bit_(des, scope, lv);
return lv;
}
}
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
@ -458,6 +464,26 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
return true;
}
bool PEIdent::elaborate_lval_darray_bit_(Design*des, NetScope*scope, NetAssign_*lv)const
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
// For now, only support single-dimension dynamic arrays.
ivl_assert(*this, name_tail.index.size() == 1);
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
// Evaluate the select expression...
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
lv->set_word(mux);
return true;
}
bool PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope,
NetAssign_*lv) const

View File

@ -1063,7 +1063,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// put all the packed dimensions there.
if (use_lidx==0 && use_ridx==0) {
ivl_assert(*this, netarray==0);
netarray = new netdarray_t(packed_dimensions, data_type_);
netarray = new netdarray_t(packed_dimensions, data_type_, wid);
packed_dimensions.clear();
continue;
}

View File

@ -20,6 +20,7 @@
# include "config.h"
# include "netlist.h"
# include "netdarray.h"
/*
* NetAssign
@ -84,13 +85,25 @@ ivl_select_type_t NetAssign_::select_type() const
unsigned NetAssign_::lwidth() const
{
if (netdarray_t*darray = sig_->darray_type()) {
if (word_ == 0)
return 1;
else
return darray->vector_width();
}
return lwid_;
}
ivl_variable_type_t NetAssign_::expr_type() const
{
if (sig_->darray_type())
return IVL_VT_DARRAY;
if (netdarray_t*darray = sig_->darray_type()) {
if (word_ == 0)
return IVL_VT_DARRAY;
else
return darray->data_type();
}
return sig_->data_type();
}

View File

@ -22,8 +22,8 @@
using namespace std;
netdarray_t::netdarray_t(const std::list<netrange_t>&packed,
ivl_variable_type_t type)
: packed_dims_(packed), type_(type)
ivl_variable_type_t type, unsigned long wid)
: packed_dims_(packed), type_(type), width_(wid)
{
}

View File

@ -27,14 +27,17 @@ class netdarray_t : public nettype_base_t {
public:
explicit netdarray_t(const std::list<netrange_t>&packed,
ivl_variable_type_t type);
ivl_variable_type_t type,
unsigned long wid);
~netdarray_t();
ivl_variable_type_t data_type() const { return type_; }
inline ivl_variable_type_t data_type() const { return type_; }
inline unsigned long vector_width(void) const { return width_; }
private:
std::list<netrange_t> packed_dims_;
ivl_variable_type_t type_;
unsigned long width_;
};
#endif

View File

@ -21,10 +21,36 @@
# include "priv.h"
# include <assert.h>
/*
* If the l-value signal is a darray object, then the ivl_lval_mux()
* gets you the array index expression.
*/
static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind)
{
ivl_signal_t sig = ivl_lval_sig(lval);
assert(sig);
if (ivl_lval_idx(lval)) {
fprintf(out, "%*sAddress-0 select of dynamic array:\n", ind+4, "");
show_expression(ivl_lval_idx(lval), ind+6);
}
if (ivl_lval_mux(lval)) {
fprintf(out, "%*sERROR: unexpected ivl_lval_mux() expression:\n", ind+4, "");
stub_errors += 1;
show_expression(ivl_lval_mux(lval), ind+6);
}
if (ivl_lval_part_off(lval)) {
fprintf(out, "%*sERROR: unexpected Part select expression:\n", ind+4, "");
stub_errors += 1;
show_expression(ivl_lval_part_off(lval), ind+8);
}
return ivl_lval_width(lval);
}
static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
{
unsigned wid = 0;
ivl_signal_t sig = ivl_lval_sig(lval);
assert(sig);
@ -34,6 +60,10 @@ static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
ivl_signal_width(sig),
ivl_lval_width(lval));
/* Special case: target signal is a darray. */
if (ivl_signal_data_type(sig) == IVL_VT_DARRAY)
return show_assign_lval_darray(lval, ind);
if (ivl_lval_idx(lval)) {
fprintf(out, "%*sAddress-0 select expression:\n", ind+4, "");
show_expression(ivl_lval_idx(lval), ind+6);
@ -59,9 +89,7 @@ static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
show_expression(ivl_lval_part_off(lval), ind+8);
}
wid = ivl_lval_width(lval);
return wid;
return ivl_lval_width(lval);
}
static void show_stmt_cassign(ivl_statement_t net, unsigned ind)