From 5e2c0e5d0419b19add47359c6d51e581d0f01d64 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 7 Nov 2010 09:58:00 -0800 Subject: [PATCH] Better handling of width of enum literals in expressions. --- elab_expr.cc | 13 +++++++++++++ elab_scope.cc | 6 +++++- net_expr.cc | 1 + netenum.cc | 7 +++++-- netenum.h | 15 +++++++++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index e8aa19abd..b41c43741 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -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 (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. diff --git a/elab_scope.cc b/elab_scope.cc index a83bfa269..47a602ef9 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -229,7 +229,11 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, for (list::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; diff --git a/net_expr.cc b/net_expr.cc index b855e0737..d0a667c16 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -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() diff --git a/netenum.cc b/netenum.cc index 0dee3dd80..3ea9458f1 100644 --- a/netenum.cc +++ b/netenum.cc @@ -18,9 +18,10 @@ */ # include "netenum.h" +# include -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::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); diff --git a/netenum.h b/netenum.h index d299bcd05..ffc190d10 100644 --- a/netenum.h +++ b/netenum.h @@ -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 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