Generalize struct member type

This commit is contained in:
Stephen Williams 2013-11-29 12:43:34 -08:00
parent aced587461
commit 0b4056817a
11 changed files with 70 additions and 28 deletions

View File

@ -1793,7 +1793,9 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
comp.name, off); comp.name, off);
if (mem == 0) return 0; if (mem == 0) return 0;
unsigned use_width = mem->width(); ivl_assert(*li, mem->net_type && mem->net_type->packed());
unsigned use_width = mem->net_type->packed_width();
if (debug_elaborate) { if (debug_elaborate) {
cerr << li->get_fileline() << ": debug: check_for_struct_members: " cerr << li->get_fileline() << ": debug: check_for_struct_members: "
@ -1805,6 +1807,11 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
// The struct member may be a packed array. Process index // The struct member may be a packed array. Process index
// expression that address the member element. // expression that address the member element.
if ( ! comp.index.empty() ) { if ( ! comp.index.empty() ) {
const netvector_t*mem_vec = dynamic_cast<const netvector_t*> (mem->net_type);
ivl_assert(*li, mem_vec);
const vector<netrange_t>&packed_dims = mem_vec->packed_dims();
// Evaluate all but the last index expression, into prefix_indices. // Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices; list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, comp.index); bool rc = evaluate_index_prefix(des, scope, prefix_indices, comp.index);
@ -1814,7 +1821,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
// elements are in fact like bit selects. The tail may // elements are in fact like bit selects. The tail may
// be part selects only if we are taking the part-select // be part selects only if we are taking the part-select
// of the word of an array. // of the word of an array.
ivl_assert(*li, comp.index.size() >= mem->packed_dims.size() || comp.index.back().sel == index_component_t::SEL_BIT); ivl_assert(*li, comp.index.size() >= packed_dims.size() || comp.index.back().sel == index_component_t::SEL_BIT);
// Evaluate the part/bit select expressions. This may be // Evaluate the part/bit select expressions. This may be
// a bit select or a part select. In any case, assume // a bit select or a part select. In any case, assume
@ -1829,7 +1836,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
// offset and width of the addressed slice of the member. // offset and width of the addressed slice of the member.
long loff; long loff;
unsigned long lwid; unsigned long lwid;
prefix_to_slice(mem->packed_dims, prefix_indices, poff, loff, lwid); prefix_to_slice(packed_dims, prefix_indices, poff, loff, lwid);
if (debug_elaborate) { if (debug_elaborate) {
cerr << li->get_fileline() << ": debug: check_for_struct_members: " cerr << li->get_fileline() << ": debug: check_for_struct_members: "
@ -1838,7 +1845,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
} }
off += loff; off += loff;
if (comp.index.size() >= mem->packed_dims.size()) if (comp.index.size() >= packed_dims.size())
use_width = pwid; use_width = pwid;
else else
use_width = lwid; use_width = lwid;
@ -2920,7 +2927,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
method_name, unused); method_name, unused);
if (mem) { if (mem) {
expr_type_ = mem->data_type(); expr_type_ = mem->data_type();
expr_width_ = mem->width(); expr_width_ = mem->net_type->packed_width();
min_width_ = expr_width_; min_width_ = expr_width_;
signed_flag_ = mem->get_signed(); signed_flag_ = mem->get_signed();
return expr_width_; return expr_width_;

View File

@ -27,6 +27,7 @@
# include "netstruct.h" # include "netstruct.h"
# include "netclass.h" # include "netclass.h"
# include "netdarray.h" # include "netdarray.h"
# include "netvector.h"
# include "compiler.h" # include "compiler.h"
# include <cstdlib> # include <cstdlib>
# include <iostream> # include <iostream>
@ -1014,9 +1015,13 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
return false; return false;
} }
unsigned long use_width = member->width(); unsigned long use_width = member->net_type->packed_width();
if (name_tail.index.size() > member->packed_dims.size()) { const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type);
ivl_assert(*this, mem_vec);
const vector<netrange_t>&mem_packed_dims = mem_vec->packed_dims();
if (name_tail.index.size() > mem_packed_dims.size()) {
cerr << get_fileline() << ": error: Too many index expressions for member." << endl; cerr << get_fileline() << ": error: Too many index expressions for member." << endl;
des->errors += 1; des->errors += 1;
return false; return false;
@ -1052,7 +1057,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
// offset and width of the addressed slice of the member. // offset and width of the addressed slice of the member.
long loff; long loff;
unsigned long lwid; unsigned long lwid;
prefix_to_slice(member->packed_dims, prefix_indices, tmp, loff, lwid); prefix_to_slice(mem_packed_dims, prefix_indices, tmp, loff, lwid);
off += loff; off += loff;
use_width = lwid; use_width = lwid;

View File

@ -524,7 +524,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "Member " << method_name << "Member " << method_name
<< " has packed dimensions " << member->packed_dims << "." << endl; << " has type " << *member->net_type << "." << endl;
cerr << get_fileline() << ": : " cerr << get_fileline() << ": : "
<< "Tail name has " << path_tail.index.size() << " indices." << endl; << "Tail name has " << path_tail.index.size() << " indices." << endl;
} }
@ -532,7 +532,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// Rewrite a member select of a packed structure as a // Rewrite a member select of a packed structure as a
// part select of the base variable. // part select of the base variable.
lidx = member_off; lidx = member_off;
midx = lidx + member->width() - 1; midx = lidx + member->net_type->packed_width() - 1;
// The dimensions of the tail of the prefix must match // The dimensions of the tail of the prefix must match
// the dimensions of the signal at this point. (The sig // the dimensions of the signal at this point. (The sig
@ -563,7 +563,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
long tmp; long tmp;
if (packed_base && eval_as_long(tmp, packed_base)) { if (packed_base && eval_as_long(tmp, packed_base)) {
lidx = tmp; lidx = tmp;
midx = lidx + member->width() - 1; midx = lidx + member->net_type->packed_width() - 1;
delete packed_base; delete packed_base;
packed_base = 0; packed_base = 0;
} }
@ -574,7 +574,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// Now the lidx/midx values get us to the member. Next // Now the lidx/midx values get us to the member. Next
// up, deal with bit/part selects from the member // up, deal with bit/part selects from the member
// itself. // itself.
ivl_assert(*this, member->packed_dims.size() <= 1); //XXXXivl_assert(*this, member->packed_dims.size() <= 1);
ivl_assert(*this, path_tail.index.size() <= 1); ivl_assert(*this, path_tail.index.size() <= 1);
if (! path_tail.index.empty()) { if (! path_tail.index.empty()) {
long tmp_off; long tmp_off;

View File

@ -894,14 +894,15 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
packed_dimensions.push_back(netrange_t(0,0)); packed_dimensions.push_back(netrange_t(0,0));
} }
netvector_t*mem_vec = new netvector_t(packed_dimensions, curp->type);
for (list<decl_assignment_t*>::iterator name = curp->names->begin() for (list<decl_assignment_t*>::iterator name = curp->names->begin()
; name != curp->names->end() ; ++ name) { ; name != curp->names->end() ; ++ name) {
decl_assignment_t*namep = *name; decl_assignment_t*namep = *name;
netstruct_t::member_t memb; netstruct_t::member_t memb;
memb.name = namep->name; memb.name = namep->name;
memb.type = curp->type; memb.net_type = mem_vec;
memb.packed_dims = packed_dimensions;
res->append_member(memb); res->append_member(memb);
} }
} }

View File

@ -47,9 +47,9 @@ class netparray_t : public netarray_t {
}; };
inline netparray_t::netparray_t(const std::vector<netrange_t>&packed, inline netparray_t::netparray_t(const std::vector<netrange_t>&pd,
ivl_type_t etype) ivl_type_t etype)
: netarray_t(etype), packed_dims_(packed) : netarray_t(etype), packed_dims_(pd)
{ {
} }

View File

@ -18,12 +18,13 @@
*/ */
# include "netstruct.h" # include "netstruct.h"
# include "netvector.h"
# include <iostream> # include <iostream>
using namespace std; using namespace std;
netstruct_t::netstruct_t() netstruct_t::netstruct_t()
: packed_(false) : union_(false), packed_(false)
{ {
} }
@ -31,6 +32,11 @@ netstruct_t::~netstruct_t()
{ {
} }
void netstruct_t::union_flag(bool flag)
{
union_ = flag;
}
void netstruct_t::packed(bool flag) void netstruct_t::packed(bool flag)
{ {
packed_ = flag; packed_ = flag;
@ -49,7 +55,7 @@ const netstruct_t::member_t* netstruct_t::packed_member(perm_string name, unsign
off = count_off; off = count_off;
return &members_[idx-1]; return &members_[idx-1];
} }
count_off += members_[idx-1].width(); count_off += members_[idx-1].net_type->packed_width();
} }
return 0; return 0;
@ -62,7 +68,7 @@ long netstruct_t::packed_width(void) const
long res = 0; long res = 0;
for (size_t idx = 0 ; idx < members_.size() ; idx += 1) for (size_t idx = 0 ; idx < members_.size() ; idx += 1)
res += members_[idx].width(); res += members_[idx].net_type->packed_width();
return res; return res;
} }

View File

@ -29,10 +29,9 @@ class netstruct_t : public LineInfo, public ivl_type_s {
public: public:
struct member_t { struct member_t {
perm_string name; perm_string name;
ivl_variable_type_t type; ivl_type_t net_type;
std::vector<netrange_t> packed_dims; inline ivl_variable_type_t data_type() const
long width() const; { return net_type->base_type(); };
ivl_variable_type_t data_type() const { return type; };
// We need to keep the individual element sign information. // We need to keep the individual element sign information.
bool get_signed() const { return false; }; bool get_signed() const { return false; };
}; };
@ -41,6 +40,12 @@ class netstruct_t : public LineInfo, public ivl_type_s {
netstruct_t(); netstruct_t();
~netstruct_t(); ~netstruct_t();
// If this is a union (instead of struct) then this flag is
// set. We handle union and struct together because they are
// so similar.
void union_flag(bool);
bool union_flag(void) const;
void packed(bool flag); void packed(bool flag);
bool packed(void) const; bool packed(void) const;
@ -61,13 +66,12 @@ class netstruct_t : public LineInfo, public ivl_type_s {
ivl_variable_type_t base_type() const; ivl_variable_type_t base_type() const;
private: private:
bool union_;
bool packed_; bool packed_;
std::vector<member_t>members_; std::vector<member_t>members_;
}; };
inline bool netstruct_t::union_flag(void) const { return union_; }
inline bool netstruct_t::packed(void) const { return packed_; } inline bool netstruct_t::packed(void) const { return packed_; }
inline long netstruct_t::member_t::width() const
{ return netrange_width(packed_dims); }
#endif #endif

View File

@ -26,6 +26,15 @@ ivl_type_s::~ivl_type_s()
{ {
} }
/*
* The derived class may override this to provide a more accurate
* response.
*/
bool ivl_type_s::packed(void) const
{
return false;
}
long ivl_type_s::packed_width(void) const long ivl_type_s::packed_width(void) const
{ {
return 1; return 1;

View File

@ -35,6 +35,7 @@ class netrange_t;
class ivl_type_s { class ivl_type_s {
public: public:
virtual ~ivl_type_s() =0; virtual ~ivl_type_s() =0;
virtual bool packed(void) const;
virtual long packed_width(void) const; virtual long packed_width(void) const;
virtual std::vector<netrange_t> slice_dimensions() const; virtual std::vector<netrange_t> slice_dimensions() const;

View File

@ -54,6 +54,14 @@ ivl_variable_type_t netvector_t::base_type() const
return type_; return type_;
} }
/*
* vectors are by definition packed.
*/
bool netvector_t::packed(void) const
{
return true;
}
long netvector_t::packed_width() const long netvector_t::packed_width() const
{ {
return netrange_width(packed_dims_); return netrange_width(packed_dims_);

View File

@ -60,6 +60,7 @@ class netvector_t : public ivl_type_s {
ivl_variable_type_t base_type() const; ivl_variable_type_t base_type() const;
const std::vector<netrange_t>&packed_dims() const; const std::vector<netrange_t>&packed_dims() const;
bool packed(void) const;
long packed_width() const; long packed_width() const;
std::vector<netrange_t> slice_dimensions() const; std::vector<netrange_t> slice_dimensions() const;
@ -89,9 +90,9 @@ class netvector_t : public ivl_type_s {
bool is_scalar_ : 1; bool is_scalar_ : 1;
}; };
inline netvector_t::netvector_t(const std::vector<netrange_t>&packed, inline netvector_t::netvector_t(const std::vector<netrange_t>&pd,
ivl_variable_type_t type) ivl_variable_type_t type)
: packed_dims_(packed), type_(type), signed_(false), isint_(false), : packed_dims_(pd), type_(type), signed_(false), isint_(false),
is_scalar_(false) is_scalar_(false)
{ {
} }