vhdlpp: Support for ExpNames with multiple indices.
This commit is contained in:
parent
34b5834a84
commit
5488ea1e2c
|
|
@ -395,10 +395,13 @@ void ExpName::dump(ostream&out, int indent) const
|
|||
<< " at " << get_fileline() << endl;
|
||||
if (prefix_.get())
|
||||
prefix_->dump(out, indent+8);
|
||||
if (index_)
|
||||
index_->dump(out, indent+6);
|
||||
if (lsb_)
|
||||
lsb_->dump(out, indent+6);
|
||||
|
||||
if (indices_) {
|
||||
for(list<Expression*>::const_iterator it = indices_->begin();
|
||||
it != indices_->end(); ++it) {
|
||||
(*it)->dump(out, indent+6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExpNameALL::dump(ostream&out, int indent) const
|
||||
|
|
|
|||
|
|
@ -578,41 +578,54 @@ ExpLogical::~ExpLogical()
|
|||
}
|
||||
|
||||
ExpName::ExpName(perm_string nn)
|
||||
: name_(nn), index_(0), lsb_(0)
|
||||
: name_(nn), indices_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
ExpName::ExpName(perm_string nn, list<Expression*>*indices)
|
||||
: name_(nn), index_(0), lsb_(0)
|
||||
{
|
||||
/* For now, assume a single index. */
|
||||
ivl_assert(*this, indices->size() == 1);
|
||||
|
||||
index_ = indices->front();
|
||||
indices->pop_front();
|
||||
}
|
||||
|
||||
ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb)
|
||||
: name_(nn), index_(msb), lsb_(lsb)
|
||||
{
|
||||
ivl_assert(*this, !msb || msb != lsb);
|
||||
}
|
||||
|
||||
ExpName::ExpName(ExpName*prefix, perm_string nn)
|
||||
: prefix_(prefix), name_(nn), index_(0), lsb_(0)
|
||||
: name_(nn), indices_(indices)
|
||||
{
|
||||
}
|
||||
|
||||
ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb)
|
||||
: prefix_(prefix), name_(nn), index_(msb), lsb_(lsb)
|
||||
ExpName::ExpName(ExpName*prefix, perm_string nn, std::list<Expression*>*indices)
|
||||
: prefix_(prefix), name_(nn), indices_(indices)
|
||||
{
|
||||
ivl_assert(*this, !msb || msb != lsb);
|
||||
}
|
||||
|
||||
ExpName::~ExpName()
|
||||
{
|
||||
delete index_;
|
||||
delete lsb_;
|
||||
if(indices_) {
|
||||
for(list<Expression*>::iterator it = indices_->begin();
|
||||
it != indices_->end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
|
||||
delete indices_;
|
||||
}
|
||||
}
|
||||
|
||||
Expression*ExpName::clone() const {
|
||||
list<Expression*>*new_indices = NULL;
|
||||
|
||||
if(indices_) {
|
||||
new_indices = new list<Expression*>();
|
||||
|
||||
for(list<Expression*>::const_iterator it = indices_->begin();
|
||||
it != indices_->end(); ++it) {
|
||||
new_indices->push_back((*it)->clone());
|
||||
}
|
||||
}
|
||||
|
||||
return new ExpName(static_cast<ExpName*>(safe_clone(prefix_.get())),
|
||||
name_, new_indices);
|
||||
}
|
||||
|
||||
void ExpName::add_index(std::list<Expression*>*idx)
|
||||
{
|
||||
if(!indices_)
|
||||
indices_ = new list<Expression*>();
|
||||
|
||||
indices_->splice(indices_->end(), *idx);
|
||||
}
|
||||
|
||||
bool ExpName::symbolic_compare(const Expression*that) const
|
||||
|
|
@ -624,25 +637,48 @@ bool ExpName::symbolic_compare(const Expression*that) const
|
|||
if (name_ != that_name->name_)
|
||||
return false;
|
||||
|
||||
if (that_name->index_ && !index_)
|
||||
if (that_name->indices_ && !indices_)
|
||||
return false;
|
||||
if (index_ && !that_name->index_)
|
||||
if (indices_ && !that_name->indices_)
|
||||
return false;
|
||||
|
||||
if (index_) {
|
||||
assert(that_name->index_);
|
||||
return index_->symbolic_compare(that_name->index_);
|
||||
if (indices_) {
|
||||
assert(that_name->indices_);
|
||||
|
||||
if(indices_->size() != that_name->indices_->size())
|
||||
return false;
|
||||
|
||||
list<Expression*>::const_iterator it, jt;
|
||||
it = indices_->begin();
|
||||
jt = that_name->indices_->begin();
|
||||
|
||||
for(unsigned int i = 0; i < indices_->size(); ++i) {
|
||||
if(!(*it)->symbolic_compare(*jt))
|
||||
return false;
|
||||
|
||||
++it;
|
||||
++jt;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExpName::set_range(Expression*msb, Expression*lsb)
|
||||
Expression*ExpName::index(unsigned int number) const
|
||||
{
|
||||
assert(index_==0);
|
||||
index_ = msb;
|
||||
assert(lsb_==0);
|
||||
lsb_ = lsb;
|
||||
if(!indices_)
|
||||
return NULL;
|
||||
|
||||
if(number >= indices_->size())
|
||||
return NULL;
|
||||
|
||||
if(number == 0)
|
||||
return indices_->front();
|
||||
|
||||
list<Expression*>::const_iterator it = indices_->begin();
|
||||
advance(it, number);
|
||||
|
||||
return *it;
|
||||
}
|
||||
|
||||
void ExpName::visit(ExprVisitor& func)
|
||||
|
|
@ -650,11 +686,12 @@ void ExpName::visit(ExprVisitor& func)
|
|||
if(prefix_.get())
|
||||
prefix_.get()->visit(func);
|
||||
|
||||
if(index_)
|
||||
index_->visit(func);
|
||||
|
||||
if(lsb_)
|
||||
lsb_->visit(func);
|
||||
if(indices_) {
|
||||
for(list<Expression*>::const_iterator it = indices_->begin();
|
||||
it != indices_->end(); ++it) {
|
||||
(*it)->visit(func);
|
||||
}
|
||||
}
|
||||
|
||||
func(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -690,22 +690,18 @@ class ExpName : public Expression {
|
|||
public:
|
||||
explicit ExpName(perm_string nn);
|
||||
ExpName(perm_string nn, std::list<Expression*>*indices);
|
||||
ExpName(perm_string nn, Expression*msb, Expression*lsb);
|
||||
ExpName(ExpName*prefix, perm_string nn);
|
||||
ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb);
|
||||
ExpName(ExpName*prefix, perm_string nn, std::list<Expression*>*indices = NULL);
|
||||
~ExpName();
|
||||
|
||||
public: // Base methods
|
||||
Expression*clone() const {
|
||||
return new ExpName(static_cast<ExpName*>(safe_clone(prefix_.get())),
|
||||
name_, safe_clone(index_), safe_clone(lsb_));
|
||||
}
|
||||
Expression*clone() const;
|
||||
int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
|
||||
int elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*);
|
||||
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
|
||||
const VType* fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*host) const;
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit_indices(ostream&out, Entity*ent, ScopeBase*scope) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope) const;
|
||||
bool is_primary(void) const;
|
||||
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
|
||||
|
|
@ -713,7 +709,7 @@ class ExpName : public Expression {
|
|||
void dump(ostream&out, int indent = 0) const;
|
||||
inline const char* name() const { return name_; }
|
||||
inline const perm_string& peek_name() const { return name_; }
|
||||
void set_range(Expression*msb, Expression*lsb);
|
||||
void add_index(std::list<Expression*>*idx);
|
||||
void visit(ExprVisitor& func);
|
||||
|
||||
private:
|
||||
|
|
@ -760,10 +756,11 @@ class ExpName : public Expression {
|
|||
const list<index_t*>&indices, int field_size) const;
|
||||
|
||||
private:
|
||||
Expression*index(unsigned int number) const;
|
||||
|
||||
std::auto_ptr<ExpName> prefix_;
|
||||
perm_string name_;
|
||||
Expression*index_;
|
||||
Expression*lsb_;
|
||||
std::list<Expression*>*indices_;
|
||||
};
|
||||
|
||||
class ExpNameALL : public ExpName {
|
||||
|
|
|
|||
|
|
@ -68,24 +68,26 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*sco
|
|||
}
|
||||
|
||||
if (const VTypeArray*array = dynamic_cast<const VTypeArray*>(type)) {
|
||||
if (index_ && !lsb_) {
|
||||
// If the name is an array or a vector, then an
|
||||
// indexed name has the type of the element.
|
||||
type = array->element_type();
|
||||
Expression*idx = index(0);
|
||||
|
||||
} else if (index_ && lsb_) {
|
||||
if (ExpRange*range = dynamic_cast<ExpRange*>(idx)) {
|
||||
// If the name is an array, then a part select is
|
||||
// also an array, but with different bounds.
|
||||
int64_t use_msb, use_lsb;
|
||||
bool flag;
|
||||
|
||||
flag = index_->evaluate(ent, scope, use_msb);
|
||||
flag = range->msb()->evaluate(ent, scope, use_msb);
|
||||
ivl_assert(*this, flag);
|
||||
flag = lsb_->evaluate(ent, scope, use_lsb);
|
||||
flag = range->lsb()->evaluate(ent, scope, use_lsb);
|
||||
ivl_assert(*this, flag);
|
||||
|
||||
type = new VTypeArray(array->element_type(), use_msb, use_lsb);
|
||||
}
|
||||
else if(idx) {
|
||||
// If the name is an array or a vector, then an
|
||||
// indexed name has the type of the element.
|
||||
type = array->element_type();
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
|
|
@ -99,10 +101,14 @@ int ExpName::elaborate_lval_(Entity*ent, ScopeBase*scope, bool is_sequ, ExpName*
|
|||
debug_log_file << get_fileline() << ": ExpName::elaborate_lval_: "
|
||||
<< "name_=" << name_
|
||||
<< ", suffix->name()=" << suffix->name();
|
||||
if (index_)
|
||||
debug_log_file << ", index_=" << *index_;
|
||||
if (lsb_)
|
||||
debug_log_file << ", lsb_=" << *lsb_;
|
||||
if (indices_) {
|
||||
for(list<Expression*>::const_iterator it = indices_->begin();
|
||||
it != indices_->end(); ++it) {
|
||||
debug_log_file << "[";
|
||||
debug_log_file << **it;
|
||||
debug_log_file << "]";
|
||||
}
|
||||
}
|
||||
debug_log_file << endl;
|
||||
}
|
||||
|
||||
|
|
@ -1032,11 +1038,12 @@ int ExpName::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
|
|||
if(prefix_.get())
|
||||
prefix_.get()->elaborate_expr(ent, scope, NULL);
|
||||
|
||||
if(index_)
|
||||
index_->elaborate_expr(ent, scope, &primitive_INTEGER);
|
||||
|
||||
if(lsb_)
|
||||
lsb_->elaborate_expr(ent, scope, &primitive_INTEGER);
|
||||
if (indices_) {
|
||||
for(list<Expression*>::const_iterator it = indices_->begin();
|
||||
it != indices_->end(); ++it) {
|
||||
(*it)->elaborate_expr(ent, scope, &primitive_INTEGER);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -694,6 +694,22 @@ int ExpLogical::emit(ostream&out, Entity*ent, ScopeBase*scope) const
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::emit_indices(ostream&out, Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (indices_) {
|
||||
for(list<Expression*>::const_iterator it = indices_->begin();
|
||||
it != indices_->end(); ++it) {
|
||||
out << "[";
|
||||
errors += (*it)->emit(out, ent, scope);
|
||||
out << "]";
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
int errors = 0;
|
||||
|
|
@ -702,12 +718,7 @@ int ExpName::emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope) const
|
|||
}
|
||||
|
||||
out << "\\" << name_ << " ";
|
||||
if (index_) {
|
||||
out << "[";
|
||||
errors += index_->emit(out, ent, scope);
|
||||
out << "]";
|
||||
ivl_assert(*this, lsb_ == 0);
|
||||
}
|
||||
errors += emit_indices(out, ent, scope);
|
||||
out << ".";
|
||||
return errors;
|
||||
}
|
||||
|
|
@ -739,16 +750,7 @@ int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope) const
|
|||
else
|
||||
out << "\\" << name_ << " ";
|
||||
|
||||
if (index_) {
|
||||
out << "[";
|
||||
errors += index_->emit(out, ent, scope);
|
||||
|
||||
if (lsb_) {
|
||||
out << ":";
|
||||
errors += lsb_->emit(out, ent, scope);
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
errors += emit_indices(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
|
@ -759,6 +761,8 @@ bool ExpName::try_workarounds_(ostream&out, Entity*ent, ScopeBase*scope,
|
|||
Expression*exp = NULL;
|
||||
bool wrkand_required = false;
|
||||
const VType*type = NULL;
|
||||
Expression*idx = index(0);
|
||||
ExpRange*range = dynamic_cast<ExpRange*>(idx);
|
||||
|
||||
if(!scope)
|
||||
return false;
|
||||
|
|
@ -766,7 +770,7 @@ bool ExpName::try_workarounds_(ostream&out, Entity*ent, ScopeBase*scope,
|
|||
if(prefix_.get())
|
||||
prefix_->try_workarounds_(out, ent, scope, indices, data_size);
|
||||
|
||||
if(index_ && !lsb_ && scope->find_constant(name_, type, exp)) {
|
||||
if(idx && !range && scope->find_constant(name_, type, exp)) {
|
||||
while(const VTypeDef*type_def = dynamic_cast<const VTypeDef*>(type)) {
|
||||
type = type_def->peek_definition();
|
||||
}
|
||||
|
|
@ -778,7 +782,7 @@ bool ExpName::try_workarounds_(ostream&out, Entity*ent, ScopeBase*scope,
|
|||
|
||||
if(prefix_.get() && scope->find_constant(prefix_->name_, type, exp)) {
|
||||
// Handle the case of array of records
|
||||
if(prefix_->index_) {
|
||||
if(prefix_->index(0)) {
|
||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
|
||||
assert(arr);
|
||||
type = arr->element_type();
|
||||
|
|
@ -795,17 +799,23 @@ bool ExpName::try_workarounds_(ostream&out, Entity*ent, ScopeBase*scope,
|
|||
wrkand_required |= check_const_record_workaround_(rec, scope, indices, data_size);
|
||||
}
|
||||
|
||||
// Workarounds are currently implemented only for one-dimensional arrays
|
||||
assert(!indices_ || indices_->size() == 1 || !wrkand_required);
|
||||
|
||||
return wrkand_required;
|
||||
}
|
||||
|
||||
bool ExpName::check_const_array_workaround_(const VTypeArray*arr,
|
||||
ScopeBase*scope, list<index_t*>&indices, int&data_size) const
|
||||
{
|
||||
assert(indices_ && indices_->size() == 1);
|
||||
|
||||
const VType*element = arr->element_type();
|
||||
data_size = element->get_width(scope);
|
||||
if(data_size < 0)
|
||||
return false;
|
||||
indices.push_back(new index_t(index_->clone(), new ExpInteger(data_size)));
|
||||
|
||||
indices.push_back(new index_t(index(0)->clone(), new ExpInteger(data_size)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -830,7 +840,7 @@ bool ExpName::check_const_record_workaround_(const VTypeRecord*rec,
|
|||
data_size = tmp_field;
|
||||
indices.push_back(new index_t(NULL, NULL, new ExpInteger(tmp_offset)));
|
||||
|
||||
if(index_) {
|
||||
if(index(0)) {
|
||||
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
|
||||
assert(arr);
|
||||
return check_const_array_workaround_(arr, scope, indices, data_size);
|
||||
|
|
|
|||
|
|
@ -217,14 +217,20 @@ void ExpName::write_to_stream(ostream&fd) const
|
|||
}
|
||||
|
||||
fd << name_;
|
||||
if (index_) {
|
||||
fd << "(";
|
||||
index_->write_to_stream(fd);
|
||||
if (lsb_) {
|
||||
fd << " downto ";
|
||||
lsb_->write_to_stream(fd);
|
||||
}
|
||||
fd << ")";
|
||||
|
||||
if (indices_) {
|
||||
fd << "(";
|
||||
bool first = true;
|
||||
for(list<Expression*>::const_iterator it = indices_->begin();
|
||||
it != indices_->end(); ++it) {
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
fd << ",";
|
||||
|
||||
(*it)->write_to_stream(fd);
|
||||
}
|
||||
fd << ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
%type <expr> expression factor primary relation
|
||||
%type <expr> expression_logical expression_logical_and expression_logical_or
|
||||
%type <expr> expression_logical_xnor expression_logical_xor
|
||||
%type <expr> name prefix selected_name
|
||||
%type <expr> name prefix selected_name indexed_name
|
||||
%type <expr> shift_expression signal_declaration_assign_opt
|
||||
%type <expr> simple_expression simple_expression_2 term
|
||||
%type <expr> variable_declaration_assign_opt waveform_element interface_element_expression
|
||||
|
|
@ -1715,36 +1715,40 @@ name /* IEEE 1076-2008 P8.1 */
|
|||
| selected_name
|
||||
{ $$ = $1; }
|
||||
|
||||
| indexed_name
|
||||
{ $$ = $1; }
|
||||
|
||||
|
||||
| selected_name '(' expression_list ')'
|
||||
{
|
||||
ExpName*name = dynamic_cast<ExpName*>($1);
|
||||
assert(name);
|
||||
name->add_index($3);
|
||||
delete $3; // contents of the list is moved to the selected_name
|
||||
}
|
||||
;
|
||||
|
||||
indexed_name
|
||||
/* Note that this rule can match array element selects and various
|
||||
function calls. The only way we can tell the difference is from
|
||||
left context, namely whether the name is a type name or function
|
||||
name. If none of the above, treat it as a array element select. */
|
||||
| IDENTIFIER argument_list
|
||||
: IDENTIFIER '(' expression_list ')'
|
||||
{ Expression*tmp;
|
||||
perm_string name = lex_strings.make($1);
|
||||
delete[]$1;
|
||||
if (active_scope->is_vector_name(name) || is_subprogram_param(name))
|
||||
tmp = new ExpName(name, $2);
|
||||
else
|
||||
tmp = new ExpFunc(name, $2);
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$1;
|
||||
if (active_scope->is_vector_name(name) || is_subprogram_param(name))
|
||||
tmp = new ExpName(name, $3);
|
||||
else
|
||||
tmp = new ExpFunc(name, $3);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| IDENTIFIER '(' range ')'
|
||||
{ ExpName*tmp = new ExpName(lex_strings.make($1), $3->msb(), $3->lsb());
|
||||
FILE_NAME(tmp, @1);
|
||||
delete[]$1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| selected_name '(' range ')'
|
||||
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
|
||||
tmp->set_range($3->msb(), $3->lsb());
|
||||
$$ = tmp;
|
||||
}
|
||||
| selected_name '(' expression ')'
|
||||
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
|
||||
tmp->set_range($3, NULL);
|
||||
$$ = tmp;
|
||||
| indexed_name '(' expression_list ')'
|
||||
{ ExpName*name = dynamic_cast<ExpName*>($1);
|
||||
assert(name);
|
||||
name->add_index($3);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue