vhdlpp: Tries to determine if function return type is fixed size.

Added Subprogram::fixed_return_type() method.
This commit is contained in:
Maciej Suminski 2015-01-22 18:29:43 +01:00
parent 962330f20a
commit c287281bbe
2 changed files with 62 additions and 21 deletions

View File

@ -78,6 +78,10 @@ void Subprogram::fix_port_types()
}
}
// Try to settle at a fixed width return type.
if(fixed_return_type())
return;
// Check if the returned type is an unbounded vector.
if(check_unb_vector(return_type_)) {
if(!statements_)
@ -87,12 +91,10 @@ void Subprogram::fix_port_types()
// statements to comply with the modified return type.
for (std::list<SequentialStmt*>::iterator s = statements_->begin()
; s != statements_->end(); ++s) {
cast_return_type r(return_type_) ;
cast_return_type r(return_type_);
(*s)->visit(r);
}
}
//fix_return_type();
}
bool Subprogram::check_unb_vector(const VType*&type)
@ -172,30 +174,65 @@ const VType*Subprogram::peek_param_type(int idx) const
return (*p)->type;
}
void Subprogram::fix_return_type(void)
{
if(!statements_)
return;
struct check_return_type : public SeqStmtVisitor {
check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {}
const ReturnStmt*ret = NULL;
const VType*t = NULL;
for (std::list<SequentialStmt*>::const_iterator s = statements_->begin()
; s != statements_->end(); ++s) {
if((ret = dynamic_cast<const ReturnStmt*>(*s))) {
void operator() (SequentialStmt*s)
{
ReturnStmt*ret;
if((ret = dynamic_cast<ReturnStmt*>(s))) {
const Expression*expr = ret->peek_expr();
const VType*t = NULL;
if(const ExpName*n = dynamic_cast<const ExpName*>(expr)) {
if(Variable*v = find_variable(n->peek_name()))
if(Variable*v = subp_->find_variable(n->peek_name()))
t = v->peek_type();
} else {
t = expr->peek_type();
}
if(t)
return_type_ = t;
if(!t) { // cannot determine the type at least in one case
ret_type_ = NULL;
return;
}
if(!ret_type_) { // this is first processed return statement
ret_type_ = t;
} else if(!t->type_match(ret_type_)) {
// the function can return different types,
// we cannot have fixed width
ret_type_ = NULL;
return;
}
}
}
const VType*get_type() const { return ret_type_; }
private:
const Subprogram*subp_;
const VType*ret_type_;
};
bool Subprogram::fixed_return_type(void)
{
if(!statements_)
return false;
check_return_type r(this);
for (std::list<SequentialStmt*>::iterator s = statements_->begin()
; s != statements_->end(); ++s) {
(*s)->visit(r);
}
const VType*return_type = r.get_type();
if(return_type && !return_type->is_unbounded()) {
return_type_ = return_type;
return true;
} else {
return false;
}
}
void Subprogram::write_to_stream(ostream&fd) const

View File

@ -63,13 +63,17 @@ class Subprogram : public LineInfo, public ScopeBase {
void dump(std::ostream&fd) const;
private:
// 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);
// Tries to set the return type to a fixed type. VHDL functions that
// return std_logic_vectors do not specify its length, as SystemVerilog
// demands.
// The function goes through the function body looking for return
// statments and probes the returned type. If it is the same for every
// statemnt then we can assume that the function returns vector of a
// fixed size.
bool fixed_return_type();
// Iterates through the list of function ports to fix all quirks related
// to translation between VHDL and SystemVerilog.
// to translation between VHDL and SystemVerilog.
void fix_port_types();
// Creates a typedef for an unbounded vector and updates the given type.