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.
This commit is contained in:
parent
94acc39b55
commit
5b5a6b05b7
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_) {
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
|||
17
net_scope.cc
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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
18
netlist.cc
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_;
|
||||
|
|
|
|||
28
netlist.h
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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue