Better handling of width of enum literals in expressions.

This commit is contained in:
Stephen Williams 2010-11-07 09:58:00 -08:00
parent d37126bda5
commit 5e2c0e5d04
5 changed files with 39 additions and 3 deletions

View File

@ -2070,6 +2070,19 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
return expr_width_; return expr_width_;
} }
// The width of an enumeration literal is the width of the
// enumeration base.
if (const NetEConstEnum*par_enum = dynamic_cast<const NetEConstEnum*> (par)) {
netenum_t*use_enum = par_enum->enumeration();
ivl_assert(*this, use_enum != 0);
expr_type_ = use_enum->base_type();
unsized_flag = false;
expr_width_ = max(use_enum->base_width(), min);
expr_type__ = expr_type_;
return expr_width_;
}
// The width of a parameter name is the width of the range for // The width of a parameter name is the width of the range for
// the parameter name, if a range is declared. Otherwise, the // the parameter name, if a range is declared. Otherwise, the
// width is undefined. // width is undefined.

View File

@ -229,7 +229,11 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
for (list<named_number_t>::const_iterator cur = enum_type->names->begin() for (list<named_number_t>::const_iterator cur = enum_type->names->begin()
; cur != enum_type->names->end() ; ++ cur) { ; cur != enum_type->names->end() ; ++ cur) {
rc_flag = use_enum->insert_name(cur->name, cur->parm); // The values are explicitly sized to the width of the
// base type of the enumeration.
verinum tmp_val (cur->parm, use_enum->base_width());
rc_flag = use_enum->insert_name(cur->name, tmp_val);
rc_flag &= scope->add_enumeration_name(use_enum, cur->name); rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
if (! rc_flag) { if (! rc_flag) {
cerr << "<>:0: error: Duplicate enumeration name " << cur->name << endl; cerr << "<>:0: error: Duplicate enumeration name " << cur->name << endl;

View File

@ -440,6 +440,7 @@ unsigned NetEConcat::repeat() const
NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, netenum_t*eset, const verinum&v) NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, netenum_t*eset, const verinum&v)
: NetEConst(v), scope_(s), enum_set_(eset), name_(n) : NetEConst(v), scope_(s), enum_set_(eset), name_(n)
{ {
assert(has_width());
} }
NetEConstEnum::~NetEConstEnum() NetEConstEnum::~NetEConstEnum()

View File

@ -18,9 +18,10 @@
*/ */
# include "netenum.h" # include "netenum.h"
# include <cassert>
netenum_t::netenum_t(ivl_variable_type_t base_type, bool signed_flag, long msb, long lsb) netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag, long msb, long lsb)
: base_type_(base_type), signed_flag_(signed_flag), msb_(msb), lsb_(lsb) : base_type_(btype), signed_flag_(signed_flag), msb_(msb), lsb_(lsb)
{ {
} }
@ -32,6 +33,8 @@ bool netenum_t::insert_name(perm_string name, const verinum&val)
{ {
std::pair<std::map<perm_string,verinum>::iterator, bool> res; std::pair<std::map<perm_string,verinum>::iterator, bool> res;
assert(val.has_len() && val.len() == (msb_-lsb_+1));
res = names_map_.insert( make_pair(name,val) ); res = names_map_.insert( make_pair(name,val) );
// Only add the name to the list if it is not there already. // Only add the name to the list if it is not there already.
if (res.second) names_.push_back(name); if (res.second) names_.push_back(name);

View File

@ -32,6 +32,10 @@ class netenum_t {
long msb, long lsb); long msb, long lsb);
~netenum_t(); ~netenum_t();
ivl_variable_type_t base_type() const;
unsigned base_width() const;
// The size() is the number of enumeration literals.
size_t size() const; size_t size() const;
bool insert_name(perm_string name, const verinum&val); bool insert_name(perm_string name, const verinum&val);
@ -53,6 +57,17 @@ class netenum_t {
std::list<perm_string> names_; std::list<perm_string> names_;
}; };
inline ivl_variable_type_t netenum_t::base_type() const
{ return base_type_; }
inline unsigned netenum_t::base_width() const
{
if (msb_ >= lsb_)
return msb_ - lsb_ + 1;
else
return lsb_ - msb_ + 1;
}
inline size_t netenum_t::size() const { return names_.size(); } inline size_t netenum_t::size() const { return names_.size(); }
#endif #endif