Skip to content
Browse files

Test type correctness during elaboration.

Create a netenum_t class to carry the enumeration type in the
netlist.h structures, and use that type to check enumerations
with assignments.
  • Loading branch information...
1 parent 94acc39 commit 5b5a6b05b75370879e071ef8a945b930f3156fa5 @steveicarus committed Nov 2, 2010
Showing with 206 additions and 21 deletions.
  1. +3 −3 Makefile.in
  2. +4 −1 design_dump.cc
  3. +9 −0 elab_expr.cc
  4. +6 −2 elab_scope.cc
  5. +9 −0 elab_sig.cc
  6. +6 −0 elaborate.cc
  7. +19 −0 net_assign.cc
  8. +7 −2 net_expr.cc
  9. +13 −4 net_scope.cc
  10. +45 −0 netenum.cc
  11. +48 −0 netenum.h
  12. +15 −3 netlist.cc
  13. +22 −6 netlist.h
View
6 Makefile.in
@@ -95,9 +95,9 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
elab_scope.o elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o net_analog.o net_assign.o net_design.o \
- net_event.o net_expr.o net_func.o net_link.o net_modulo.o net_nex_input.o \
- net_nex_output.o net_proc.o net_scope.o net_tran.o net_udp.o \
- pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
+ netenum.o net_event.o net_expr.o net_func.o net_link.o net_modulo.o \
+ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \
+ net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \
pform_disciplines.o pform_dump.o pform_types.o set_width.o \
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \
View
5 design_dump.cc
@@ -94,6 +94,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
case IVL_VT_LOGIC:
o << "logic";
break;
+ case IVL_VT_STRING:
+ o << "string";
+ break;
}
return o;
}
@@ -1190,7 +1193,7 @@ void NetScope::dump(ostream&o) const
o << " enum sets {" << endl;
/* Dump the enumerations and enum names in this scope. */
- for (list<enum_set_t>::const_iterator cur = enum_sets_.begin()
+ for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
; cur != enum_sets_.end() ; ++ cur) {
o << " " << *cur << endl;
}
View
9 elab_expr.cc
@@ -104,6 +104,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
switch (data_type_lv) {
case IVL_VT_REAL:
+ case IVL_VT_STRING:
unsized_flag = true;
expr_wid = -2;
expr_wid_lv = -1;
@@ -2782,7 +2783,15 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
tmp = stmp;
}
+ } else if (NetEConstEnum*etmp = dynamic_cast<NetEConstEnum*>(tmp)) {
+ if (debug_elaborate)
+ cerr << get_fileline() << ": debug: "
+ << "Elaborate parameter <" << path_
+ << "> as enumeration constant." << endl;
+ tmp = etmp->dup_expr();
+
} else {
+
/* No bit or part select. Make the constant into a
NetEConstParam if possible. */
NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp);
View
8 elab_scope.cc
@@ -42,6 +42,7 @@
# include "Statement.h"
# include "AStatement.h"
# include "netlist.h"
+# include "netenum.h"
# include "util.h"
# include <typeinfo>
# include <cassert>
@@ -209,12 +210,15 @@ static void elaborate_scope_localparams_(Design*des, NetScope*scope,
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_set_t enum_set)
{
- scope->add_enumeration_set(enum_set);
+ netenum_t*use_enum = new netenum_t(IVL_VT_BOOL, true, 31, 0);
+
+ scope->add_enumeration_set(use_enum);
for (map<perm_string,verinum>::const_iterator cur = enum_set->begin()
; cur != enum_set->end() ; ++ cur) {
- bool rc = scope->add_enumeration_name(enum_set, cur->first);
+ bool rc = use_enum->insert_name(cur->first, cur->second);
+ rc &= scope->add_enumeration_name(use_enum, cur->first);
if (! rc) {
cerr << "<>:0: error: Duplicate enumeration name " << cur->first << endl;
des->errors += 1;
View
9 elab_sig.cc
@@ -1098,6 +1098,15 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
: new NetNet(scope, name_, wtype, msb, lsb);
+ // If this is an enumeration, then set the enumeration set for
+ // the new signal. This turns it into an enumeration.
+ if (enum_set_) {
+ ivl_assert(*this, enum_set_->size() > 0);
+ enum_set_m::const_iterator sample_name = enum_set_->begin();
+ netenum_t*use_enum = scope->enumeration_for_name(sample_name->first);
+ sig->set_enumeration(use_enum);
+ }
+
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
ivl_variable_type_t use_data_type = data_type_;
View
6 elaborate.cc
@@ -2271,6 +2271,12 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
rv = cast_to_int2(rv);
}
+ if (lv->enumeration() && (lv->enumeration() != rv->enumeration())) {
+ cerr << get_fileline() << ": error: "
+ << "Enumeration type mismatch in assignment." << endl;
+ des->errors += 1;
+ }
+
NetAssign*cur = new NetAssign(lv, rv);
cur->set_line(*this);
View
19 net_assign.cc
@@ -87,6 +87,25 @@ ivl_variable_type_t NetAssign_::expr_type() const
return sig_->data_type();
}
+netenum_t*NetAssign_::enumeration() const
+{
+ netenum_t*tmp = 0;
+
+ // If the base signal is not an enumeration, return nil.
+ if ( (tmp = sig_->enumeration()) == 0 )
+ return 0;
+
+ // Part select of an enumeration is not an enumeration.
+ if (base_ != 0)
+ return 0;
+
+ // Concatenation of enumerations is not an enumeration.
+ if (more != 0)
+ return 0;
+
+ return tmp;
+}
+
perm_string NetAssign_::name() const
{
if (sig_) {
View
9 net_expr.cc
@@ -31,6 +31,11 @@ ivl_variable_type_t NetExpr::expr_type() const
return IVL_VT_LOGIC;
}
+netenum_t*NetExpr::enumeration() const
+{
+ return 0;
+}
+
/*
* Create an add/sub node from the two operands. Make a best guess of
* the
@@ -432,7 +437,7 @@ unsigned NetEConcat::repeat() const
return repeat_value_;
}
-NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, enum_set_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)
{
}
@@ -441,7 +446,7 @@ NetEConstEnum::~NetEConstEnum()
{
}
-const enum_set_t NetEConstEnum::enumeration() const
+netenum_t*NetEConstEnum::enumeration() const
{
return enum_set_;
}
View
17 net_scope.cc
@@ -21,6 +21,7 @@
# include "compiler.h"
# include "netlist.h"
+# include "netenum.h"
# include <cstring>
# include <cstdlib>
# include <sstream>
@@ -453,15 +454,15 @@ NetNet* NetScope::find_signal(perm_string key)
return 0;
}
-void NetScope::add_enumeration_set(enum_set_t enum_set)
+void NetScope::add_enumeration_set(netenum_t*enum_set)
{
enum_sets_.push_back(enum_set);
}
-bool NetScope::add_enumeration_name(enum_set_t enum_set, perm_string name)
+bool NetScope::add_enumeration_name(netenum_t*enum_set, perm_string name)
{
- enum_set_m::const_iterator enum_val = enum_set->find(name);
- assert(enum_val != enum_set->end());
+ enum_set_m::const_iterator enum_val = enum_set->find_name(name);
+ assert(enum_val != enum_set->end_name());
NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second);
@@ -472,6 +473,14 @@ bool NetScope::add_enumeration_name(enum_set_t enum_set, perm_string name)
return cur.second;
}
+netenum_t*NetScope::enumeration_for_name(perm_string name)
+{
+ NetEConstEnum*tmp = enum_names_[name];
+ assert(tmp != 0);
+
+ return tmp->enumeration();
+}
+
/*
* This method locates a child scope by name. The name is the simple
* name of the child, no hierarchy is searched.
View
45 netenum.cc
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Stephen Williams (steve@icarus.com)
+ *
+ * This source code is free software; you can redistribute it
+ * and/or modify it in source code form under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+# include "netenum.h"
+
+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()
+{
+}
+
+bool netenum_t::insert_name(perm_string name, const verinum&val)
+{
+ names_[name] = verinum(val, msb_-lsb_+1);
+ return true;
+}
+
+netenum_t::iterator netenum_t::find_name(perm_string name) const
+{
+ return names_.find(name);
+}
+
+netenum_t::iterator netenum_t::end_name() const
+{
+ return names_.end();
+}
View
48 netenum.h
@@ -0,0 +1,48 @@
+#ifndef __netenum_H
+#define __netenum_H
+/*
+ * Copyright (c) 2010 Stephen Williams (steve@icarus.com)
+ *
+ * This source code is free software; you can redistribute it
+ * and/or modify it in source code form under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+# include "ivl_target.h"
+# include "verinum.h"
+# include "StringHeap.h"
+# include <map>
+
+class netenum_t {
+
+ public:
+ explicit netenum_t(ivl_variable_type_t base_type, bool signed_flag,
+ long msb, long lsb);
+ ~netenum_t();
+
+ bool insert_name(perm_string name, const verinum&val);
+
+ typedef std::map<perm_string,verinum>::const_iterator iterator;
+ iterator find_name(perm_string name) const;
+ iterator end_name() const;
+
+ private:
+ ivl_variable_type_t base_type_;
+ bool signed_flag_;
+ long msb_, lsb_;
+
+ std::map<perm_string,verinum> names_;
+};
+
+#endif
View
18 netlist.cc
@@ -450,7 +450,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
signed_(false), isint_(false), is_scalar_(false), local_flag_(false),
- discipline_(0), msb_(npins-1), lsb_(0), dimensions_(0),
+ enumeration_(0), discipline_(0), msb_(npins-1), lsb_(0), dimensions_(0),
s0_(0), e0_(0), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -495,7 +495,8 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls)
: NetObj(s, n, 1), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
- isint_(false), is_scalar_(false), local_flag_(false), discipline_(0),
+ isint_(false), is_scalar_(false), local_flag_(false),
+ enumeration_(0), discipline_(0),
msb_(ms), lsb_(ls),
dimensions_(0), s0_(0), e0_(0),
eref_count_(0), lref_count_(0)
@@ -543,7 +544,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
: NetObj(s, n, calculate_count(array_s, array_e)),
type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
- is_scalar_(false), local_flag_(false), discipline_(0),
+ is_scalar_(false), local_flag_(false), enumeration_(0), discipline_(0),
msb_(ms), lsb_(ls),
dimensions_(1), s0_(array_s), e0_(array_e),
eref_count_(0), lref_count_(0)
@@ -684,6 +685,17 @@ void NetNet::set_scalar(bool flag)
is_scalar_ = flag;
}
+netenum_t*NetNet::enumeration(void) const
+{
+ return enumeration_;
+}
+
+void NetNet::set_enumeration(netenum_t*es)
+{
+ ivl_assert(*this, enumeration_ == 0);
+ enumeration_ = es;
+}
+
ivl_discipline_t NetNet::get_discipline() const
{
return discipline_;
View
28 netlist.h
@@ -71,6 +71,7 @@ class NetRamDq;
class NetTaskDef;
class NetEvTrig;
class NetEvWait;
+class netenum_t;
struct target;
struct functor_t;
@@ -596,6 +597,9 @@ class NetNet : public NetObj {
bool get_scalar() const;
void set_scalar(bool);
+ void set_enumeration(netenum_t*enum_set);
+ netenum_t*enumeration(void) const;
+
/* Attach a discipline to the net. */
ivl_discipline_t get_discipline() const;
void set_discipline(ivl_discipline_t dis);
@@ -668,6 +672,7 @@ class NetNet : public NetObj {
bool isint_ : 1; // original type of integer
bool is_scalar_ : 1;
bool local_flag_: 1;
+ netenum_t*enumeration_;
ivl_discipline_t discipline_;
long msb_, lsb_;
@@ -749,8 +754,10 @@ class NetScope : public Attrib {
void rem_signal(NetNet*);
NetNet* find_signal(perm_string name);
- void add_enumeration_set(enum_set_t enum_set);
- bool add_enumeration_name(enum_set_t enum_set, perm_string);
+ void add_enumeration_set(netenum_t*enum_set);
+ bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
+
+ netenum_t* enumeration_for_name(perm_string name);
/* The parent and child() methods allow users of NetScope
objects to locate nearby scopes. */
@@ -931,7 +938,7 @@ class NetScope : public Attrib {
// enumerations present in this scope. The enum_names_ is a
// map of all the enumeration names back to the sets that
// contain them.
- std::list<enum_set_t> enum_sets_;
+ std::list<netenum_t*> enum_sets_;
std::map<perm_string,NetEConstEnum*> enum_names_;
NetScope*up_;
@@ -1633,6 +1640,11 @@ class NetExpr : public LineInfo {
// expressions to check validity.
virtual bool has_width() const;
+ // Return the enumeration set that defines this expressions
+ // enumeration type, or return nil if the expression is not
+ // part of the enumeration.
+ virtual netenum_t*enumeration() const;
+
// Expressions in parameter declarations may have encountered
// arguments that are themselves untyped parameters. These
// cannot be fully resolved for type when elaborated (they are
@@ -1725,12 +1737,12 @@ class NetEConstEnum : public NetEConst {
public:
explicit NetEConstEnum(NetScope*scope, perm_string name,
- enum_set_t enum_set, const verinum&val);
+ netenum_t*enum_set, const verinum&val);
~NetEConstEnum();
perm_string name() const;
const NetScope*scope() const;
- const enum_set_t enumeration() const;
+ netenum_t*enumeration() const;
virtual bool set_width(unsigned w, bool last_chance =false);
virtual void expr_scan(struct expr_scan_t*) const;
@@ -1740,7 +1752,7 @@ class NetEConstEnum : public NetEConst {
private:
NetScope*scope_;
- enum_set_t enum_set_;
+ netenum_t*enum_set_;
perm_string name_;
};
@@ -2289,6 +2301,10 @@ class NetAssign_ {
unsigned lwidth() const;
ivl_variable_type_t expr_type() const;
+ // Return the enumeration type of this l-value, or nil if it's
+ // not an enumeration.
+ netenum_t*enumeration() const;
+
// Get the name of the underlying object.
perm_string name() const;

0 comments on commit 5b5a6b0

Please sign in to comment.
Something went wrong with that request. Please try again.