Better handling of width of enum literals in expressions.
This commit is contained in:
parent
d37126bda5
commit
5e2c0e5d04
13
elab_expr.cc
13
elab_expr.cc
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
15
netenum.h
15
netenum.h
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue