Get the netenum_t base type data from the pform.
The pform propagates the parsed enum base type information to the elaborator so that the base type can be fully elaborated. This is necessary to get the types of the enumeration literals correct.
This commit is contained in:
parent
5b5a6b05b7
commit
cd6c6c7a70
2
PScope.h
2
PScope.h
|
|
@ -100,7 +100,7 @@ class LexicalScope {
|
|||
list<AProcess*> analog_behaviors;
|
||||
|
||||
// Enumeration sets.
|
||||
list<enum_set_t> enum_sets;
|
||||
list<enum_type_t*> enum_sets;
|
||||
|
||||
LexicalScope* parent_scope() const { return parent_; }
|
||||
|
||||
|
|
|
|||
8
PWire.cc
8
PWire.cc
|
|
@ -30,7 +30,7 @@ PWire::PWire(perm_string n,
|
|||
signed_(false), isint_(false),
|
||||
port_msb_(0), port_lsb_(0), port_set_(false),
|
||||
net_msb_(0), net_lsb_(0), net_set_(false), is_scalar_(false),
|
||||
error_cnt_(0), lidx_(0), ridx_(0), enum_set_(0), discipline_(0)
|
||||
error_cnt_(0), lidx_(0), ridx_(0), enum_type_(0), discipline_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
|
|
@ -206,10 +206,10 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
|||
}
|
||||
}
|
||||
|
||||
void PWire::set_enumeration(enum_set_t enum_set)
|
||||
void PWire::set_enumeration(enum_type_t*enum_type)
|
||||
{
|
||||
assert(enum_set_ == 0);
|
||||
enum_set_ = enum_set;
|
||||
assert(enum_type_ == 0);
|
||||
enum_type_ = enum_type;
|
||||
}
|
||||
|
||||
void PWire::set_discipline(ivl_discipline_t d)
|
||||
|
|
|
|||
4
PWire.h
4
PWire.h
|
|
@ -79,7 +79,7 @@ class PWire : public LineInfo {
|
|||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
|
||||
void set_enumeration(enum_set_t enum_set);
|
||||
void set_enumeration(enum_type_t*enum_type);
|
||||
|
||||
void set_discipline(ivl_discipline_t);
|
||||
ivl_discipline_t get_discipline(void) const;
|
||||
|
|
@ -115,7 +115,7 @@ class PWire : public LineInfo {
|
|||
PExpr*lidx_;
|
||||
PExpr*ridx_;
|
||||
|
||||
enum_set_t enum_set_;
|
||||
enum_type_t*enum_type_;
|
||||
|
||||
ivl_discipline_t discipline_;
|
||||
|
||||
|
|
|
|||
|
|
@ -208,29 +208,41 @@ static void elaborate_scope_localparams_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
||||
enum_set_t enum_set)
|
||||
enum_type_t*enum_type)
|
||||
{
|
||||
netenum_t*use_enum = new netenum_t(IVL_VT_BOOL, true, 31, 0);
|
||||
bool rc_flag;
|
||||
assert(enum_type->range->size() == 2);
|
||||
NetExpr*msb_ex = enum_type->range->front()->elaborate_pexpr(des, scope);
|
||||
NetExpr*lsb_ex = enum_type->range->back() ->elaborate_pexpr(des, scope);
|
||||
|
||||
long msb = 0;
|
||||
rc_flag = eval_as_long(msb, msb_ex);
|
||||
assert(rc_flag);
|
||||
long lsb = 0;
|
||||
rc_flag = eval_as_long(lsb, lsb_ex);
|
||||
assert(rc_flag);
|
||||
|
||||
netenum_t*use_enum = new netenum_t(enum_type->base_type, enum_type->signed_flag, msb, lsb);
|
||||
|
||||
scope->add_enumeration_set(use_enum);
|
||||
|
||||
for (map<perm_string,verinum>::const_iterator cur = enum_set->begin()
|
||||
; cur != enum_set->end() ; ++ cur) {
|
||||
for (list<named_number_t>::const_iterator cur = enum_type->names->begin()
|
||||
; cur != enum_type->names->end() ; ++ cur) {
|
||||
|
||||
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;
|
||||
rc_flag = use_enum->insert_name(cur->name, cur->parm);
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
if (! rc_flag) {
|
||||
cerr << "<>:0: error: Duplicate enumeration name " << cur->name << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void elaborate_scope_enumerations(Design*des, NetScope*scope,
|
||||
const list<enum_set_t>&enum_sets)
|
||||
const list<enum_type_t*>&enum_types)
|
||||
{
|
||||
for (list<enum_set_t>::const_iterator cur = enum_sets.begin()
|
||||
; cur != enum_sets.end() ; ++ cur) {
|
||||
for (list<enum_type_t*>::const_iterator cur = enum_types.begin()
|
||||
; cur != enum_types.end() ; ++ cur) {
|
||||
elaborate_scope_enumeration(des, scope, *cur);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1100,10 +1100,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
// 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);
|
||||
if (enum_type_) {
|
||||
ivl_assert(*this, enum_type_->names->size() > 0);
|
||||
list<named_number_t>::const_iterator sample_name = enum_type_->names->begin();
|
||||
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
|
||||
sig->set_enumeration(use_enum);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ unsigned NetEConcat::repeat() const
|
|||
}
|
||||
|
||||
NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, netenum_t*eset, const verinum&v)
|
||||
: NetEConst(v), scope_(s), enum_set_(eset)
|
||||
: NetEConst(v), scope_(s), enum_set_(eset), name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -461,7 +461,7 @@ void NetScope::add_enumeration_set(netenum_t*enum_set)
|
|||
|
||||
bool NetScope::add_enumeration_name(netenum_t*enum_set, perm_string name)
|
||||
{
|
||||
enum_set_m::const_iterator enum_val = enum_set->find_name(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);
|
||||
|
|
|
|||
26
pform.cc
26
pform.cc
|
|
@ -378,7 +378,7 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net)
|
|||
lexical_scope->wires[name] = net;
|
||||
}
|
||||
|
||||
static void pform_put_enum_set_in_scope(enum_set_t enum_set)
|
||||
static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
|
||||
{
|
||||
lexical_scope->enum_sets.push_back(enum_set);
|
||||
}
|
||||
|
|
@ -2462,7 +2462,7 @@ void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>
|
|||
}
|
||||
|
||||
static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
||||
enum_set_t enum_set, perm_string name)
|
||||
perm_string name)
|
||||
{
|
||||
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, enum_type->base_type);
|
||||
assert(cur);
|
||||
|
|
@ -2472,7 +2472,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
|
|||
assert(enum_type->range.get() != 0);
|
||||
assert(enum_type->range->size() == 2);
|
||||
cur->set_range(enum_type->range->front(), enum_type->range->back(), SR_NET, false);
|
||||
cur->set_enumeration(enum_set);
|
||||
cur->set_enumeration(enum_type);
|
||||
}
|
||||
|
||||
void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names)
|
||||
|
|
@ -2487,7 +2487,6 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
|
|||
// Scan the list of enum name declarations and evaluate them
|
||||
// to a map of names with values. This expands out the
|
||||
// inferred values (if any) and checks for duplicates.
|
||||
enum_set_t enum_map = new enum_set_m;
|
||||
verinum cur_value (0);
|
||||
verinum one_value (1);
|
||||
for (list<named_number_t>::iterator cur = enum_type->names->begin()
|
||||
|
|
@ -2505,6 +2504,9 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
|
|||
next_value = cur_value;
|
||||
cur_value = cur_value + one_value;
|
||||
}
|
||||
|
||||
cur->parm - next_value;
|
||||
|
||||
} else {
|
||||
if (enum_type->base_type==IVL_VT_BOOL && ! next_value.is_defined()) {
|
||||
cerr << li.text << ":" << li.first_line << ": "
|
||||
|
|
@ -2514,32 +2516,20 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
|
|||
}
|
||||
cur_value = next_value + one_value;
|
||||
}
|
||||
|
||||
map<perm_string,verinum>::iterator map_name = enum_map->find(cur->name);
|
||||
if (map_name == enum_map->end()) {
|
||||
enum_map->insert(make_pair(cur->name, next_value));;
|
||||
|
||||
} else {
|
||||
cerr << li.text << ":" << li.first_line << ": "
|
||||
<< "error: Enumeration name " << cur->name
|
||||
<< " is already defined." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Attach the enumeration to the current scope.
|
||||
pform_put_enum_set_in_scope(enum_map);
|
||||
pform_put_enum_type_in_scope(enum_type);
|
||||
|
||||
// Now apply the checked enumeration type to the variables
|
||||
// that are being declared with this type.
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_enum(li, enum_type, enum_map, txt);
|
||||
pform_set_enum(li, enum_type, txt);
|
||||
}
|
||||
|
||||
delete names;
|
||||
delete enum_type;
|
||||
}
|
||||
|
||||
svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||
|
|
|
|||
9
pform.h
9
pform.h
|
|
@ -86,8 +86,6 @@ extern bool pform_library_flag;
|
|||
|
||||
typedef named<PExpr*> named_pexpr_t;
|
||||
|
||||
typedef named<verinum> named_number_t;
|
||||
|
||||
struct parmvalue_t {
|
||||
list<PExpr*>*by_order;
|
||||
svector<named_pexpr_t*>*by_name;
|
||||
|
|
@ -102,13 +100,6 @@ struct net_decl_assign_t {
|
|||
struct net_decl_assign_t*next;
|
||||
};
|
||||
|
||||
struct enum_type_t {
|
||||
ivl_variable_type_t base_type;
|
||||
bool signed_flag;
|
||||
auto_ptr< list<PExpr*> > range;
|
||||
auto_ptr< list<named_number_t> > names;
|
||||
};
|
||||
|
||||
/* The lgate is gate instantiation information. */
|
||||
struct lgate {
|
||||
lgate(int =0)
|
||||
|
|
|
|||
|
|
@ -1108,14 +1108,14 @@ void LexicalScope::dump_localparams_(ostream&out, unsigned indent) const
|
|||
|
||||
void LexicalScope::dump_enumerations_(ostream&out, unsigned indent) const
|
||||
{
|
||||
for (list<enum_set_t>::const_iterator cur = enum_sets.begin()
|
||||
for (list<enum_type_t*>::const_iterator cur = enum_sets.begin()
|
||||
; cur != enum_sets.end() ; ++ cur) {
|
||||
out << setw(indent) << "" << "enum {" << endl;
|
||||
|
||||
for (map<perm_string,verinum>::const_iterator idx = (*cur)->begin()
|
||||
; idx != (*cur)->end() ; ++ idx) {
|
||||
out << setw(indent+4) << "" << idx->first
|
||||
<< " = " << idx->second << endl;
|
||||
for (list<named_number_t>::const_iterator idx = (*cur)->names->begin()
|
||||
; idx != (*cur)->names->end() ; ++ idx) {
|
||||
out << setw(indent+4) << "" << idx->name
|
||||
<< " = " << idx->parm << endl;
|
||||
}
|
||||
|
||||
out << setw(indent) << "" << "}" << endl;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
// This for the perm_string type.
|
||||
# include "StringHeap.h"
|
||||
# include "verinum.h"
|
||||
# include "named.h"
|
||||
# include "ivl_target.h"
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
# include <map>
|
||||
|
|
@ -30,6 +32,8 @@
|
|||
* parse-form types.
|
||||
*/
|
||||
|
||||
typedef named<verinum> named_number_t;
|
||||
|
||||
struct index_component_t {
|
||||
enum ctype_t { SEL_NONE, SEL_BIT, SEL_PART, SEL_IDX_UP, SEL_IDX_DO };
|
||||
|
||||
|
|
@ -50,11 +54,17 @@ struct name_component_t {
|
|||
};
|
||||
|
||||
/*
|
||||
* The enum_map_t holds the values that represent the enumeration. An
|
||||
* enumeration, then, is defined by its pointer to the set.
|
||||
* The enum_type_t holds the parsed declaration to represent an
|
||||
* enumeration. Since this is in the pform, it represents the type
|
||||
* before elaboration to the range, for example, man not be complete
|
||||
* until it is elaborated in a scope.
|
||||
*/
|
||||
typedef map<perm_string,verinum> enum_set_m;
|
||||
typedef enum_set_m *enum_set_t;
|
||||
struct enum_type_t {
|
||||
ivl_variable_type_t base_type;
|
||||
bool signed_flag;
|
||||
auto_ptr< list<PExpr*> > range;
|
||||
auto_ptr< list<named_number_t> > names;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue