Handle enumeration literals that are in $root.

This commit is contained in:
Stephen Williams 2013-12-15 23:55:26 +02:00
parent b0491b9c54
commit a3b29dd70b
8 changed files with 139 additions and 56 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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());

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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)