From d37126bda5a99b67a557b68658f1750f1b2892e0 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 5 Nov 2010 19:49:28 -0700 Subject: [PATCH] Implement enum first/last/num methods. --- elab_expr.cc | 28 ++++++++++++++++++++++++++++ netenum.cc | 23 +++++++++++++++++++---- netenum.h | 12 +++++++++++- netmisc.cc | 8 ++++++++ netmisc.h | 1 + 5 files changed, 67 insertions(+), 5 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index ebb1bd951..e8aa19abd 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -26,6 +26,7 @@ # include "pform.h" # include "netlist.h" +# include "netenum.h" # include "discipline.h" # include "netmisc.h" # include "util.h" @@ -2214,9 +2215,36 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, net, par, eve, ex1, ex2); if (net != 0) { + // Special case: The net is an enum, and the + // method name is "num". + netenum_t*netenum = net->enumeration(); + if (netenum && method_name == "num") { + NetEConst*tmp = make_const_val(netenum->size()); + tmp->set_line(*this); + return tmp; + } + + // Special case: The net is an enum, and the + // method name is "first". + if (netenum && method_name == "first") { + netenum_t::iterator item = netenum->first_name(); + NetEConstEnum*tmp = new NetEConstEnum(scope, item->first, + netenum, item->second); + tmp->set_line(*this); + return tmp; + } + if (netenum && method_name == "last") { + netenum_t::iterator item = netenum->last_name(); + NetEConstEnum*tmp = new NetEConstEnum(scope, item->first, + netenum, item->second); + tmp->set_line(*this); + return tmp; + } + const char*func_name = 0; if (method_name == "name") { func_name = "$ivl_method$name"; + } else { cerr << get_fileline() << ": error: " << "Unknown method name `" << method_name << "'" diff --git a/netenum.cc b/netenum.cc index 1821e9385..0dee3dd80 100644 --- a/netenum.cc +++ b/netenum.cc @@ -30,16 +30,31 @@ netenum_t::~netenum_t() bool netenum_t::insert_name(perm_string name, const verinum&val) { - names_[name] = verinum(val, msb_-lsb_+1); - return true; + std::pair::iterator, bool> res; + + 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); + + return res.second; } netenum_t::iterator netenum_t::find_name(perm_string name) const { - return names_.find(name); + return names_map_.find(name); } netenum_t::iterator netenum_t::end_name() const { - return names_.end(); + return names_map_.end(); +} + +netenum_t::iterator netenum_t::first_name() const +{ + return names_map_.find(names_.front()); +} + +netenum_t::iterator netenum_t::last_name() const +{ + return names_map_.find(names_.back()); } diff --git a/netenum.h b/netenum.h index 34843ef37..d299bcd05 100644 --- a/netenum.h +++ b/netenum.h @@ -22,6 +22,7 @@ # include "ivl_target.h" # include "verinum.h" # include "StringHeap.h" +# include # include class netenum_t { @@ -31,18 +32,27 @@ class netenum_t { long msb, long lsb); ~netenum_t(); + size_t size() const; + bool insert_name(perm_string name, const verinum&val); typedef std::map::const_iterator iterator; iterator find_name(perm_string name) const; iterator end_name() const; + // These methods roughly match the .first() and .last() methods. + iterator first_name() const; + iterator last_name() const; + private: ivl_variable_type_t base_type_; bool signed_flag_; long msb_, lsb_; - std::map names_; + std::map names_map_; + std::list names_; }; +inline size_t netenum_t::size() const { return names_.size(); } + #endif diff --git a/netmisc.cc b/netmisc.cc index 73d1f3b58..11d042f83 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -24,6 +24,7 @@ # include "netmisc.h" # include "PExpr.h" # include "pform_types.h" +# include "compiler.h" # include "ivl_assert.h" NetNet* add_to_net(Design*des, NetNet*sig, long val) @@ -393,6 +394,13 @@ NetEConst* make_const_0(unsigned long wid) return resx; } +NetEConst* make_const_val(unsigned long value) +{ + verinum tmp (value, integer_width); + NetEConst*res = new NetEConst(tmp); + return res; +} + NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid) { verinum xxx (verinum::Vx, wid); diff --git a/netmisc.h b/netmisc.h index b7618f7ed..5c4ae014c 100644 --- a/netmisc.h +++ b/netmisc.h @@ -116,6 +116,7 @@ extern NetNet*sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig); */ extern NetEConst*make_const_x(unsigned long wid); extern NetEConst*make_const_0(unsigned long wid); +extern NetEConst*make_const_val(unsigned long val); /* * Make A const net