Get arrayed property expressions down to the ivl_target API.
This commit is contained in:
parent
acce9fc2a0
commit
ea4b000be6
|
|
@ -1734,6 +1734,8 @@ void NetENull::dump(ostream&o) const
|
||||||
void NetEProperty::dump(ostream&o) const
|
void NetEProperty::dump(ostream&o) const
|
||||||
{
|
{
|
||||||
o << net_->name() << ".<" << pidx_ << ">";
|
o << net_->name() << ".<" << pidx_ << ">";
|
||||||
|
if (index_)
|
||||||
|
o << "[" << *index_ << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetEScope::dump(ostream&o) const
|
void NetEScope::dump(ostream&o) const
|
||||||
|
|
|
||||||
40
elab_expr.cc
40
elab_expr.cc
|
|
@ -3298,7 +3298,9 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
|
||||||
if (class_type == 0)
|
if (class_type == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
perm_string member_name = peek_tail_name(path_);
|
const name_component_t&name_comp = path_.back();
|
||||||
|
|
||||||
|
perm_string member_name = name_comp.name;
|
||||||
int pidx = class_type->property_idx_from_name(member_name);
|
int pidx = class_type->property_idx_from_name(member_name);
|
||||||
if (pidx < 0)
|
if (pidx < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -3336,14 +3338,40 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
|
||||||
return class_static_property_expression(this, class_type, member_name);
|
return class_static_property_expression(this, class_type, member_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetExpr*canon_index = 0;
|
||||||
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
|
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
|
||||||
if (/* const netuarray_t*tmp_ua =*/ dynamic_cast<const netuarray_t*>(tmp_type)) {
|
if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
|
||||||
cerr << get_fileline() << ": sorry: "
|
|
||||||
<< "Unpacked array properties not supported yet." << endl;
|
const std::vector<netrange_t>&dims = tmp_ua->static_dimensions();
|
||||||
des->errors += 1;
|
|
||||||
|
if (debug_elaborate) {
|
||||||
|
cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member_: "
|
||||||
|
<< "Property " << class_type->get_prop_name(pidx)
|
||||||
|
<< " has " << dims.size() << " dimensions, "
|
||||||
|
<< " got " << name_comp.index.size() << " indices." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dims.size() != name_comp.index.size()) {
|
||||||
|
cerr << get_fileline() << ": error: "
|
||||||
|
<< "Got " << name_comp.index.size() << " indices, "
|
||||||
|
<< "expecting " << dims.size()
|
||||||
|
<< " to index the property " << class_type->get_prop_name(pidx) << "." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
canon_index = make_canonical_index(des, scope, this,
|
||||||
|
name_comp.index, tmp_ua, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEProperty*tmp = new NetEProperty(this_net, member_name);
|
if (debug_elaborate && canon_index) {
|
||||||
|
cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member_: "
|
||||||
|
<< "Property " << class_type->get_prop_name(pidx)
|
||||||
|
<< " canonical index: " << *canon_index << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetEProperty*tmp = new NetEProperty(this_net, member_name, canon_index);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
47
elab_lval.cc
47
elab_lval.cc
|
|
@ -425,27 +425,8 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||||
ivl_type_t property_type = class_type->get_prop_type(pidx);
|
ivl_type_t property_type = class_type->get_prop_type(pidx);
|
||||||
|
|
||||||
if (const netsarray_t* stype = dynamic_cast<const netsarray_t*> (property_type)) {
|
if (const netsarray_t* stype = dynamic_cast<const netsarray_t*> (property_type)) {
|
||||||
list<long> indices_const;
|
canon_index = make_canonical_index(des, scope, this,
|
||||||
list<NetExpr*> indices_expr;
|
name_comp.index, stype, false);
|
||||||
indices_flags flags;
|
|
||||||
indices_to_expressions(des, scope, this,
|
|
||||||
name_comp.index, name_comp.index.size(),
|
|
||||||
false, flags,
|
|
||||||
indices_expr, indices_const);
|
|
||||||
|
|
||||||
if (flags.undefined) {
|
|
||||||
cerr << get_fileline() << ": warning: "
|
|
||||||
<< "ignoring undefined l-value array access "
|
|
||||||
<< member_name
|
|
||||||
<< " (" << path_ << ")"
|
|
||||||
<< "." << endl;
|
|
||||||
} else if (flags.variable) {
|
|
||||||
canon_index = normalize_variable_unpacked(*this, stype, indices_expr);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
canon_index = normalize_variable_unpacked(stype, indices_const);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
|
|
@ -490,9 +471,27 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||||
|
|
||||||
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
|
ivl_type_t tmp_type = class_type->get_prop_type(pidx);
|
||||||
if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
|
if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
|
||||||
cerr << get_fileline() << ": sorry: "
|
|
||||||
<< "Unpacked array properties (l-values) not supported yet." << endl;
|
const std::vector<netrange_t>&dims = tmp_ua->static_dimensions();
|
||||||
des->errors += 1;
|
|
||||||
|
if (debug_elaborate) {
|
||||||
|
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||||
|
<< "Property " << class_type->get_prop_name(pidx)
|
||||||
|
<< " has " << dims.size() << " dimensions, "
|
||||||
|
<< " got " << name_comp.index.size() << " indices." << endl;
|
||||||
|
if (canon_index) {
|
||||||
|
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||||
|
<< "Canonical index is:" << *canon_index << endl;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dims.size() != name_comp.index.size()) {
|
||||||
|
cerr << get_fileline() << ": error: "
|
||||||
|
<< "Got " << name_comp.index.size() << " indices, "
|
||||||
|
<< "expecting " << dims.size()
|
||||||
|
<< " to index the property " << class_type->get_prop_name(pidx) << "." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetAssign_*this_lval = new NetAssign_(this_net);
|
NetAssign_*this_lval = new NetAssign_(this_net);
|
||||||
|
|
|
||||||
|
|
@ -832,6 +832,10 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
|
||||||
* table. That number can be passed to ivl_type_prop_*() functions to
|
* table. That number can be passed to ivl_type_prop_*() functions to
|
||||||
* get details about the property.
|
* get details about the property.
|
||||||
*
|
*
|
||||||
|
* If the property is an array, then the ivl_expr_oper1() function
|
||||||
|
* returns the canonical expression for accessing the element of the
|
||||||
|
* property.
|
||||||
|
*
|
||||||
* - IVL_EX_NEW
|
* - IVL_EX_NEW
|
||||||
* This expression takes one or two operands. The first operand,
|
* This expression takes one or two operands. The first operand,
|
||||||
* returned by ivl_expr_oper1() is the number of elements to create
|
* returned by ivl_expr_oper1() is the number of elements to create
|
||||||
|
|
@ -1499,6 +1503,11 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||||
* then the ivl_lval_idx expression must *not* be present.
|
* then the ivl_lval_idx expression must *not* be present.
|
||||||
*
|
*
|
||||||
* For array words, the ivl_lval_width is the width of the word.
|
* For array words, the ivl_lval_width is the width of the word.
|
||||||
|
*
|
||||||
|
* - Arrayed properties
|
||||||
|
* If the l-value is a class property, then the ivl_lval_idx function
|
||||||
|
* will return an expression if the property is in fact arrayed. The
|
||||||
|
* expression is the canonical index for elements in the property.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||||
|
|
|
||||||
|
|
@ -376,8 +376,8 @@ NetENull::~NetENull()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEProperty::NetEProperty(NetNet*net, perm_string pnam)
|
NetEProperty::NetEProperty(NetNet*net, perm_string pnam, NetExpr*idx)
|
||||||
: net_(net)
|
: net_(net), index_(idx)
|
||||||
{
|
{
|
||||||
const netclass_t*use_type = dynamic_cast<const netclass_t*>(net->net_type());
|
const netclass_t*use_type = dynamic_cast<const netclass_t*>(net->net_type());
|
||||||
assert(use_type);
|
assert(use_type);
|
||||||
|
|
|
||||||
|
|
@ -4293,14 +4293,18 @@ class NetENull : public NetExpr {
|
||||||
* The NetEProperty represents a SystemVerilog property select of a
|
* The NetEProperty represents a SystemVerilog property select of a
|
||||||
* class object. In SV, the expression would look like "a.b", where
|
* class object. In SV, the expression would look like "a.b", where
|
||||||
* the "a" is the signal (the NetNet) and "b" is the property name.
|
* the "a" is the signal (the NetNet) and "b" is the property name.
|
||||||
|
*
|
||||||
|
* The canon_index is an optional expression to address an element for
|
||||||
|
* parameters that are arrays.
|
||||||
*/
|
*/
|
||||||
class NetEProperty : public NetExpr {
|
class NetEProperty : public NetExpr {
|
||||||
public:
|
public:
|
||||||
NetEProperty(NetNet*n, perm_string pname);
|
NetEProperty(NetNet*n, perm_string pname, NetExpr*canon_index =0);
|
||||||
~NetEProperty();
|
~NetEProperty();
|
||||||
|
|
||||||
inline const NetNet* get_sig() const { return net_; }
|
inline const NetNet* get_sig() const { return net_; }
|
||||||
inline size_t property_idx() const { return pidx_; }
|
inline size_t property_idx() const { return pidx_; }
|
||||||
|
inline const NetExpr*get_index() const { return index_; }
|
||||||
|
|
||||||
public: // Overridden methods
|
public: // Overridden methods
|
||||||
ivl_variable_type_t expr_type() const;
|
ivl_variable_type_t expr_type() const;
|
||||||
|
|
@ -4313,6 +4317,7 @@ class NetEProperty : public NetExpr {
|
||||||
private:
|
private:
|
||||||
NetNet*net_;
|
NetNet*net_;
|
||||||
size_t pidx_;
|
size_t pidx_;
|
||||||
|
NetExpr*index_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
30
netmisc.cc
30
netmisc.cc
|
|
@ -667,6 +667,36 @@ NetExpr* normalize_variable_unpacked(const LineInfo&loc, const netsarray_t*stype
|
||||||
return normalize_variable_unpacked(loc, dims, indices);
|
return normalize_variable_unpacked(loc, dims, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetExpr* make_canonical_index(Design*des, NetScope*scope,
|
||||||
|
const LineInfo*loc,
|
||||||
|
const std::list<index_component_t>&src,
|
||||||
|
const netsarray_t*stype,
|
||||||
|
bool need_const)
|
||||||
|
{
|
||||||
|
NetExpr*canon_index = 0;
|
||||||
|
|
||||||
|
list<long> indices_const;
|
||||||
|
list<NetExpr*> indices_expr;
|
||||||
|
indices_flags flags;
|
||||||
|
indices_to_expressions(des, scope, loc,
|
||||||
|
src, src.size(),
|
||||||
|
need_const, flags,
|
||||||
|
indices_expr, indices_const);
|
||||||
|
|
||||||
|
if (flags.undefined) {
|
||||||
|
cerr << loc->get_fileline() << ": warning: "
|
||||||
|
<< "ignoring undefined value array access." << endl;
|
||||||
|
|
||||||
|
} else if (flags.variable) {
|
||||||
|
canon_index = normalize_variable_unpacked(*loc, stype, indices_expr);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
canon_index = normalize_variable_unpacked(stype, indices_const);
|
||||||
|
}
|
||||||
|
|
||||||
|
return canon_index;
|
||||||
|
}
|
||||||
|
|
||||||
NetEConst* make_const_x(unsigned long wid)
|
NetEConst* make_const_x(unsigned long wid)
|
||||||
{
|
{
|
||||||
verinum xxx (verinum::Vx, wid);
|
verinum xxx (verinum::Vx, wid);
|
||||||
|
|
|
||||||
10
netmisc.h
10
netmisc.h
|
|
@ -191,6 +191,16 @@ extern NetExpr*normalize_variable_unpacked(const netsarray_t*net, list<long>&ind
|
||||||
extern NetExpr*normalize_variable_unpacked(const NetNet*net, list<NetExpr*>&indices);
|
extern NetExpr*normalize_variable_unpacked(const NetNet*net, list<NetExpr*>&indices);
|
||||||
extern NetExpr*normalize_variable_unpacked(const LineInfo&loc, const netsarray_t*net, list<NetExpr*>&indices);
|
extern NetExpr*normalize_variable_unpacked(const LineInfo&loc, const netsarray_t*net, list<NetExpr*>&indices);
|
||||||
|
|
||||||
|
extern NetExpr*make_canonical_index(Design*des, NetScope*scope,
|
||||||
|
// loc for error messages
|
||||||
|
const LineInfo*loc,
|
||||||
|
// src is the index list
|
||||||
|
const std::list<index_component_t>&src,
|
||||||
|
// This is the reference type
|
||||||
|
const netsarray_t*stype,
|
||||||
|
// True if the expression MUST be constant.
|
||||||
|
bool need_const);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function takes as input a NetNet signal and adds a constant
|
* This function takes as input a NetNet signal and adds a constant
|
||||||
* value to it. If the val is 0, then simply return sig. Otherwise,
|
* value to it. If the val is 0, then simply return sig. Otherwise,
|
||||||
|
|
|
||||||
|
|
@ -485,6 +485,9 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net)
|
||||||
case IVL_EX_BINARY:
|
case IVL_EX_BINARY:
|
||||||
return net->u_.binary_.lef_;
|
return net->u_.binary_.lef_;
|
||||||
|
|
||||||
|
case IVL_EX_PROPERTY:
|
||||||
|
return net->u_.property_.index;
|
||||||
|
|
||||||
case IVL_EX_SELECT:
|
case IVL_EX_SELECT:
|
||||||
return net->u_.select_.expr_;
|
return net->u_.select_.expr_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -420,6 +420,12 @@ void dll_target::expr_null(const NetENull*net)
|
||||||
|
|
||||||
void dll_target::expr_property(const NetEProperty*net)
|
void dll_target::expr_property(const NetEProperty*net)
|
||||||
{
|
{
|
||||||
|
ivl_expr_t index = 0;
|
||||||
|
if (const NetExpr*index_expr = net->get_index()) {
|
||||||
|
index_expr->expr_scan(this);
|
||||||
|
index = expr_;
|
||||||
|
expr_ = 0;
|
||||||
|
}
|
||||||
assert(expr_ == 0);
|
assert(expr_ == 0);
|
||||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||||
expr_->width_ = net->expr_width();
|
expr_->width_ = net->expr_width();
|
||||||
|
|
@ -431,6 +437,7 @@ void dll_target::expr_property(const NetEProperty*net)
|
||||||
expr_->net_type= net->net_type();
|
expr_->net_type= net->net_type();
|
||||||
expr_->u_.property_.sig = find_signal(des_, net->get_sig());
|
expr_->u_.property_.sig = find_signal(des_, net->get_sig());
|
||||||
expr_->u_.property_.prop_idx = net->property_idx();
|
expr_->u_.property_.prop_idx = net->property_idx();
|
||||||
|
expr_->u_.property_.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dll_target::expr_event(const NetEEvent*net)
|
void dll_target::expr_event(const NetEEvent*net)
|
||||||
|
|
|
||||||
1
t-dll.h
1
t-dll.h
|
|
@ -346,6 +346,7 @@ struct ivl_expr_s {
|
||||||
struct {
|
struct {
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
unsigned prop_idx;
|
unsigned prop_idx;
|
||||||
|
ivl_expr_t index;
|
||||||
} property_;
|
} property_;
|
||||||
} u_;
|
} u_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,7 @@ static void show_property_expression(ivl_expr_t net, unsigned ind)
|
||||||
ivl_signal_t sig = ivl_expr_signal(net);
|
ivl_signal_t sig = ivl_expr_signal(net);
|
||||||
const char* pnam = ivl_expr_name(net);
|
const char* pnam = ivl_expr_name(net);
|
||||||
const char*signed_flag = ivl_expr_signed(net)? "signed" : "unsigned";
|
const char*signed_flag = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||||
|
ivl_expr_t index;
|
||||||
|
|
||||||
if (ivl_expr_value(net) == IVL_VT_REAL) {
|
if (ivl_expr_value(net) == IVL_VT_REAL) {
|
||||||
fprintf(out, "%*s<property base=%s, prop=%s, real>\n", ind, "",
|
fprintf(out, "%*s<property base=%s, prop=%s, real>\n", ind, "",
|
||||||
|
|
@ -243,6 +244,9 @@ static void show_property_expression(ivl_expr_t net, unsigned ind)
|
||||||
fprintf(out, "%*s<property base=%s, prop=%s, width=%u, %s>\n", ind, "",
|
fprintf(out, "%*s<property base=%s, prop=%s, width=%u, %s>\n", ind, "",
|
||||||
ivl_signal_basename(sig), pnam, ivl_expr_width(net), signed_flag);
|
ivl_signal_basename(sig), pnam, ivl_expr_width(net), signed_flag);
|
||||||
}
|
}
|
||||||
|
if ( (index=ivl_expr_oper1(net)) ) {
|
||||||
|
show_expression(index, ind+3);
|
||||||
|
}
|
||||||
if (ivl_signal_data_type(sig) != IVL_VT_CLASS) {
|
if (ivl_signal_data_type(sig) != IVL_VT_CLASS) {
|
||||||
fprintf(out, "%*sERROR: Property signal must be IVL_VT_CLASS, got %s.\n",
|
fprintf(out, "%*sERROR: Property signal must be IVL_VT_CLASS, got %s.\n",
|
||||||
ind+3, "", data_type_string(ivl_signal_data_type(sig)));
|
ind+3, "", data_type_string(ivl_signal_data_type(sig)));
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,12 @@ static unsigned show_assign_lval_class(ivl_lval_t lval, unsigned ind)
|
||||||
fprintf(out, "%*s{name=%s.<property-%d> l-value width=%u}\n",
|
fprintf(out, "%*s{name=%s.<property-%d> l-value width=%u}\n",
|
||||||
ind, "", ivl_signal_name(sig), sig_prop, ivl_lval_width(lval));
|
ind, "", ivl_signal_name(sig), sig_prop, ivl_lval_width(lval));
|
||||||
|
|
||||||
|
if (ivl_lval_idx(lval)) {
|
||||||
|
ivl_expr_t mux = ivl_lval_idx(lval);
|
||||||
|
fprintf(out, "%*sAddress-0 select expression:\n", ind+4, "");
|
||||||
|
show_expression(mux, ind+6);
|
||||||
|
}
|
||||||
|
|
||||||
return ivl_lval_width(lval);
|
return ivl_lval_width(lval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue