vhdlpp: Out & inout arguments in subprogram calls are turned to registers.

Otherwise it is not possible to modify their values in subprograms.
Argument elaboration has been moved to a separate function, so now it is
common for procedure and function calls.
This commit is contained in:
Maciej Suminski 2015-09-23 11:46:29 +02:00
parent 637d7c9633
commit 46ea9e6954
6 changed files with 50 additions and 17 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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<const ExpName*>(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);
}

View File

@ -173,13 +173,8 @@ int ProcedureCall::elaborate(Entity*ent, ScopeBase*scope)
if(param_list_) {
for(list<named_expr_t*>::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;
}
}

View File

@ -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<InterfacePort*>::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)

View File

@ -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_; }