diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index c255df43a..749e2a0d6 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -368,9 +368,16 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc) return errors; } - for (list::const_iterator cur = rval_.begin() + for (list::iterator cur = rval_.begin() ; cur != rval_.end() ; ++cur) { (*cur)->elaborate_expr(ent, arc, lval_type); + + // Handle functions that return unbounded arrays + if(ExpFunc*call = dynamic_cast(*cur)) { + const VType*ret_type = call->func_ret_type(); + if(ret_type && ret_type->is_unbounded()) + *cur = new ExpCast(*cur, get_global_typedef(lval_type)); + } } return errors; diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 063063772..019c2fb89 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -286,7 +286,7 @@ ExpFunc::~ExpFunc() const VType* ExpFunc::func_ret_type() const { - return def_->peek_return_type(); + return def_ ? def_->peek_return_type() : NULL; } ExpInteger::ExpInteger(int64_t val) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index b07ff6994..11f43de6d 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -751,11 +751,20 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*) ivl_assert(*this, def_==0); def_ = prog; + // Elaborate arguments for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { const VType*tmp = argv_[idx]->probe_type(ent, arc); - if(!tmp && prog) - tmp = prog->peek_param_type(idx); + const VType*param_type = prog ? prog->peek_param_type(idx) : NULL; + + if(!tmp && param_type) + tmp = param_type; + errors += argv_[idx]->elaborate_expr(ent, arc, tmp); + + // Type casting for unbounded arrays + if(param_type && param_type->is_unbounded() /*&& !param_type->type_match(tmp)*/) { + argv_[idx] = new ExpCast(argv_[idx], get_global_typedef(param_type)); + } } return errors; diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 184f85d56..dcfabe978 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -80,7 +80,6 @@ int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, Architecture*arc) return errors; } - int ForLoopStatement::elaborate(Entity*ent, Architecture*arc) { int errors = 0; @@ -176,6 +175,13 @@ int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc) // Elaborate the r-value expression. errors += rval_->elaborate_expr(ent, arc, lval_type); + // Handle functions that return unbounded arrays + if(ExpFunc*call = dynamic_cast(rval_)) { + const VType*ret_type = call->func_ret_type(); + if(ret_type && ret_type->is_unbounded()) + rval_ = new ExpCast(rval_, get_global_typedef(lval_type)); + } + return errors; } diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 5814bfdbf..19aa56e62 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -1,6 +1,8 @@ /* * Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -23,6 +25,7 @@ # include "vtype.h" # include "sequential.h" # include "ivl_assert.h" +# include "compiler.h" using namespace std; @@ -46,7 +49,71 @@ void Subprogram::set_program_body(list*stmt) { ivl_assert(*this, statements_==0); statements_ = stmt; - fix_return_type(); + fix_port_types(); +} + +// Functor used to add type casting to each return statement. +struct cast_return_type : public SeqStmtVisitor { + cast_return_type(const VType*ret_type) : ret_(ret_type) {} + + void operator() (SequentialStmt*s) + { + ReturnStmt*ret; + if((ret = dynamic_cast(s))) { + ret->cast_to(ret_); + } + } + +private: + const VType*ret_; +}; + +void Subprogram::fix_port_types() +{ + // Check function parameters for unbounded vectors and possibly fix it. + if(ports_) { + for(std::list::iterator it = ports_->begin(); + it != ports_->end(); ++it) { + check_unb_vector((*it)->type); + } + } + + // Check if the returned type is an unbounded vector. + if(check_unb_vector(return_type_)) { + if(!statements_) + return; + + // Go through the statement list and add type casting to return + // statements to comply with the modified return type. + for (std::list::iterator s = statements_->begin() + ; s != statements_->end(); ++s) { + cast_return_type r(return_type_) ; + (*s)->visit(r); + } + } + + //fix_return_type(); +} + +bool Subprogram::check_unb_vector(const VType*&type) +{ + if(const VTypeArray*arr = dynamic_cast(type)) { + if(arr->dimensions() == 1 && arr->dimension(0).is_box() ) { + // For the time being, dynamic arrays work exclusively with vectors. + // To emulate simple 'logic'/'bit' type, we need to create a vector + // of width == 1, to be used as the array element type. + // Effectively 'logic name []' becomes 'logic [0:0] name []'. + Expression*zero = new ExpInteger(0); + std::vector sub_range; + sub_range.push_back(VTypeArray::range_t(zero, zero)); + VTypeArray*new_arr = new VTypeArray(arr, sub_range); + type = get_global_typedef(new_arr); + + return true; + } + } + + return false; } bool Subprogram::compare_specification(Subprogram*that) const diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 5b38f1223..b37fe6cd4 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -3,6 +3,8 @@ /* * Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) + * Copyright CERN 2015 + * @author Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -50,6 +52,7 @@ class Subprogram : public LineInfo, public ScopeBase { const InterfacePort*find_param(perm_string nam) const; const VType*peek_param_type(int idx) const; + const VType*peek_return_type() const { return return_type_; } int emit(ostream&out, Entity*ent, Architecture*arc); @@ -60,10 +63,18 @@ class Subprogram : public LineInfo, public ScopeBase { void dump(std::ostream&fd) const; private: - // Determines appropriate return type. Un case of std_logic_vector - // VHDL requires skipping its size in contrary to Verilog + // Determines appropriate return type, basing on the *first* return + // statement found in the function body. In case of std_logic_vector + // VHDL requires skipping its size, contrary to Verilog. void fix_return_type(void); + // Iterates through the list of function ports to fix all quirks related + // to translation between VHDL and SystemVerilog. + void fix_port_types(); + + // Creates a typedef for an unbounded vector and updates the given type. + bool check_unb_vector(const VType*&type); + perm_string name_; const ScopeBase*parent_; std::list*ports_;