Some support for unpacked arrays in class properties.
This commit is contained in:
parent
1465fd1570
commit
3b0dfaadba
52
elab_lval.cc
52
elab_lval.cc
|
|
@ -27,6 +27,7 @@
|
|||
# include "netstruct.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netvector.h"
|
||||
# include "compiler.h"
|
||||
# include <cstdlib>
|
||||
|
|
@ -259,6 +260,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
}
|
||||
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
|
||||
<< "Lval reg = " << reg->name() << endl;
|
||||
}
|
||||
|
||||
// We are processing the tail of a string of names. For
|
||||
// example, the verilog may be "a.b.c", so we are processing
|
||||
// "c" at this point. (Note that if method_name is not nil,
|
||||
|
|
@ -389,7 +396,9 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
|||
if (class_type == 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);
|
||||
if (pidx < 0)
|
||||
return 0;
|
||||
|
|
@ -402,6 +411,46 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Ident " << member_name
|
||||
<< " is a property of class " << class_type->get_name() << endl;
|
||||
}
|
||||
|
||||
NetExpr*canon_index = 0;
|
||||
if (name_comp.index.size() > 0) {
|
||||
ivl_type_t property_type = class_type->get_prop_type(pidx);
|
||||
|
||||
if (const netsarray_t* stype = dynamic_cast<const netsarray_t*> (property_type)) {
|
||||
list<long> indices_const;
|
||||
list<NetExpr*> indices_expr;
|
||||
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 {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Index expressions don't apply to this type of property." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect assignment to constant properties. Note that the
|
||||
// initializer constructor MAY assign to constant properties,
|
||||
// as this is how the property gets its value.
|
||||
|
|
@ -438,6 +487,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
|||
|
||||
NetAssign_*this_lval = new NetAssign_(this_net);
|
||||
this_lval->set_property(member_name);
|
||||
if (canon_index) this_lval->set_word(canon_index);
|
||||
|
||||
return this_lval;
|
||||
}
|
||||
|
|
|
|||
44
elab_sig.cc
44
elab_sig.cc
|
|
@ -836,48 +836,6 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
|||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
static bool evaluate_ranges(Design*des, NetScope*scope,
|
||||
vector<netrange_t>&llist,
|
||||
const list<pform_range_t>&rlist)
|
||||
{
|
||||
bool bad_msb = false, bad_lsb = false;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = rlist.begin()
|
||||
; cur != rlist.end() ; ++cur) {
|
||||
long use_msb, use_lsb;
|
||||
|
||||
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
|
||||
if (! eval_as_long(use_msb, texpr)) {
|
||||
cerr << cur->first->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << cur->first->get_fileline() << " : "
|
||||
"This MSB expression violates the rule: "
|
||||
<< *cur->first << endl;
|
||||
des->errors += 1;
|
||||
bad_msb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, cur->second, -1, true);
|
||||
if (! eval_as_long(use_lsb, texpr)) {
|
||||
cerr << cur->second->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << cur->second->get_fileline() << " : "
|
||||
"This LSB expression violates the rule: "
|
||||
<< *cur->second << endl;
|
||||
des->errors += 1;
|
||||
bad_lsb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
llist.push_back(netrange_t(use_msb, use_lsb));
|
||||
}
|
||||
|
||||
return bad_msb | bad_lsb;
|
||||
}
|
||||
|
||||
static netclass_t* locate_class_type(Design*, NetScope*scope,
|
||||
class_type_t*class_type)
|
||||
{
|
||||
|
|
@ -1288,7 +1246,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal " << wtype
|
||||
<< " parray=" << use_type->packed_dimensions()
|
||||
<< " parray=" << use_type->static_dimensions()
|
||||
<< " " << name_ << unpacked_dimensions
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
|
|
|||
19
elab_type.cc
19
elab_type.cc
|
|
@ -22,6 +22,7 @@
|
|||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netenum.h"
|
||||
# include "netparray.h"
|
||||
# include "netscalar.h"
|
||||
# include "netstruct.h"
|
||||
# include "netvector.h"
|
||||
|
|
@ -203,9 +204,21 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
|||
|
||||
ivl_type_t btype = base_type->elaborate_type(des, scope);
|
||||
|
||||
assert(dims->size() == 1);
|
||||
assert(dims->size() >= 1);
|
||||
list<pform_range_t>::const_iterator cur = dims->begin();
|
||||
assert(cur->first == 0 && cur->second==0);
|
||||
ivl_type_s*res = new netdarray_t(btype);
|
||||
|
||||
// Special case: if the dimension is nil:nil, this is a
|
||||
// dynamic array. Note that we only know how to handle dynamic
|
||||
// arrays with 1 dimension at a time.
|
||||
if (cur->first==0 && cur->second==0) {
|
||||
assert(dims->size()==1);
|
||||
ivl_type_s*res = new netdarray_t(btype);
|
||||
return res;
|
||||
}
|
||||
|
||||
vector<netrange_t> dimensions;
|
||||
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
|
||||
|
||||
ivl_type_s*res = new netuarray_t(dimensions, btype);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
35
elaborate.cc
35
elaborate.cc
|
|
@ -40,6 +40,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netvector.h"
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
# include "netclass.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
|
@ -2290,6 +2291,14 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
|||
NetAssign_*lv = new NetAssign_(tmp);
|
||||
return lv;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PAssign_::elaborate_lval: "
|
||||
<< "lval_ = " << *lval_ << endl;
|
||||
cerr << get_fileline() << ": PAssign_::elaborate_lval: "
|
||||
<< "lval_ expr type = " << typeid(*lval_).name() << endl;
|
||||
}
|
||||
|
||||
return lval_->elaborate_lval(des, scope, false, false);
|
||||
}
|
||||
|
||||
|
|
@ -2520,6 +2529,22 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
rv = elaborate_rval_(des, scope, use_lv_type);
|
||||
|
||||
} else if (const netuarray_t*utype = dynamic_cast<const netuarray_t*>(lv_net_type)) {
|
||||
ivl_assert(*this, lv->more==0);
|
||||
if (debug_elaborate) {
|
||||
if (lv->word())
|
||||
cerr << get_fileline() << ": PAssign::elaborate: "
|
||||
<< "lv->word() = " << *lv->word() << endl;
|
||||
else
|
||||
cerr << get_fileline() << ": PAssign::elaborate: "
|
||||
<< "lv->word() = <nil>" << endl;
|
||||
}
|
||||
ivl_type_t use_lv_type = lv_net_type;
|
||||
ivl_assert(*this, lv->word());
|
||||
use_lv_type = utype->element_type();
|
||||
|
||||
rv = elaborate_rval_(des, scope, use_lv_type);
|
||||
|
||||
} else {
|
||||
/* Elaborate the r-value expression, then try to evaluate it. */
|
||||
rv = elaborate_rval_(des, scope, lv_net_type, lv->expr_type(), count_lval_width(lv));
|
||||
|
|
@ -4595,6 +4620,16 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
|
|||
pform_name_t array_name;
|
||||
array_name.push_back(name_component_t(array_var_));
|
||||
NetNet*array_sig = des->find_signal(scope, array_name);
|
||||
|
||||
if (array_sig == 0) {
|
||||
cerr << get_fileline() << ": error:"
|
||||
<< " Unable to find " << array_name
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_assert(*this, array_sig);
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ void NetForLoop::wrap_up()
|
|||
NetBlock*internal_block = new NetBlock(NetBlock::SEQU, 0);
|
||||
internal_block->set_line(*this);
|
||||
|
||||
internal_block->append(statement_);
|
||||
if (statement_) internal_block->append(statement_);
|
||||
internal_block->append(step_statement_);
|
||||
|
||||
NetWhile*wloop = new NetWhile(condition_, internal_block);
|
||||
|
|
|
|||
75
netmisc.cc
75
netmisc.cc
|
|
@ -22,6 +22,7 @@
|
|||
# include <cstdlib>
|
||||
# include <climits>
|
||||
# include "netlist.h"
|
||||
# include "netparray.h"
|
||||
# include "netvector.h"
|
||||
# include "netmisc.h"
|
||||
# include "PExpr.h"
|
||||
|
|
@ -526,10 +527,8 @@ static void make_strides(const vector<netrange_t>&dims,
|
|||
* word. If any of the indices are out of bounds, return nil instead
|
||||
* of an expression.
|
||||
*/
|
||||
NetExpr* normalize_variable_unpacked(const NetNet*net, list<long>&indices)
|
||||
static NetExpr* normalize_variable_unpacked(const vector<netrange_t>&dims, list<long>&indices)
|
||||
{
|
||||
const vector<netrange_t>&dims = net->unpacked_dims();
|
||||
|
||||
// Make strides for each index. The stride is the distance (in
|
||||
// words) to the next element in the canonical array.
|
||||
vector<long> stride (dims.size());
|
||||
|
|
@ -559,10 +558,20 @@ NetExpr* normalize_variable_unpacked(const NetNet*net, list<long>&indices)
|
|||
return canonical_expr;
|
||||
}
|
||||
|
||||
NetExpr* normalize_variable_unpacked(const NetNet*net, list<NetExpr*>&indices)
|
||||
NetExpr* normalize_variable_unpacked(const NetNet*net, list<long>&indices)
|
||||
{
|
||||
const vector<netrange_t>&dims = net->unpacked_dims();
|
||||
return normalize_variable_unpacked(dims, indices);
|
||||
}
|
||||
|
||||
NetExpr* normalize_variable_unpacked(const netsarray_t*stype, list<long>&indices)
|
||||
{
|
||||
const vector<netrange_t>&dims = stype->static_dimensions();
|
||||
return normalize_variable_unpacked(dims, indices);
|
||||
}
|
||||
|
||||
NetExpr* normalize_variable_unpacked(const LineInfo&loc, const vector<netrange_t>&dims, list<NetExpr*>&indices)
|
||||
{
|
||||
// Make strides for each index. The stride is the distance (in
|
||||
// words) to the next element in the canonical array.
|
||||
vector<long> stride (dims.size());
|
||||
|
|
@ -602,7 +611,7 @@ NetExpr* normalize_variable_unpacked(const NetNet*net, list<NetExpr*>&indices)
|
|||
if (use_stride != 1)
|
||||
min_wid += num_bits(use_stride);
|
||||
|
||||
tmp = pad_to_width(tmp, min_wid, *net);
|
||||
tmp = pad_to_width(tmp, min_wid, loc);
|
||||
|
||||
// Now generate the math to calculate the canonical address.
|
||||
NetExpr*tmp_scaled = 0;
|
||||
|
|
@ -641,11 +650,23 @@ NetExpr* normalize_variable_unpacked(const NetNet*net, list<NetExpr*>&indices)
|
|||
// If we don't have an expression at this point, all the indices were
|
||||
// constant zero. But this variant of normalize_variable_unpacked()
|
||||
// is only used when at least one index is not a constant.
|
||||
ivl_assert(*net, canonical_expr);
|
||||
ivl_assert(loc, canonical_expr);
|
||||
|
||||
return canonical_expr;
|
||||
}
|
||||
|
||||
NetExpr* normalize_variable_unpacked(const NetNet*net, list<NetExpr*>&indices)
|
||||
{
|
||||
const vector<netrange_t>&dims = net->unpacked_dims();
|
||||
return normalize_variable_unpacked(*net, dims, indices);
|
||||
}
|
||||
|
||||
NetExpr* normalize_variable_unpacked(const LineInfo&loc, const netsarray_t*stype, list<NetExpr*>&indices)
|
||||
{
|
||||
const vector<netrange_t>&dims = stype->static_dimensions();
|
||||
return normalize_variable_unpacked(loc, dims, indices);
|
||||
}
|
||||
|
||||
NetEConst* make_const_x(unsigned long wid)
|
||||
{
|
||||
verinum xxx (verinum::Vx, wid);
|
||||
|
|
@ -885,6 +906,48 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
bool evaluate_ranges(Design*des, NetScope*scope,
|
||||
vector<netrange_t>&llist,
|
||||
const list<pform_range_t>&rlist)
|
||||
{
|
||||
bool bad_msb = false, bad_lsb = false;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = rlist.begin()
|
||||
; cur != rlist.end() ; ++cur) {
|
||||
long use_msb, use_lsb;
|
||||
|
||||
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
|
||||
if (! eval_as_long(use_msb, texpr)) {
|
||||
cerr << cur->first->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << cur->first->get_fileline() << " : "
|
||||
"This MSB expression violates the rule: "
|
||||
<< *cur->first << endl;
|
||||
des->errors += 1;
|
||||
bad_msb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, cur->second, -1, true);
|
||||
if (! eval_as_long(use_lsb, texpr)) {
|
||||
cerr << cur->second->get_fileline() << ": error: "
|
||||
"Range expressions must be constant." << endl;
|
||||
cerr << cur->second->get_fileline() << " : "
|
||||
"This LSB expression violates the rule: "
|
||||
<< *cur->second << endl;
|
||||
des->errors += 1;
|
||||
bad_lsb = true;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
llist.push_back(netrange_t(use_msb, use_lsb));
|
||||
}
|
||||
|
||||
return bad_msb | bad_lsb;
|
||||
}
|
||||
|
||||
void eval_expr(NetExpr*&expr, int context_width)
|
||||
{
|
||||
assert(expr);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
# include "netlist.h"
|
||||
|
||||
class netsarray_t;
|
||||
|
||||
/*
|
||||
* Search for a symbol using the "start" scope as the starting
|
||||
* point. If the path includes a scope part, then locate the
|
||||
|
|
@ -184,7 +186,10 @@ extern void indices_to_expressions(Design*des, NetScope*scope,
|
|||
list<NetExpr*>&indices,list<long>&indices_const);
|
||||
|
||||
extern NetExpr*normalize_variable_unpacked(const NetNet*net, list<long>&indices);
|
||||
extern NetExpr*normalize_variable_unpacked(const netsarray_t*net, list<long>&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);
|
||||
|
||||
/*
|
||||
* This function takes as input a NetNet signal and adds a constant
|
||||
|
|
@ -278,6 +283,9 @@ extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
|||
unsigned lv_width, PExpr*expr,
|
||||
bool need_const =false);
|
||||
|
||||
extern bool evaluate_ranges(Design*des, NetScope*scope,
|
||||
std::vector<netrange_t>&llist,
|
||||
const std::list<pform_range_t>&rlist);
|
||||
/*
|
||||
* This procedure evaluates an expression and if the evaluation is
|
||||
* successful the original expression is replaced with the new one.
|
||||
|
|
|
|||
22
netparray.cc
22
netparray.cc
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
netsarray_t::~netsarray_t()
|
||||
{
|
||||
}
|
||||
|
||||
netparray_t::~netparray_t()
|
||||
{
|
||||
}
|
||||
|
|
@ -34,8 +38,8 @@ long netparray_t::packed_width(void) const
|
|||
{
|
||||
long cur_width = element_type()->packed_width();
|
||||
|
||||
for (vector<netrange_t>::const_iterator cur = packed_dims_.begin()
|
||||
; cur != packed_dims_.end() ; ++cur) {
|
||||
for (vector<netrange_t>::const_iterator cur = static_dimensions().begin()
|
||||
; cur != static_dimensions().end() ; ++cur) {
|
||||
cur_width *= cur->width();
|
||||
}
|
||||
|
||||
|
|
@ -44,14 +48,20 @@ long netparray_t::packed_width(void) const
|
|||
|
||||
vector<netrange_t> netparray_t::slice_dimensions() const
|
||||
{
|
||||
const vector<netrange_t>&packed_dims = static_dimensions();
|
||||
|
||||
vector<netrange_t> elem_dims = element_type()->slice_dimensions();
|
||||
|
||||
vector<netrange_t> res (packed_dims_.size() + elem_dims.size());
|
||||
vector<netrange_t> res (packed_dims.size() + elem_dims.size());
|
||||
|
||||
for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1)
|
||||
res[idx] = packed_dims_[idx];
|
||||
for (size_t idx = 0 ; idx < packed_dims.size() ; idx += 1)
|
||||
res[idx] = packed_dims[idx];
|
||||
for (size_t idx = 0 ; idx < elem_dims.size() ; idx += 1)
|
||||
res[idx+packed_dims_.size()] = elem_dims[idx];
|
||||
res[idx+packed_dims.size()] = elem_dims[idx];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
netuarray_t::~netuarray_t()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
57
netparray.h
57
netparray.h
|
|
@ -23,10 +23,39 @@
|
|||
# include "nettypes.h"
|
||||
# include <vector>
|
||||
|
||||
/*
|
||||
* Arrays with static dimensions (packed and unpacked) share this
|
||||
* common base type.
|
||||
*/
|
||||
class netsarray_t : public netarray_t {
|
||||
|
||||
public:
|
||||
explicit netsarray_t(const std::vector<netrange_t>&packed,
|
||||
ivl_type_t etype);
|
||||
~netsarray_t();
|
||||
|
||||
public:
|
||||
// Virtual methods from the ivl_type_s type...
|
||||
|
||||
public:
|
||||
inline const std::vector<netrange_t>& static_dimensions() const
|
||||
{ return dims_; }
|
||||
|
||||
private:
|
||||
std::vector<netrange_t> dims_;
|
||||
|
||||
};
|
||||
|
||||
inline netsarray_t::netsarray_t(const std::vector<netrange_t>&pd,
|
||||
ivl_type_t etype)
|
||||
: netarray_t(etype), dims_(pd)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Packed arrays.
|
||||
*/
|
||||
class netparray_t : public netarray_t {
|
||||
class netparray_t : public netsarray_t {
|
||||
|
||||
public:
|
||||
explicit netparray_t(const std::vector<netrange_t>&packed,
|
||||
|
|
@ -38,18 +67,28 @@ class netparray_t : public netarray_t {
|
|||
long packed_width(void) const;
|
||||
std::vector<netrange_t> slice_dimensions() const;
|
||||
|
||||
public:
|
||||
inline const std::vector<netrange_t>& packed_dimensions() const
|
||||
{ return packed_dims_; }
|
||||
|
||||
private:
|
||||
std::vector<netrange_t> packed_dims_;
|
||||
|
||||
};
|
||||
|
||||
inline netparray_t::netparray_t(const std::vector<netrange_t>&pd,
|
||||
ivl_type_t etype)
|
||||
: netarray_t(etype), packed_dims_(pd)
|
||||
: netsarray_t(pd, etype)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Unpacked arrays are very similar, but lack packed slices.
|
||||
*/
|
||||
class netuarray_t : public netsarray_t {
|
||||
|
||||
public:
|
||||
explicit netuarray_t(const std::vector<netrange_t>&packed,
|
||||
ivl_type_t etype);
|
||||
~netuarray_t();
|
||||
};
|
||||
|
||||
inline netuarray_t::netuarray_t(const std::vector<netrange_t>&pd,
|
||||
ivl_type_t etype)
|
||||
: netsarray_t(pd, etype)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue