vhdlpp: Added fit_type() & probe_type() for ExpFunc.

This commit is contained in:
Maciej Suminski 2015-03-27 14:51:34 +01:00
parent e6525ec35f
commit ab9a8ccbf3
2 changed files with 119 additions and 0 deletions

View File

@ -516,12 +516,14 @@ class ExpFunc : public Expression {
Expression*clone() const;
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
inline perm_string func_name() const { return name_; }
inline size_t func_args() const { return argv_.size(); }
inline const Expression*func_arg(size_t idx) const { return argv_[idx]; }
const VType*func_ret_type() const;
public: // Base methods
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);

View File

@ -744,6 +744,56 @@ int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VT
return errors;
}
const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
{
if(name_ == "integer")
return &primitive_INTEGER;
if(name_ == "unsigned" || name_ == "resize") {
if(argv_.empty())
return NULL;
const VType*type = argv_[0]->probe_type(ent, scope);
if(!type)
return NULL;
int msb = type->get_width(scope) - 1;
ivl_assert(*this, msb >= 0);
// Determine the sign
bool sign = false;
if(name_ == "resize") {
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
sign = arr->signed_vector();
}
return new VTypeArray(&primitive_BIT, msb, 0, sign);
}
if(name_ == "std_logic_vector" || name_ == "conv_std_logic_vector") {
if(argv_.empty())
return NULL;
const VType*type = argv_[0]->probe_type(ent, scope);
if(!type)
return NULL;
int msb = type->get_width(scope) - 1;
return new VTypeArray(&primitive_STDLOGIC, msb, 0);
}
Subprogram*prog = scope->find_subprogram(name_);
if(!prog)
prog = library_find_subprogram(name_);
if(!prog)
return NULL;
return prog->peek_return_type();
}
int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{
int errors = 0;
@ -776,6 +826,73 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
return errors;
}
const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const
{
// Built-in functions
if(name_ == "to_integer" || name_ == "unsigned" || name_ == "integer") {
ivl_assert(*this, argv_.size() == 1);
const VType*type = argv_[0]->probe_type(ent, scope);
ivl_assert(*this, type);
// Determine the sign
bool sign = false;
if(name_ == "integer") {
sign = true;
} else if(name_ == "to_integer") {
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
sign = arr->signed_vector();
}
return new VTypeArray(&primitive_BIT, type->get_width(scope), 0, sign);
}
if(name_ == "to_unsigned" || name_ == "std_logic_vector" ||
name_ == "conv_std_logic_vector" || name_ == "resize")
{
ivl_assert(*this, argv_.size() == 2);
// Determine the sign
bool sign = false;
const VType*element = &primitive_STDLOGIC;
if(name_ == "resize") {
const VType*type = argv_[0]->probe_type(ent, scope);
ivl_assert(*this, type);
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type))
{
sign = arr->signed_vector();
element = arr->element_type();
}
} else if(name_ == "to_unsigned") {
element = &primitive_BIT;
}
int64_t width = 0;
bool evaluated = argv_[1]->evaluate(scope, width);
ivl_assert(*this, evaluated);
return new VTypeArray(element, width, 0, sign);
}
// Other cases
Subprogram*prog = def_;
if(!prog) {
ivl_assert(*this, scope);
prog = scope->find_subprogram(name_);
}
if(!prog)
prog = library_find_subprogram(name_);
ivl_assert(*this, prog);
return def_->peek_return_type();
}
const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const
{
return &primitive_INTEGER;