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:
parent
637d7c9633
commit
46ea9e6954
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue