vhdlpp: ExpAttribute split to Exp{Obj,Type}Attribute.

This commit is contained in:
Maciej Suminski 2016-01-05 13:35:39 +01:00
parent 71c63bf993
commit dff1ad08b0
9 changed files with 239 additions and 87 deletions

View File

@ -228,7 +228,7 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
} }
// If operand1 is not an 'event attribute, I give up. // If operand1 is not an 'event attribute, I give up.
const ExpAttribute*op1 = dynamic_cast<const ExpAttribute*>(op1_raw); const ExpObjAttribute*op1 = dynamic_cast<const ExpObjAttribute*>(op1_raw);
if (op1 == 0) if (op1 == 0)
return -1; return -1;
if (op1->peek_attribute() != "event") if (op1->peek_attribute() != "event")

View File

@ -251,9 +251,16 @@ void ExpAggregate::choice_t::dump(ostream&out, int indent) const
out << setw(indent) << "" << "?choice_t?" << endl; out << setw(indent) << "" << "?choice_t?" << endl;
} }
void ExpAttribute::dump(ostream&out, int indent) const void ExpTypeAttribute::dump(ostream&out, int indent) const
{ {
out << setw(indent) << "" << "Attribute " << name_ out << setw(indent) << "" << "Attribute (type-related) " << name_
<< " at " << get_fileline() << endl;
base_->show(out);
}
void ExpObjAttribute::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Attribute (object-related) " << name_
<< " at " << get_fileline() << endl; << " at " << get_fileline() << endl;
base_->dump(out, indent+4); base_->dump(out, indent+4);
} }

View File

@ -54,29 +54,88 @@ bool Expression::symbolic_compare(const Expression*) const
return false; return false;
} }
ExpAttribute::ExpAttribute(ExpName*bas, perm_string nam) ExpAttribute::ExpAttribute(perm_string nam, list<Expression*>*args)
: base_(bas), name_(nam) : name_(nam), args_(args)
{ {
} }
ExpAttribute::~ExpAttribute() ExpAttribute::~ExpAttribute()
{ {
/* Different attributes can point to the same base so we cannot delete this here. if(args_) {
* Look at the vhdl_range test with valgrind to see this issue. */ for(list<Expression*>::iterator it = args_->begin();
// delete base_; it != args_->end(); ++it) {
delete *it;
}
}
delete args_;
} }
Expression*ExpAttribute::clone() const list<Expression*>*ExpAttribute::clone_args() const {
{ list<Expression*>*new_args = NULL;
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
if(args_) {
for(list<Expression*>::iterator it = args_->begin();
it != args_->end(); ++it) {
new_args->push_back((*it)->clone());
}
}
return new_args;
} }
void ExpAttribute::visit(ExprVisitor& func) void ExpAttribute::visit_args(ExprVisitor& func)
{ {
if(args_) {
for(list<Expression*>::iterator it = args_->begin();
it != args_->end(); ++it) {
func(*it);
}
}
}
ExpObjAttribute::ExpObjAttribute(ExpName*base, perm_string name, list<Expression*>*args)
: ExpAttribute(name, args), base_(base)
{
}
ExpObjAttribute::~ExpObjAttribute()
{
}
Expression*ExpObjAttribute::clone() const
{
return new ExpObjAttribute(static_cast<ExpName*>(base_->clone()),
name_, clone_args());
}
void ExpObjAttribute::visit(ExprVisitor& func)
{
visit_args(func);
base_->visit(func); base_->visit(func);
func(this); func(this);
} }
ExpTypeAttribute::ExpTypeAttribute(const VType*base, perm_string name, list<Expression*>*args)
: ExpAttribute(name, args), base_(base)
{
}
ExpTypeAttribute::~ExpTypeAttribute()
{
}
Expression*ExpTypeAttribute::clone() const
{
return new ExpTypeAttribute(base_, name_, clone_args());
}
void ExpTypeAttribute::visit(ExprVisitor& func)
{
visit_args(func);
func(this);
}
const perm_string ExpAttribute::LEFT = perm_string::literal("left"); const perm_string ExpAttribute::LEFT = perm_string::literal("left");
const perm_string ExpAttribute::RIGHT = perm_string::literal("right"); const perm_string ExpAttribute::RIGHT = perm_string::literal("right");
@ -772,7 +831,8 @@ Expression* ExpRange::lsb()
Expression*ExpRange::left() Expression*ExpRange::left()
{ {
if(range_expr_ && !left_) if(range_expr_ && !left_)
left_ = new ExpAttribute(range_base_, ExpAttribute::LEFT); // TODO check if it is an object or type
left_ = new ExpObjAttribute(range_base_, ExpAttribute::LEFT, NULL);
return left_; return left_;
} }
@ -780,7 +840,8 @@ Expression*ExpRange::left()
Expression*ExpRange::right() Expression*ExpRange::right()
{ {
if(range_expr_ && !right_) if(range_expr_ && !right_)
right_ = new ExpAttribute(range_base_, ExpAttribute::RIGHT); // TODO check if it is an object or type
right_ = new ExpObjAttribute(range_base_, ExpAttribute::RIGHT, NULL);
return right_; return right_;
} }

View File

@ -124,7 +124,7 @@ class Expression : public LineInfo {
virtual void dump(ostream&out, int indent = 0) const =0; virtual void dump(ostream&out, int indent = 0) const =0;
virtual ostream& dump_inline(ostream&out) const; virtual ostream& dump_inline(ostream&out) const;
// Recursively visits a tree of expressions (useful of complex expressions). // Recursively visits a tree of expressions (useful for complex expressions).
virtual void visit(ExprVisitor& func) { func(this); } virtual void visit(ExprVisitor& func) { func(this); }
protected: protected:
@ -355,30 +355,68 @@ class ExpArithmetic : public ExpBinary {
class ExpAttribute : public Expression { class ExpAttribute : public Expression {
public: public:
ExpAttribute(ExpName*base, perm_string name); ExpAttribute(perm_string name,std::list<Expression*>*args);
~ExpAttribute(); virtual ~ExpAttribute();
Expression*clone() const;
inline perm_string peek_attribute() const { return name_; } inline perm_string peek_attribute() const { return name_; }
inline const ExpName* peek_base() const { return base_; }
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
// Some attributes can be evaluated at compile time
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func);
// Constants for the standard attributes // Constants for the standard attributes
static const perm_string LEFT; static const perm_string LEFT;
static const perm_string RIGHT; static const perm_string RIGHT;
protected:
std::list<Expression*>*clone_args() const;
void visit_args(ExprVisitor& func);
bool evaluate_type_attr(const VType*type, Entity*ent, ScopeBase*scope, int64_t&val) const;
bool test_array_type(const VType*type) const;
perm_string name_;
std::list<Expression*>*args_;
};
class ExpObjAttribute : public ExpAttribute {
public:
ExpObjAttribute(ExpName*base, perm_string name, std::list<Expression*>*args);
~ExpObjAttribute();
Expression*clone() const;
inline const ExpName* peek_base() const { return base_; }
int emit(ostream&out, Entity*ent, ScopeBase*scope);
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
// Some attributes can be evaluated at compile time
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func);
private: private:
ExpName*base_; ExpName*base_;
perm_string name_; };
class ExpTypeAttribute : public ExpAttribute {
public:
ExpTypeAttribute(const VType*base, perm_string name, std::list<Expression*>*args);
~ExpTypeAttribute();
Expression*clone() const;
inline const VType* peek_base() const { return base_; }
int emit(ostream&out, Entity*ent, ScopeBase*scope);
const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
// Some attributes can be evaluated at compile time
bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
void visit(ExprVisitor& func);
private:
const VType*base_;
}; };
class ExpBitstring : public Expression { class ExpBitstring : public Expression {

View File

@ -327,7 +327,8 @@ int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lva
int Expression::elaborate_expr(Entity*, ScopeBase*, const VType*) int Expression::elaborate_expr(Entity*, ScopeBase*, const VType*)
{ {
cerr << get_fileline() << ": internal error: I don't know how to elaborate expression type=" << typeid(*this).name() << endl; cerr << get_fileline() << ": internal error: I don't know how to "
<< "elaborate expression type=" << typeid(*this).name() << endl;
return 1; return 1;
} }
@ -582,23 +583,29 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
return 0; return 0;
} }
const VType* ExpAttribute::probe_type(Entity*ent, ScopeBase*scope) const int ExpObjAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{ {
base_->probe_type(ent, scope); const VType*sub_type = base_->probe_type(ent, scope);
return base_->elaborate_expr(ent, scope, sub_type);
}
if (name_ == "length" || name_ == "left" || name_ == "right") { const VType* ExpObjAttribute::probe_type(Entity*, ScopeBase*) const
{
if (name_ == "length" || name_ == "left" || name_ == "right")
return &primitive_NATURAL; return &primitive_NATURAL;
}
return NULL;
}
int ExpTypeAttribute::elaborate_expr(Entity*, ScopeBase*, const VType*)
{
// This is just to mute warnings, there is nothing to elaborate here
return 0; return 0;
} }
int ExpAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) const VType* ExpTypeAttribute::probe_type(Entity*, ScopeBase*) const
{ {
int errors = 0; return NULL;
const VType*sub_type = base_->probe_type(ent, scope);
errors += base_->elaborate_expr(ent, scope, sub_type);
return errors;
} }
const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const

View File

@ -331,7 +331,7 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const V
return errors; return errors;
} }
int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope) int ExpObjAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
@ -365,12 +365,24 @@ int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
return errors; return errors;
} }
// Fallback
out << "$ivl_attribute("; out << "$ivl_attribute(";
errors += base_->emit(out, ent, scope); errors += base_->emit(out, ent, scope);
out << ", \"" << name_ << "\")"; out << ", \"" << name_ << "\")";
return errors; return errors;
} }
int ExpTypeAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
// Fallback
out << "$ivl_attribute(";
errors += base_->emit_def(out, empty_perm_string);
out << ", \"" << name_ << "\")";
return errors;
}
int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope) int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;

View File

@ -73,56 +73,69 @@ bool ExpArithmetic::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
return true; return true;
} }
bool ExpAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const bool ExpAttribute::test_array_type(const VType*type) const
{
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
if (arr == 0) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_ << " attribute to non-array objects"
<< endl;
ivl_assert(*this, false);
return false;
}
if (arr->dimensions() > 1) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to multidimensional arrays" << endl;
return false;
}
if (arr->dimension(0).is_box())
return false;
return true;
}
bool ExpAttribute::evaluate_type_attr(const VType*type, Entity*ent, ScopeBase*scope, int64_t&val) const
{
if (name_ == "length" && test_array_type(type)) {
int64_t size = type->get_width(scope);
if(size > 0) {
val = size;
return true;
}
} else if (name_ == "left" && test_array_type(type)) {
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
return arr->dimension(0).msb()->evaluate(ent, scope, val);
} else if (name_ == "right" && test_array_type(type)) {
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type);
return arr->dimension(0).lsb()->evaluate(ent, scope, val);
}
return false;
}
bool ExpObjAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
const VType*base_type = base_->peek_type(); const VType*base_type = base_->peek_type();
if (base_type == NULL) if (base_type == NULL)
base_type = base_->probe_type(ent, scope); base_type = base_->probe_type(ent, scope);
if (base_type == NULL) if (base_type)
return false; return evaluate_type_attr(base_type, ent, scope, val);
if (name_ == "left" || name_ == "right") {
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == NULL) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to non-array objects" << endl;
return false;
}
if (arr->dimensions() != 1) {
cerr << endl << get_fileline() << ": error: "
<< "Cannot apply the '" << name_
<< " attribute to multidimensional arrays" << endl;
return false;
}
if (arr->dimension(0).is_box())
return false;
if (name_ == "left") {
return arr->dimension(0).msb()->evaluate(ent, scope, val);
} else if (name_ == "right") {
return arr->dimension(0).lsb()->evaluate(ent, scope, val);
} else {
ivl_assert(*this, false);
}
}
else if (name_ == "length") {
int64_t size = base_type->get_width(scope);
if (size > 0) {
val = size;
return true;
}
}
return false; return false;
} }
bool ExpTypeAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{
return evaluate_type_attr(base_, ent, scope, val);
}
bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
if (prefix_.get()) { if (prefix_.get()) {

View File

@ -107,7 +107,13 @@ void ExpArithmetic::write_to_stream(ostream&out) const
out << ")"; out << ")";
} }
void ExpAttribute::write_to_stream(ostream&fd) const void ExpObjAttribute::write_to_stream(ostream&fd) const
{
base_->write_to_stream(fd);
fd << "'" << name_;
}
void ExpTypeAttribute::write_to_stream(ostream&fd) const
{ {
base_->write_to_stream(fd); base_->write_to_stream(fd);
fd << "'" << name_; fd << "'" << name_;

View File

@ -1882,10 +1882,18 @@ prefix /* IEEE 1076-2008 P8.1 */
primary primary
: name : name
{ $$ = $1; } { $$ = $1; }
| name '\'' IDENTIFIER | name '\'' IDENTIFIER argument_list_opt
{ perm_string name = lex_strings.make($3); { ExpAttribute*tmp = NULL;
ExpName*base = dynamic_cast<ExpName*> ($1); perm_string attr = lex_strings.make($3);
ExpAttribute*tmp = new ExpAttribute(base, name); ExpName*base = dynamic_cast<ExpName*>($1);
const VType*type = parse_type_by_name(base->peek_name());
if(type) {
tmp = new ExpTypeAttribute(type, attr, $4);
} else {
tmp = new ExpObjAttribute(base, attr, $4);
}
FILE_NAME(tmp, @3); FILE_NAME(tmp, @3);
delete[]$3; delete[]$3;
$$ = tmp; $$ = tmp;