Handle enumeration literals that are in $root.
This commit is contained in:
parent
b0491b9c54
commit
a3b29dd70b
|
|
@ -48,6 +48,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
# include "parse_api.h"
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
|
|
@ -156,6 +157,10 @@ static void collect_scope_specparams_(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the enumeration into the given scope. If scope==0, then
|
||||
* the enumeration goes into $root instead of a scope.
|
||||
*/
|
||||
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
enum_type_t*enum_type)
|
||||
{
|
||||
|
|
@ -176,7 +181,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
msb, lsb, enum_type->names->size());
|
||||
|
||||
use_enum->set_line(enum_type->li);
|
||||
scope->add_enumeration_set(use_enum);
|
||||
if (scope)
|
||||
scope->add_enumeration_set(use_enum);
|
||||
else
|
||||
des->add_enumeration_set(use_enum);
|
||||
|
||||
ivl_assert(*enum_type, enum_type->net_type == 0);
|
||||
enum_type->net_type = use_enum;
|
||||
|
|
@ -270,7 +278,11 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
tmp_val.has_sign(enum_type->signed_flag);
|
||||
|
||||
rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val);
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
if (scope)
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
else
|
||||
rc_flag &= des->add_enumeration_name(use_enum, cur->name);
|
||||
|
||||
if (! rc_flag) {
|
||||
cerr << use_enum->get_fileline()
|
||||
<< ": error: Duplicate enumeration name "
|
||||
|
|
@ -297,6 +309,15 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
void elaborate_rootscope_enumerations(Design*des)
|
||||
{
|
||||
for (set<enum_type_t*>::const_iterator cur = pform_enum_sets.begin()
|
||||
; cur != pform_enum_sets.end() ; ++ cur) {
|
||||
enum_type_t*curp = *cur;
|
||||
elaborate_scope_enumeration(des, 0, curp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the pclass includes an implicit and explicit constructor, then
|
||||
* merge the implicit constructor into the explicit constructor as
|
||||
|
|
|
|||
|
|
@ -965,7 +965,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
<< "'." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
// A signal can not have the same name as a parameter.
|
||||
// A signal can not have the same name as a parameter. Note
|
||||
// that we treat enumeration literals similar to parameters,
|
||||
// so if the name matches an enumeration literal, it will be
|
||||
// caught here.
|
||||
const NetExpr *ex_msb, *ex_lsb;
|
||||
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
|
||||
if (parm) {
|
||||
|
|
|
|||
|
|
@ -5663,6 +5663,9 @@ Design* elaborate(list<perm_string>roots)
|
|||
// module and elaborate what I find.
|
||||
Design*des = new Design;
|
||||
|
||||
// Elaborate enum sets in $root scope.
|
||||
elaborate_rootscope_enumerations(des);
|
||||
|
||||
// Elaborate the packages. Package elaboration is simpler
|
||||
// because there are fewer sub-scopes involved.
|
||||
i = 0;
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ void NetEConcat::set(unsigned idx, NetExpr*e)
|
|||
expr_width( expr_width() + repeat_ * e->expr_width() );
|
||||
}
|
||||
|
||||
NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, const netenum_t*eset, const verinum&v)
|
||||
NetEConstEnum::NetEConstEnum(Definitions*s, perm_string n, const netenum_t*eset, const verinum&v)
|
||||
: NetEConst(v), scope_(s), enum_set_(eset), name_(n)
|
||||
{
|
||||
assert(has_width());
|
||||
|
|
|
|||
93
net_scope.cc
93
net_scope.cc
|
|
@ -30,6 +30,59 @@
|
|||
|
||||
class PExpr;
|
||||
|
||||
Definitions::Definitions()
|
||||
{
|
||||
}
|
||||
|
||||
Definitions::~Definitions()
|
||||
{
|
||||
}
|
||||
|
||||
void Definitions::add_enumeration_set(netenum_t*enum_set)
|
||||
{
|
||||
enum_sets_.push_back(enum_set);
|
||||
}
|
||||
|
||||
bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name)
|
||||
{
|
||||
netenum_t::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);
|
||||
|
||||
pair<map<perm_string,NetEConstEnum*>::iterator, bool> cur;
|
||||
cur = enum_names_.insert(make_pair(name,val));
|
||||
|
||||
// Return TRUE if the name is added (i.e. is NOT a duplicate.)
|
||||
return cur.second;
|
||||
}
|
||||
|
||||
/*
|
||||
* This locates the enumeration TYPE for the given enumeration literal.
|
||||
*/
|
||||
const netenum_t*Definitions::enumeration_for_name(perm_string name)
|
||||
{
|
||||
NetEConstEnum*tmp = enum_names_[name];
|
||||
assert(tmp != 0);
|
||||
|
||||
return tmp->enumeration();
|
||||
}
|
||||
|
||||
/*
|
||||
* This locates the VALUE for the given enumeration literal.
|
||||
*/
|
||||
const NetExpr* Definitions::enumeration_expr(perm_string key)
|
||||
{
|
||||
map<perm_string,NetEConstEnum*>::const_iterator eidx;
|
||||
|
||||
eidx = enum_names_.find(key);
|
||||
if (eidx != enum_names_.end()) {
|
||||
return eidx->second;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetScope class keeps a scope tree organized. Each node of the
|
||||
* scope tree points to its parent, its right sibling and its leftmost
|
||||
|
|
@ -265,14 +318,13 @@ const NetExpr* NetScope::get_parameter(Design*des,
|
|||
return idx->second.val;
|
||||
}
|
||||
|
||||
map<perm_string,NetEConstEnum*>::const_iterator eidx;
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
const NetExpr*tmp = enumeration_expr(key);
|
||||
if (tmp) return tmp;
|
||||
|
||||
eidx = enum_names_.find(key);
|
||||
if (eidx != enum_names_.end()) {
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
return eidx->second;
|
||||
}
|
||||
tmp = des->enumeration_expr(key);
|
||||
if (tmp) return tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -551,33 +603,6 @@ NetNet* NetScope::find_signal(perm_string key)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_enumeration_set(netenum_t*enum_set)
|
||||
{
|
||||
enum_sets_.push_back(enum_set);
|
||||
}
|
||||
|
||||
bool NetScope::add_enumeration_name(netenum_t*enum_set, perm_string name)
|
||||
{
|
||||
netenum_t::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);
|
||||
|
||||
pair<map<perm_string,NetEConstEnum*>::iterator, bool> cur;
|
||||
cur = enum_names_.insert(make_pair(name,val));
|
||||
|
||||
// Return TRUE if the name is added (i.e. is NOT a duplicate.)
|
||||
return cur.second;
|
||||
}
|
||||
|
||||
const netenum_t*NetScope::enumeration_for_name(perm_string name)
|
||||
{
|
||||
NetEConstEnum*tmp = enum_names_[name];
|
||||
assert(tmp != 0);
|
||||
|
||||
return tmp->enumeration();
|
||||
}
|
||||
|
||||
void NetScope::add_class(netclass_t*net_class)
|
||||
{
|
||||
classes_[net_class->get_name()] = net_class;
|
||||
|
|
|
|||
53
netlist.h
53
netlist.h
|
|
@ -819,12 +819,44 @@ class NetBaseDef {
|
|||
NetProc*proc_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Some definitions (and methods to manipulate them) are common to a
|
||||
* couple of types. Keep them here.
|
||||
*/
|
||||
class Definitions {
|
||||
|
||||
public:
|
||||
Definitions();
|
||||
~Definitions();
|
||||
|
||||
void add_enumeration_set(netenum_t*enum_set);
|
||||
bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
|
||||
|
||||
// Look up the enumeration literal in this scope. if the name
|
||||
// is present, then return the enumeration type that declares it.
|
||||
const netenum_t* enumeration_for_name(perm_string name);
|
||||
|
||||
// Look up an enumeration literal in this scope. If the
|
||||
// literal is present, return the expression that defines its
|
||||
// value.
|
||||
const NetExpr* enumeration_expr(perm_string key);
|
||||
|
||||
protected:
|
||||
// Enumerations. The enum_sets_ is a list of all the
|
||||
// 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<netenum_t*> enum_sets_;
|
||||
std::map<perm_string,NetEConstEnum*> enum_names_;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* This object type is used to contain a logical scope within a
|
||||
* design. The scope doesn't represent any executable hardware, but is
|
||||
* just a handle that netlist processors can use to grab at the design.
|
||||
*/
|
||||
class NetScope : public Attrib {
|
||||
class NetScope : public Definitions, public Attrib {
|
||||
|
||||
public:
|
||||
enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE };
|
||||
|
|
@ -897,11 +929,6 @@ class NetScope : public Attrib {
|
|||
void rem_signal(NetNet*);
|
||||
NetNet* find_signal(perm_string name);
|
||||
|
||||
void add_enumeration_set(netenum_t*enum_set);
|
||||
bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
|
||||
|
||||
const netenum_t* enumeration_for_name(perm_string name);
|
||||
|
||||
void add_class(netclass_t*class_type);
|
||||
netclass_t* find_class(perm_string name);
|
||||
|
||||
|
|
@ -1153,13 +1180,6 @@ class NetScope : public Attrib {
|
|||
const PFunction*func_pform_;
|
||||
unsigned elab_stage_;
|
||||
|
||||
// Enumerations. The enum_sets_ is a list of all the
|
||||
// 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<netenum_t*> enum_sets_;
|
||||
std::map<perm_string,NetEConstEnum*> enum_names_;
|
||||
|
||||
std::map<perm_string,netclass_t*> classes_;
|
||||
|
||||
NetScope*up_;
|
||||
|
|
@ -1973,12 +1993,11 @@ class NetEConst : public NetExpr {
|
|||
class NetEConstEnum : public NetEConst {
|
||||
|
||||
public:
|
||||
explicit NetEConstEnum(NetScope*scope, perm_string name,
|
||||
explicit NetEConstEnum(Definitions*scope, perm_string name,
|
||||
const netenum_t*enum_set, const verinum&val);
|
||||
~NetEConstEnum();
|
||||
|
||||
perm_string name() const;
|
||||
const NetScope*scope() const;
|
||||
const netenum_t*enumeration() const;
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
|
|
@ -1987,7 +2006,7 @@ class NetEConstEnum : public NetEConst {
|
|||
virtual NetEConstEnum* dup_expr() const;
|
||||
|
||||
private:
|
||||
NetScope*scope_;
|
||||
Definitions*scope_;
|
||||
const netenum_t*enum_set_;
|
||||
perm_string name_;
|
||||
};
|
||||
|
|
@ -4499,7 +4518,7 @@ struct elaborator_work_item_t {
|
|||
* This class contains an entire design. It includes processes and a
|
||||
* netlist, and can be passed around from function to function.
|
||||
*/
|
||||
class Design {
|
||||
class Design : public Definitions {
|
||||
|
||||
public:
|
||||
Design();
|
||||
|
|
|
|||
|
|
@ -24,11 +24,14 @@
|
|||
# include <string>
|
||||
# include <ostream>
|
||||
# include <map>
|
||||
# include <set>
|
||||
|
||||
class Design;
|
||||
class Module;
|
||||
class PPackage;
|
||||
class PUdp;
|
||||
class data_type_t;
|
||||
class enum_type_t;
|
||||
|
||||
/*
|
||||
* These are maps of the modules and primitives parsed from the
|
||||
|
|
@ -38,10 +41,13 @@ class data_type_t;
|
|||
extern std::map<perm_string,Module*> pform_modules;
|
||||
extern std::map<perm_string,PUdp*> pform_primitives;
|
||||
extern std::map<perm_string,data_type_t*> pform_typedefs;
|
||||
extern std::set<enum_type_t*> pform_enum_sets;
|
||||
|
||||
extern std::map<perm_string,PPackage*> pform_packages;
|
||||
extern void pform_dump(std::ostream&out, const PPackage*pac);
|
||||
|
||||
extern void elaborate_rootscope_enumerations(Design*des);
|
||||
|
||||
/*
|
||||
* This code actually invokes the parser to make modules. The first
|
||||
* parameter is the name of the file that is to be parsed. The
|
||||
|
|
|
|||
8
pform.cc
8
pform.cc
|
|
@ -55,6 +55,7 @@ map<perm_string,PUdp*> pform_primitives;
|
|||
* typedefs in the $root scope go here.
|
||||
*/
|
||||
map<perm_string,data_type_t*>pform_typedefs;
|
||||
set<enum_type_t*>pform_enum_sets;
|
||||
|
||||
std::string vlltype::get_fileline() const
|
||||
{
|
||||
|
|
@ -487,7 +488,12 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net)
|
|||
|
||||
static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
|
||||
{
|
||||
lexical_scope->enum_sets.insert(enum_set);
|
||||
if (lexical_scope) {
|
||||
ivl_assert(*enum_set, lexical_scope);
|
||||
lexical_scope->enum_sets.insert(enum_set);
|
||||
} else {
|
||||
pform_enum_sets.insert(enum_set);
|
||||
}
|
||||
}
|
||||
|
||||
PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type)
|
||||
|
|
|
|||
Loading…
Reference in New Issue