Elaborate dynamic array expressions (lval/rval) down to ivl_target.h
This commit is contained in:
parent
18714e2efd
commit
fdc92ea464
2
PExpr.h
2
PExpr.h
|
|
@ -367,6 +367,8 @@ class PEIdent : public PExpr {
|
||||||
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
|
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
|
||||||
NetAssign_*,
|
NetAssign_*,
|
||||||
const perm_string&) const;
|
const perm_string&) const;
|
||||||
|
bool elaborate_lval_darray_bit_(Design*, NetScope*,
|
||||||
|
NetAssign_*) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetExpr*elaborate_expr_param_(Design*des,
|
NetExpr*elaborate_expr_param_(Design*des,
|
||||||
|
|
|
||||||
33
elab_expr.cc
33
elab_expr.cc
|
|
@ -29,6 +29,7 @@
|
||||||
# include "netenum.h"
|
# include "netenum.h"
|
||||||
# include "discipline.h"
|
# include "discipline.h"
|
||||||
# include "netmisc.h"
|
# include "netmisc.h"
|
||||||
|
# include "netdarray.h"
|
||||||
# include "netstruct.h"
|
# include "netstruct.h"
|
||||||
# include "util.h"
|
# include "util.h"
|
||||||
# include "ivl_assert.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);
|
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) {
|
if (use_width != UINT_MAX) {
|
||||||
expr_type_ = IVL_VT_LOGIC; // Assume bit/parts selects are logic
|
expr_type_ = IVL_VT_LOGIC; // Assume bit/parts selects are logic
|
||||||
expr_width_ = use_width;
|
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_type_ = net->data_type();
|
||||||
expr_width_ = net->vector_width();
|
expr_width_ = net->vector_width();
|
||||||
min_width_ = expr_width_;
|
min_width_ = expr_width_;
|
||||||
signed_flag_ = net->get_signed();
|
signed_flag_ = net->get_signed();
|
||||||
|
|
||||||
return expr_width_;
|
return expr_width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3739,6 +3754,20 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||||
return res;
|
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);
|
long idx = net->sig()->sb_to_idx(prefix_indices,msv);
|
||||||
|
|
||||||
if (idx >= (long)net->vector_width() || idx < 0) {
|
if (idx >= (long)net->vector_width() || idx < 0) {
|
||||||
|
|
|
||||||
32
elab_lval.cc
32
elab_lval.cc
|
|
@ -257,9 +257,15 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
|
|
||||||
|
|
||||||
if (use_sel == index_component_t::SEL_BIT) {
|
if (use_sel == index_component_t::SEL_BIT) {
|
||||||
NetAssign_*lv = new NetAssign_(reg);
|
if (reg->darray_type()) {
|
||||||
elaborate_lval_net_bit_(des, scope, lv);
|
NetAssign_*lv = new NetAssign_(reg);
|
||||||
return lv;
|
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);
|
ivl_assert(*this, use_sel == index_component_t::SEL_NONE);
|
||||||
|
|
@ -458,6 +464,26 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||||
return true;
|
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,
|
bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
NetAssign_*lv) const
|
NetAssign_*lv) const
|
||||||
|
|
|
||||||
|
|
@ -1063,7 +1063,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
// put all the packed dimensions there.
|
// put all the packed dimensions there.
|
||||||
if (use_lidx==0 && use_ridx==0) {
|
if (use_lidx==0 && use_ridx==0) {
|
||||||
ivl_assert(*this, netarray==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();
|
packed_dimensions.clear();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
# include "netdarray.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NetAssign
|
* NetAssign
|
||||||
|
|
@ -84,13 +85,25 @@ ivl_select_type_t NetAssign_::select_type() const
|
||||||
|
|
||||||
unsigned NetAssign_::lwidth() const
|
unsigned NetAssign_::lwidth() const
|
||||||
{
|
{
|
||||||
|
if (netdarray_t*darray = sig_->darray_type()) {
|
||||||
|
if (word_ == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return darray->vector_width();
|
||||||
|
}
|
||||||
|
|
||||||
return lwid_;
|
return lwid_;
|
||||||
}
|
}
|
||||||
|
|
||||||
ivl_variable_type_t NetAssign_::expr_type() const
|
ivl_variable_type_t NetAssign_::expr_type() const
|
||||||
{
|
{
|
||||||
if (sig_->darray_type())
|
if (netdarray_t*darray = sig_->darray_type()) {
|
||||||
return IVL_VT_DARRAY;
|
if (word_ == 0)
|
||||||
|
return IVL_VT_DARRAY;
|
||||||
|
else
|
||||||
|
return darray->data_type();
|
||||||
|
}
|
||||||
|
|
||||||
return sig_->data_type();
|
return sig_->data_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
netdarray_t::netdarray_t(const std::list<netrange_t>&packed,
|
netdarray_t::netdarray_t(const std::list<netrange_t>&packed,
|
||||||
ivl_variable_type_t type)
|
ivl_variable_type_t type, unsigned long wid)
|
||||||
: packed_dims_(packed), type_(type)
|
: packed_dims_(packed), type_(type), width_(wid)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,17 @@ class netdarray_t : public nettype_base_t {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit netdarray_t(const std::list<netrange_t>&packed,
|
explicit netdarray_t(const std::list<netrange_t>&packed,
|
||||||
ivl_variable_type_t type);
|
ivl_variable_type_t type,
|
||||||
|
unsigned long wid);
|
||||||
~netdarray_t();
|
~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:
|
private:
|
||||||
std::list<netrange_t> packed_dims_;
|
std::list<netrange_t> packed_dims_;
|
||||||
ivl_variable_type_t type_;
|
ivl_variable_type_t type_;
|
||||||
|
unsigned long width_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,36 @@
|
||||||
# include "priv.h"
|
# include "priv.h"
|
||||||
# include <assert.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)
|
static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
|
||||||
{
|
{
|
||||||
unsigned wid = 0;
|
|
||||||
|
|
||||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||||
assert(sig);
|
assert(sig);
|
||||||
|
|
||||||
|
|
@ -34,6 +60,10 @@ static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
|
||||||
ivl_signal_width(sig),
|
ivl_signal_width(sig),
|
||||||
ivl_lval_width(lval));
|
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)) {
|
if (ivl_lval_idx(lval)) {
|
||||||
fprintf(out, "%*sAddress-0 select expression:\n", ind+4, "");
|
fprintf(out, "%*sAddress-0 select expression:\n", ind+4, "");
|
||||||
show_expression(ivl_lval_idx(lval), ind+6);
|
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);
|
show_expression(ivl_lval_part_off(lval), ind+8);
|
||||||
}
|
}
|
||||||
|
|
||||||
wid = ivl_lval_width(lval);
|
return ivl_lval_width(lval);
|
||||||
|
|
||||||
return wid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_stmt_cassign(ivl_statement_t net, unsigned ind)
|
static void show_stmt_cassign(ivl_statement_t net, unsigned ind)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue