vhdlpp: ExpAttribute split to Exp{Obj,Type}Attribute.
This commit is contained in:
parent
71c63bf993
commit
dff1ad08b0
|
|
@ -228,7 +228,7 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
|
|||
}
|
||||
|
||||
// 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)
|
||||
return -1;
|
||||
if (op1->peek_attribute() != "event")
|
||||
|
|
|
|||
|
|
@ -251,9 +251,16 @@ void ExpAggregate::choice_t::dump(ostream&out, int indent) const
|
|||
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;
|
||||
base_->dump(out, indent+4);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,29 +54,88 @@ bool Expression::symbolic_compare(const Expression*) const
|
|||
return false;
|
||||
}
|
||||
|
||||
ExpAttribute::ExpAttribute(ExpName*bas, perm_string nam)
|
||||
: base_(bas), name_(nam)
|
||||
ExpAttribute::ExpAttribute(perm_string nam, list<Expression*>*args)
|
||||
: name_(nam), args_(args)
|
||||
{
|
||||
}
|
||||
|
||||
ExpAttribute::~ExpAttribute()
|
||||
{
|
||||
/* Different attributes can point to the same base so we cannot delete this here.
|
||||
* Look at the vhdl_range test with valgrind to see this issue. */
|
||||
// delete base_;
|
||||
if(args_) {
|
||||
for(list<Expression*>::iterator it = args_->begin();
|
||||
it != args_->end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
delete args_;
|
||||
}
|
||||
|
||||
Expression*ExpAttribute::clone() const
|
||||
{
|
||||
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
|
||||
list<Expression*>*ExpAttribute::clone_args() const {
|
||||
list<Expression*>*new_args = NULL;
|
||||
|
||||
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);
|
||||
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::RIGHT = perm_string::literal("right");
|
||||
|
||||
|
|
@ -772,7 +831,8 @@ Expression* ExpRange::lsb()
|
|||
Expression*ExpRange::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_;
|
||||
}
|
||||
|
|
@ -780,7 +840,8 @@ Expression*ExpRange::left()
|
|||
Expression*ExpRange::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_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class Expression : public LineInfo {
|
|||
virtual void dump(ostream&out, int indent = 0) const =0;
|
||||
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); }
|
||||
|
||||
protected:
|
||||
|
|
@ -355,30 +355,68 @@ class ExpArithmetic : public ExpBinary {
|
|||
class ExpAttribute : public Expression {
|
||||
|
||||
public:
|
||||
ExpAttribute(ExpName*base, perm_string name);
|
||||
~ExpAttribute();
|
||||
|
||||
Expression*clone() const;
|
||||
ExpAttribute(perm_string name,std::list<Expression*>*args);
|
||||
virtual ~ExpAttribute();
|
||||
|
||||
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
|
||||
static const perm_string LEFT;
|
||||
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:
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -327,7 +327,8 @@ int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lva
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -582,23 +583,29 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
|
|||
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 NULL;
|
||||
}
|
||||
|
||||
int ExpTypeAttribute::elaborate_expr(Entity*, ScopeBase*, const VType*)
|
||||
{
|
||||
// This is just to mute warnings, there is nothing to elaborate here
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
|
||||
const VType* ExpTypeAttribute::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
int errors = 0;
|
||||
const VType*sub_type = base_->probe_type(ent, scope);
|
||||
errors += base_->elaborate_expr(ent, scope, sub_type);
|
||||
return errors;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const V
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
int ExpObjAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
|
@ -365,12 +365,24 @@ int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
return errors;
|
||||
}
|
||||
|
||||
// Fallback
|
||||
out << "$ivl_attribute(";
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ", \"" << name_ << "\")";
|
||||
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 errors = 0;
|
||||
|
|
|
|||
|
|
@ -73,56 +73,69 @@ bool ExpArithmetic::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
|
|||
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();
|
||||
|
||||
if (base_type == NULL)
|
||||
base_type = base_->probe_type(ent, scope);
|
||||
base_type = base_->probe_type(ent, scope);
|
||||
|
||||
if (base_type == NULL)
|
||||
return false;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (base_type)
|
||||
return evaluate_type_attr(base_type, ent, scope, val);
|
||||
|
||||
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
|
||||
{
|
||||
if (prefix_.get()) {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,13 @@ void ExpArithmetic::write_to_stream(ostream&out) const
|
|||
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);
|
||||
fd << "'" << name_;
|
||||
|
|
|
|||
|
|
@ -1882,10 +1882,18 @@ prefix /* IEEE 1076-2008 P8.1 */
|
|||
primary
|
||||
: name
|
||||
{ $$ = $1; }
|
||||
| name '\'' IDENTIFIER
|
||||
{ perm_string name = lex_strings.make($3);
|
||||
ExpName*base = dynamic_cast<ExpName*> ($1);
|
||||
ExpAttribute*tmp = new ExpAttribute(base, name);
|
||||
| name '\'' IDENTIFIER argument_list_opt
|
||||
{ ExpAttribute*tmp = NULL;
|
||||
perm_string attr = lex_strings.make($3);
|
||||
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);
|
||||
delete[]$3;
|
||||
$$ = tmp;
|
||||
|
|
|
|||
Loading…
Reference in New Issue