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);
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) {
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
// expression that address the member element.
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.
list<long>prefix_indices;
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
// be part selects only if we are taking the part-select
// 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
// 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.
long loff;
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) {
cerr << li->get_fileline() << ": debug: check_for_struct_members: "
@ -1838,7 +1845,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
}
off += loff;
if (comp.index.size() >= mem->packed_dims.size())
if (comp.index.size() >= packed_dims.size())
use_width = pwid;
else
use_width = lwid;
@ -2920,7 +2927,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
method_name, unused);
if (mem) {
expr_type_ = mem->data_type();
expr_width_ = mem->width();
expr_width_ = mem->net_type->packed_width();
min_width_ = expr_width_;
signed_flag_ = mem->get_signed();
return expr_width_;

View File

@ -27,6 +27,7 @@
# include "netstruct.h"
# include "netclass.h"
# include "netdarray.h"
# include "netvector.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
@ -1014,9 +1015,13 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
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;
des->errors += 1;
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.
long loff;
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;
use_width = lwid;

View File

@ -524,7 +524,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "Member " << method_name
<< " has packed dimensions " << member->packed_dims << "." << endl;
<< " has type " << *member->net_type << "." << endl;
cerr << get_fileline() << ": : "
<< "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
// part select of the base variable.
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 signal at this point. (The sig
@ -563,7 +563,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
long tmp;
if (packed_base && eval_as_long(tmp, packed_base)) {
lidx = tmp;
midx = lidx + member->width() - 1;
midx = lidx + member->net_type->packed_width() - 1;
delete packed_base;
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
// up, deal with bit/part selects from the member
// 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);
if (! path_tail.index.empty()) {
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));
}
netvector_t*mem_vec = new netvector_t(packed_dimensions, curp->type);
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
; name != curp->names->end() ; ++ name) {
decl_assignment_t*namep = *name;
netstruct_t::member_t memb;
memb.name = namep->name;
memb.type = curp->type;
memb.packed_dims = packed_dimensions;
memb.net_type = mem_vec;
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)
: netarray_t(etype), packed_dims_(packed)
: netarray_t(etype), packed_dims_(pd)
{
}

View File

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

View File

@ -29,10 +29,9 @@ class netstruct_t : public LineInfo, public ivl_type_s {
public:
struct member_t {
perm_string name;
ivl_variable_type_t type;
std::vector<netrange_t> packed_dims;
long width() const;
ivl_variable_type_t data_type() const { return type; };
ivl_type_t net_type;
inline ivl_variable_type_t data_type() const
{ return net_type->base_type(); };
// We need to keep the individual element sign information.
bool get_signed() const { return false; };
};
@ -41,6 +40,12 @@ class netstruct_t : public LineInfo, public ivl_type_s {
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);
bool packed(void) const;
@ -61,13 +66,12 @@ class netstruct_t : public LineInfo, public ivl_type_s {
ivl_variable_type_t base_type() const;
private:
bool union_;
bool packed_;
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 long netstruct_t::member_t::width() const
{ return netrange_width(packed_dims); }
#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
{
return 1;

View File

@ -35,6 +35,7 @@ class netrange_t;
class ivl_type_s {
public:
virtual ~ivl_type_s() =0;
virtual bool packed(void) const;
virtual long packed_width(void) 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_;
}
/*
* vectors are by definition packed.
*/
bool netvector_t::packed(void) const
{
return true;
}
long netvector_t::packed_width() const
{
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;
const std::vector<netrange_t>&packed_dims() const;
bool packed(void) const;
long packed_width() const;
std::vector<netrange_t> slice_dimensions() const;
@ -89,9 +90,9 @@ class netvector_t : public ivl_type_s {
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)
: packed_dims_(packed), type_(type), signed_(false), isint_(false),
: packed_dims_(pd), type_(type), signed_(false), isint_(false),
is_scalar_(false)
{
}