From ab9a8ccbf305d6c060215794e32157cb97a0beb7 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 27 Mar 2015 14:51:34 +0100 Subject: [PATCH] vhdlpp: Added fit_type() & probe_type() for ExpFunc. --- vhdlpp/expression.h | 2 + vhdlpp/expression_elaborate.cc | 117 +++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index dd1ae6783..c9b53e77b 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -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); diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index bca9e743d..30ddd4e2f 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -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(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(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(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;