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_;
}
// 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 parameter name, if a range is declared. Otherwise, the
// 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()
; 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);
if (! rc_flag) {
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)
: NetEConst(v), scope_(s), enum_set_(eset), name_(n)
{
assert(has_width());
}
NetEConstEnum::~NetEConstEnum()

View File

@ -18,9 +18,10 @@
*/
# include "netenum.h"
# include <cassert>
netenum_t::netenum_t(ivl_variable_type_t base_type, bool signed_flag, long msb, long lsb)
: base_type_(base_type), signed_flag_(signed_flag), msb_(msb), lsb_(lsb)
netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag, long msb, long 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;
assert(val.has_len() && val.len() == (msb_-lsb_+1));
res = names_map_.insert( make_pair(name,val) );
// Only add the name to the list if it is not there already.
if (res.second) names_.push_back(name);

View File

@ -32,6 +32,10 @@ class netenum_t {
long msb, long lsb);
~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;
bool insert_name(perm_string name, const verinum&val);
@ -53,6 +57,17 @@ class netenum_t {
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(); }
#endif