diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 4faefe441..01a5e15fb 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -45,6 +45,10 @@ class InterfacePort : public LineInfo { : mode(PORT_NONE), type(typ), expr(NULL) {} + InterfacePort(const VType*typ, port_mode_t mod) + : mode(mod), type(typ), expr(NULL) + {} + // Port direction from the source code. port_mode_t mode; // Name of the port from the source code diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index ee609ae60..50c2e8e2c 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -903,4 +903,8 @@ class ExpTime : public Expression { timeunit_t unit_; }; +// Elaborates an expression used as an argument in a procedure/function call. +int elaborate_argument(Expression*expr, const SubprogramHeader*subp, + int idx, Entity*ent, ScopeBase*scope); + #endif /* IVL_expression_H */ diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 0c57544b3..79fa6c04c 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -782,14 +782,8 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) def_ = prog; // Elaborate arguments - for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { - const VType*tmp = argv_[idx]->probe_type(ent, scope); - const VType*param_type = prog ? prog->peek_param_type(idx) : NULL; - - if(!tmp && param_type) - tmp = param_type; - - errors += argv_[idx]->elaborate_expr(ent, scope, tmp); + for (size_t idx = 0; idx < argv_.size(); ++idx) { + errors += elaborate_argument(argv_[idx], prog, idx, ent, scope); } // SystemVerilog functions work only with defined size data types, therefore @@ -1058,3 +1052,28 @@ int ExpTime::elaborate_expr(Entity*, ScopeBase*, const VType*) set_type(&primitive_INTEGER); return 0; } + +int elaborate_argument(Expression*expr, const SubprogramHeader*subp, + int idx, Entity*ent, ScopeBase*scope) +{ + const VType*type = expr->probe_type(ent, scope); + + if(subp) { + const InterfacePort*param = subp->peek_param(idx); + + // Enable reg_flag for variables that might be modified in subprograms + if(param->mode == PORT_OUT || param->mode == PORT_INOUT) { + if(const ExpName*e = dynamic_cast(expr)) { + if(Signal*sig = scope->find_signal(e->peek_name())) + sig->count_ref_sequ(); + else if(Variable*var = scope->find_variable(e->peek_name())) + var->count_ref_sequ(); + } + } + + if(!type) + type = param->type; + } + + return expr->elaborate_expr(ent, scope, type); +} diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 6967fc574..3f90f0f9f 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -173,13 +173,8 @@ int ProcedureCall::elaborate(Entity*ent, ScopeBase*scope) if(param_list_) { for(list::iterator cur = param_list_->begin() ; cur != param_list_->end() ; ++cur) { - const VType*tmp = (*cur)->expr()->probe_type(ent, scope); - const VType*param_type = def_ ? def_->peek_param_type(idx) : NULL; - - if(!tmp && param_type) - tmp = param_type; - - errors += (*cur)->expr()->elaborate_expr(ent, scope, tmp); + errors += elaborate_argument((*cur)->expr(), def_, idx, ent, scope); + ++idx; } } diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 9f6c58aee..59862f97d 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -138,7 +138,7 @@ const InterfacePort*SubprogramHeader::find_param(perm_string nam) const return NULL; } -const VType*SubprogramHeader::peek_param_type(int idx) const +const InterfacePort*SubprogramHeader::peek_param(int idx) const { if(!ports_ || idx < 0 || (size_t)idx >= ports_->size()) return NULL; @@ -146,7 +146,17 @@ const VType*SubprogramHeader::peek_param_type(int idx) const std::list::const_iterator p = ports_->begin(); std::advance(p, idx); - return (*p)->type; + return *p; +} + +const VType*SubprogramHeader::peek_param_type(int idx) const +{ + const InterfacePort*port = peek_param(idx); + + if(port) + return port->type; + + return NULL; } void SubprogramHeader::set_parent(const ScopeBase*par) diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 0aa5dbdbc..6972ae0be 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -71,6 +71,7 @@ class SubprogramHeader : public LineInfo { bool compare_specification(SubprogramHeader*that) const; const InterfacePort*find_param(perm_string nam) const; + const InterfacePort*peek_param(int idx) const; const VType*peek_param_type(int idx) const; const VType*peek_return_type() const { return return_type_; }