Skip to content

Commit

Permalink
Better handling of width of enum literals in expressions.
Browse files Browse the repository at this point in the history
  • Loading branch information
steveicarus committed Nov 7, 2010
1 parent d37126b commit 5e2c0e5
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 3 deletions.
13 changes: 13 additions & 0 deletions elab_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 5 additions & 1 deletion elab_scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions net_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
7 changes: 5 additions & 2 deletions netenum.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
}

Expand All @@ -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);
Expand Down
15 changes: 15 additions & 0 deletions netenum.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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

0 comments on commit 5e2c0e5

Please sign in to comment.