Handle packed unions properly during elaboration.
This also gets r-value use of packed unions correct.
This commit is contained in:
parent
49756a8e7a
commit
0d6c15e45a
42
elab_sig.cc
42
elab_sig.cc
|
|
@ -38,7 +38,6 @@
|
|||
# include "netmisc.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
# include "netstruct.h"
|
||||
# include "netvector.h"
|
||||
# include "netdarray.h"
|
||||
# include "netparray.h"
|
||||
|
|
@ -873,47 +872,6 @@ static netclass_t* locate_class_type(Design*, NetScope*scope,
|
|||
return use_class;
|
||||
}
|
||||
|
||||
netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const
|
||||
{
|
||||
netstruct_t*res = new netstruct_t;
|
||||
|
||||
res->packed(packed_flag);
|
||||
|
||||
if (union_flag)
|
||||
res->union_flag(true);
|
||||
|
||||
for (list<struct_member_t*>::iterator cur = members->begin()
|
||||
; cur != members->end() ; ++ cur) {
|
||||
|
||||
vector<netrange_t>packed_dimensions;
|
||||
|
||||
struct_member_t*curp = *cur;
|
||||
vector_type_t*vecp = dynamic_cast<vector_type_t*> (curp->type.get());
|
||||
if (vecp && vecp->pdims.get() && ! vecp->pdims->empty()) {
|
||||
bool bad_range;
|
||||
bad_range = evaluate_ranges(des, scope, packed_dimensions, *vecp->pdims);
|
||||
ivl_assert(*curp, !bad_range);
|
||||
} else {
|
||||
packed_dimensions.push_back(netrange_t(0,0));
|
||||
}
|
||||
|
||||
netvector_t*mem_vec = new netvector_t(packed_dimensions,
|
||||
curp->type->figure_packed_base_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.net_type = mem_vec;
|
||||
res->append_member(memb);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
|
||||
data_type_t*pform_type)
|
||||
{
|
||||
|
|
|
|||
34
elab_type.cc
34
elab_type.cc
|
|
@ -22,6 +22,7 @@
|
|||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netscalar.h"
|
||||
# include "netstruct.h"
|
||||
# include "netvector.h"
|
||||
# include "netmisc.h"
|
||||
# include <typeinfo>
|
||||
|
|
@ -130,6 +131,39 @@ ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const
|
|||
return &netstring_t::type_string;
|
||||
}
|
||||
|
||||
netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const
|
||||
{
|
||||
netstruct_t*res = new netstruct_t;
|
||||
|
||||
res->packed(packed_flag);
|
||||
|
||||
if (union_flag)
|
||||
res->union_flag(true);
|
||||
|
||||
for (list<struct_member_t*>::iterator cur = members->begin()
|
||||
; cur != members->end() ; ++ cur) {
|
||||
|
||||
// Elaborate the type of the member.
|
||||
struct_member_t*curp = *cur;
|
||||
ivl_type_t mem_vec = curp->type->elaborate_type(des, scope);
|
||||
|
||||
// There may be several names that are the same type:
|
||||
// <data_type> name1, name2, ...;
|
||||
// Process all the member, and give them a 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.net_type = mem_vec;
|
||||
res->append_member(des, memb);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ivl_type_s* uarray_type_t::elaborate_type(Design*des, NetScope*scope) const
|
||||
{
|
||||
|
||||
|
|
|
|||
42
netstruct.cc
42
netstruct.cc
|
|
@ -17,10 +17,13 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netstruct.h"
|
||||
# include "netvector.h"
|
||||
# include <iostream>
|
||||
|
||||
# include "ivl_assert.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
netstruct_t::netstruct_t()
|
||||
|
|
@ -34,17 +37,43 @@ netstruct_t::~netstruct_t()
|
|||
|
||||
void netstruct_t::union_flag(bool flag)
|
||||
{
|
||||
// This MUST be called before any members are pushed into the
|
||||
// definition. This is because the append relies on this flag
|
||||
// being accurate.
|
||||
ivl_assert(*this, members_.empty());
|
||||
union_ = flag;
|
||||
}
|
||||
|
||||
void netstruct_t::packed(bool flag)
|
||||
{
|
||||
ivl_assert(*this, members_.empty());
|
||||
packed_ = flag;
|
||||
}
|
||||
|
||||
void netstruct_t::append_member(const netstruct_t::member_t&val)
|
||||
void netstruct_t::append_member(Design*des, const netstruct_t::member_t&val)
|
||||
{
|
||||
members_.push_back(val);
|
||||
if (packed_) {
|
||||
if (! members_.back().net_type->packed()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Member " << members_.back().name
|
||||
<< " of packed struct/union"
|
||||
<< " must be packed." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
if (union_ && packed_ && members_.size() > 1) {
|
||||
unsigned long expect_wid = members_.front().net_type->packed_width();
|
||||
unsigned long got_wid = members_.back().net_type->packed_width();
|
||||
if (expect_wid != got_wid) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Member " << val.name
|
||||
<< " of packed union"
|
||||
<< " is " << got_wid
|
||||
<< " bits, expecting " << expect_wid << " bits." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const netstruct_t::member_t* netstruct_t::packed_member(perm_string name, unsigned long&off) const
|
||||
|
|
@ -55,6 +84,10 @@ const netstruct_t::member_t* netstruct_t::packed_member(perm_string name, unsign
|
|||
off = count_off;
|
||||
return &members_[idx-1];
|
||||
}
|
||||
// If this is not a union, then the members are lined up
|
||||
// from LSB to MSB. If this is a union, then all
|
||||
// members are at offset 0.
|
||||
if (!union_)
|
||||
count_off += members_[idx-1].net_type->packed_width();
|
||||
}
|
||||
|
||||
|
|
@ -66,6 +99,13 @@ long netstruct_t::packed_width(void) const
|
|||
if (! packed_)
|
||||
return -1;
|
||||
|
||||
// If this is a packed union, then all the members are the
|
||||
// same width, so it is sufficient to return the width of any
|
||||
// single member.
|
||||
if (union_)
|
||||
return members_.front().net_type->packed_width();
|
||||
|
||||
// The width of a packed struct is the sum of member widths.
|
||||
long res = 0;
|
||||
for (size_t idx = 0 ; idx < members_.size() ; idx += 1)
|
||||
res += members_[idx].net_type->packed_width();
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
# include "ivl_target.h"
|
||||
# include "nettypes.h"
|
||||
|
||||
class Design;
|
||||
|
||||
class netstruct_t : public LineInfo, public ivl_type_s {
|
||||
|
||||
public:
|
||||
|
|
@ -49,7 +51,11 @@ class netstruct_t : public LineInfo, public ivl_type_s {
|
|||
void packed(bool flag);
|
||||
bool packed(void) const;
|
||||
|
||||
void append_member(const member_t&);
|
||||
// Append a new member to the struct/union. This must be done
|
||||
// after the union_flag and packed settings are set. This
|
||||
// function does error checking, and the "des" argument is
|
||||
// only present so that it can set error flags.
|
||||
void append_member(Design*des, const member_t&);
|
||||
|
||||
// Given the name of a member, return a pointer to the member
|
||||
// description, and set the off value to be the offset into
|
||||
|
|
|
|||
Loading…
Reference in New Issue