vhdlpp: Subprogram split to SubprogramHeader and SubprogramBody.

This commit is contained in:
Maciej Suminski 2015-06-10 11:29:37 +02:00
parent 3c437874e2
commit 47c5ce0ab6
15 changed files with 263 additions and 173 deletions

View File

@ -101,7 +101,7 @@ int Architecture::emit(ostream&out, Entity*entity)
errors += emit_signals(out, entity, this); errors += emit_signals(out, entity, this);
errors += emit_variables(out, entity, this); errors += emit_variables(out, entity, this);
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin() for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++ cur) { ; cur != cur_subprograms_.end() ; ++ cur) {
// Do not emit unbounded functions, we will just need fixed instances later // Do not emit unbounded functions, we will just need fixed instances later
if(!cur->second->unbounded()) if(!cur->second->unbounded())

View File

@ -150,17 +150,21 @@ void Scope::dump_scope(ostream&out) const
} }
// Dump subprograms // Dump subprograms
out << " -- Imported Subprograms" << endl; out << " -- Imported Subprograms" << endl;
for (map<perm_string,Subprogram*>::const_iterator cur = use_subprograms_.begin() for (map<perm_string,SubprogramHeader*>::const_iterator cur = use_subprograms_.begin()
; cur != use_subprograms_.end() ; ++cur) { ; cur != use_subprograms_.end() ; ++cur) {
out << " subprogram " << cur->first << " is" << endl; out << " subprogram " << cur->first << " is" << endl;
cur->second->dump(out); cur->second->dump(out);
if(cur->second->body())
cur->second->body()->dump(out);
out << " end subprogram " << cur->first << endl; out << " end subprogram " << cur->first << endl;
} }
out << " -- Subprograms from this scope" << endl; out << " -- Subprograms from this scope" << endl;
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin() for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) { ; cur != cur_subprograms_.end() ; ++cur) {
out << " subprogram " << cur->first << " is" << endl; out << " subprogram " << cur->first << " is" << endl;
cur->second->dump(out); cur->second->dump(out);
if(cur->second->body())
cur->second->body()->dump(out);
out << " end subprogram " << cur->first << endl; out << " end subprogram " << cur->first << endl;
} }
// Dump component declarations // Dump component declarations
@ -467,7 +471,20 @@ ostream& ExpReal::dump_inline(ostream&out) const
return out; return out;
} }
void Subprogram::dump(ostream&fd) const void SubprogramBody::dump(ostream&fd) const
{
if (statements_== 0 || statements_->empty()) {
fd << " <no definition>" << endl;
} else {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
SequentialStmt*curp = *cur;
curp->dump(fd, 8);
}
}
}
void SubprogramHeader::dump(ostream&fd) const
{ {
fd << " " << name_; fd << " " << name_;
@ -493,14 +510,4 @@ void Subprogram::dump(ostream&fd) const
fd << " return "; fd << " return ";
return_type_->show(fd); return_type_->show(fd);
fd << endl; fd << endl;
if (statements_== 0 || statements_->empty()) {
fd << " <no definition>" << endl;
} else {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
SequentialStmt*curp = *cur;
curp->dump(fd, 8);
}
}
} }

View File

@ -32,7 +32,7 @@
class prange_t; class prange_t;
class Entity; class Entity;
class ScopeBase; class ScopeBase;
class Subprogram; class SubprogramHeader;
class VType; class VType;
class VTypeArray; class VTypeArray;
class VTypePrimitive; class VTypePrimitive;
@ -564,7 +564,7 @@ class ExpFunc : public Expression {
private: private:
perm_string name_; perm_string name_;
std::vector<Expression*> argv_; std::vector<Expression*> argv_;
Subprogram*def_; SubprogramHeader*def_;
}; };
class ExpInteger : public Expression { class ExpInteger : public Expression {

View File

@ -777,7 +777,7 @@ const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const
return new VTypeArray(&primitive_STDLOGIC, msb, 0); return new VTypeArray(&primitive_STDLOGIC, msb, 0);
} }
Subprogram*prog = scope->find_subprogram(name_); SubprogramHeader*prog = scope->find_subprogram(name_);
if(!prog) if(!prog)
prog = library_find_subprogram(name_); prog = library_find_subprogram(name_);
@ -793,7 +793,7 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
int errors = 0; int errors = 0;
ivl_assert(*this, scope); ivl_assert(*this, scope);
Subprogram*prog = scope->find_subprogram(name_); SubprogramHeader*prog = scope->find_subprogram(name_);
if(!prog) if(!prog)
prog = library_find_subprogram(name_); prog = library_find_subprogram(name_);
@ -878,7 +878,7 @@ const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) c
} }
// Other cases // Other cases
Subprogram*prog = def_; SubprogramHeader*prog = def_;
if(!prog) { if(!prog) {
ivl_assert(*this, scope); ivl_assert(*this, scope);

View File

@ -72,9 +72,9 @@ void library_add_directory(const char*directory)
library_search_path.push_front(directory); library_search_path.push_front(directory);
} }
Subprogram*library_find_subprogram(perm_string name) SubprogramHeader*library_find_subprogram(perm_string name)
{ {
Subprogram*subp = NULL; SubprogramHeader*subp = NULL;
map<perm_string,struct library_contents>::const_iterator lib_it; map<perm_string,struct library_contents>::const_iterator lib_it;
for(lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) { for(lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) {

View File

@ -19,12 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
class Subprogram; class SubprogramHeader;
extern void library_set_work_path(const char*work_path); extern void library_set_work_path(const char*work_path);
extern void library_add_directory(const char*directory); extern void library_add_directory(const char*directory);
extern Subprogram*library_find_subprogram(perm_string name); extern SubprogramHeader*library_find_subprogram(perm_string name);
extern void emit_std_types(ostream&out); extern void emit_std_types(ostream&out);
extern int emit_packages(void); extern int emit_packages(void);

View File

@ -111,9 +111,10 @@ void Package::write_to_stream(ostream&fd) const
fd << ";" << endl; fd << ";" << endl;
} }
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin() for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) { ; cur != cur_subprograms_.end() ; ++cur) {
cur->second->write_to_stream(fd); cur->second->write_to_stream(fd);
fd << ";" << endl;
} }
for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin() for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin()
@ -130,9 +131,14 @@ void Package::write_to_stream(ostream&fd) const
fd << "end package " << name_ << ";" << endl; fd << "end package " << name_ << ";" << endl;
fd << "package body " << name_ << " is" << endl; fd << "package body " << name_ << " is" << endl;
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin() for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) { ; cur != cur_subprograms_.end() ; ++cur) {
cur->second->write_to_stream_body(fd); SubprogramHeader*subp = cur->second;
if(subp->body()) {
subp->write_to_stream(fd);
fd << " is" << endl;
subp->body()->write_to_stream(fd);
}
} }
fd << "end " << name_ << ";" << endl; fd << "end " << name_ << ";" << endl;
} }

View File

@ -36,7 +36,7 @@ class Package : public Scope, public LineInfo {
perm_string name() const { return name_; } perm_string name() const { return name_; }
Subprogram* recall_subprogram(perm_string name) const; SubprogramHeader* recall_subprogram(perm_string name) const;
// This method writes a package header to a library file. // This method writes a package header to a library file.
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;

View File

@ -64,7 +64,7 @@ int Package::emit_package(ostream&fd) const
//} //}
fd << "package \\" << name() << " ;" << endl; fd << "package \\" << name() << " ;" << endl;
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin() for (map<perm_string,SubprogramHeader*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++ cur) { ; cur != cur_subprograms_.end() ; ++ cur) {
// Do not emit unbounded functions, we will just need fixed instances later // Do not emit unbounded functions, we will just need fixed instances later
if(!cur->second->unbounded()) if(!cur->second->unbounded())

View File

@ -83,7 +83,7 @@ extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner);
*/ */
static ActiveScope*active_scope = new ActiveScope; static ActiveScope*active_scope = new ActiveScope;
static stack<ActiveScope*> scope_stack; static stack<ActiveScope*> scope_stack;
static Subprogram*active_sub = NULL; static SubprogramHeader*active_sub = NULL;
// perm_strings for attributes // perm_strings for attributes
const static perm_string left_attr = perm_string::literal("left"); const static perm_string left_attr = perm_string::literal("left");
@ -262,7 +262,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
ReportStmt::severity_t severity; ReportStmt::severity_t severity;
Subprogram*subprogram; SubprogramHeader*subprogram;
}; };
/* The keywords are all tokens. */ /* The keywords are all tokens. */
@ -374,6 +374,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <exp_options_list> else_when_waveforms selected_waveform_list %type <exp_options_list> else_when_waveforms selected_waveform_list
%type <subprogram> function_specification subprogram_specification subprogram_body_start %type <subprogram> function_specification subprogram_specification subprogram_body_start
%type <severity> severity severity_opt %type <severity> severity severity_opt
%% %%
@ -1246,8 +1247,8 @@ function_specification /* IEEE 1076-2008 P4.2.1 */
perm_string name = lex_strings.make($2); perm_string name = lex_strings.make($2);
const VType*type_mark = active_scope->find_type(type_name); const VType*type_mark = active_scope->find_type(type_name);
touchup_interface_for_functions($4); touchup_interface_for_functions($4);
Subprogram*tmp = new Subprogram(name, $4, type_mark); SubprogramHeader*tmp = new SubprogramHeader(name, $4, type_mark);
FILE_NAME(tmp,@1); FILE_NAME(tmp, @1);
delete[]$2; delete[]$2;
delete[]$7; delete[]$7;
$$ = tmp; $$ = tmp;
@ -2420,16 +2421,20 @@ subprogram_body /* IEEE 1076-2008 P4.3 */
: subprogram_body_start subprogram_declarative_part : subprogram_body_start subprogram_declarative_part
K_begin subprogram_statement_part K_end K_begin subprogram_statement_part K_end
subprogram_kind_opt identifier_opt ';' subprogram_kind_opt identifier_opt ';'
{ Subprogram*prog = $1; { SubprogramHeader*prog = $1;
Subprogram*tmp = active_scope->recall_subprogram(prog->name()); SubprogramHeader*tmp = active_scope->recall_subprogram(prog->name());
if (tmp && prog->compare_specification(tmp)) { if (tmp && prog->compare_specification(tmp)) {
delete prog; delete prog;
prog = tmp; prog = tmp;
} else if (tmp) { } else if (tmp) {
errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str()); errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str());
} }
prog->transfer_from(*active_scope, ScopeBase::VARIABLES);
prog->set_program_body($4); SubprogramBody*body = new SubprogramBody();
body->transfer_from(*active_scope, ScopeBase::VARIABLES);
body->set_statements($4);
prog->set_body(body);
active_scope->bind_name(prog->name(), prog); active_scope->bind_name(prog->name(), prog);
active_sub = NULL; active_sub = NULL;
} }

View File

@ -65,9 +65,9 @@ ScopeBase::ScopeBase(const ActiveScope&ref)
// an active scope and is making the actual scope. At this point // an active scope and is making the actual scope. At this point
// we know that "this" is the parent scope for the subprograms, // we know that "this" is the parent scope for the subprograms,
// so set it now. // so set it now.
for (map<perm_string,Subprogram*>::iterator cur = cur_subprograms_.begin() for (map<perm_string,SubprogramHeader*>::iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++ cur) { ; cur != cur_subprograms_.end(); ++cur) {
cur->second->set_parent(this); cur->second->set_parent(this);
} }
} }
@ -158,13 +158,13 @@ Variable* ScopeBase::find_variable(perm_string by_name) const
const InterfacePort* ScopeBase::find_param(perm_string by_name) const const InterfacePort* ScopeBase::find_param(perm_string by_name) const
{ {
for(map<perm_string,Subprogram*>::const_iterator it = use_subprograms_.begin(); for(map<perm_string,SubprogramHeader*>::const_iterator it = use_subprograms_.begin();
it != use_subprograms_.end(); ++it) { it != use_subprograms_.end(); ++it) {
if(const InterfacePort*port = it->second->find_param(by_name)) if(const InterfacePort*port = it->second->find_param(by_name))
return port; return port;
} }
for(map<perm_string,Subprogram*>::const_iterator it = cur_subprograms_.begin(); for(map<perm_string,SubprogramHeader*>::const_iterator it = cur_subprograms_.begin();
it != cur_subprograms_.end(); ++it) { it != cur_subprograms_.end(); ++it) {
if(const InterfacePort*port = it->second->find_param(by_name)) if(const InterfacePort*port = it->second->find_param(by_name))
return port; return port;
@ -173,9 +173,9 @@ const InterfacePort* ScopeBase::find_param(perm_string by_name) const
return NULL; return NULL;
} }
Subprogram* ScopeBase::find_subprogram(perm_string name) const SubprogramHeader* ScopeBase::find_subprogram(perm_string name) const
{ {
map<perm_string,Subprogram*>::const_iterator cur; map<perm_string,SubprogramHeader*>::const_iterator cur;
cur = cur_subprograms_.find(name); cur = cur_subprograms_.find(name);
if (cur != cur_subprograms_.end()) if (cur != cur_subprograms_.end())
@ -218,7 +218,7 @@ void ScopeBase::do_use_from(const ScopeBase*that)
old_components_[cur->first] = cur->second; old_components_[cur->first] = cur->second;
} }
for (map<perm_string,Subprogram*>::const_iterator cur = that->cur_subprograms_.begin() for (map<perm_string,SubprogramHeader*>::const_iterator cur = that->cur_subprograms_.begin()
; cur != that->cur_subprograms_.end() ; ++ cur) { ; cur != that->cur_subprograms_.end() ; ++ cur) {
if (cur->second == 0) if (cur->second == 0)
continue; continue;
@ -274,9 +274,9 @@ void ActiveScope::set_package_header(Package*pkg)
package_header_ = pkg; package_header_ = pkg;
} }
Subprogram* ActiveScope::recall_subprogram(perm_string name) const SubprogramHeader* ActiveScope::recall_subprogram(perm_string name) const
{ {
if (Subprogram*tmp = find_subprogram(name)) if (SubprogramHeader*tmp = find_subprogram(name))
return tmp; return tmp;
if (package_header_) if (package_header_)

View File

@ -32,7 +32,7 @@ class ActiveScope;
class Architecture; class Architecture;
class ComponentBase; class ComponentBase;
class Package; class Package;
class Subprogram; class SubprogramHeader;
class VType; class VType;
template<typename T> template<typename T>
@ -57,7 +57,7 @@ class ScopeBase {
Signal* find_signal(perm_string by_name) const; Signal* find_signal(perm_string by_name) const;
Variable* find_variable(perm_string by_name) const; Variable* find_variable(perm_string by_name) const;
virtual const InterfacePort* find_param(perm_string by_name) const; virtual const InterfacePort* find_param(perm_string by_name) const;
Subprogram* find_subprogram(perm_string by_name) const; SubprogramHeader* find_subprogram(perm_string by_name) const;
// Checks if a string is one of possible enum values. If so, the enum // Checks if a string is one of possible enum values. If so, the enum
// type is returned, otherwise NULL. // type is returned, otherwise NULL.
const VTypeEnum* is_enum_name(perm_string name) const; const VTypeEnum* is_enum_name(perm_string name) const;
@ -67,8 +67,8 @@ class ScopeBase {
enum transfer_type_t { SIGNALS = 1, VARIABLES = 2, COMPONENTS = 4, ALL = 0xffff }; enum transfer_type_t { SIGNALS = 1, VARIABLES = 2, COMPONENTS = 4, ALL = 0xffff };
void transfer_from(ScopeBase&ref, transfer_type_t what = ALL); void transfer_from(ScopeBase&ref, transfer_type_t what = ALL);
inline void bind_subprogram(perm_string name, Subprogram*obj) inline void bind_subprogram(perm_string name, SubprogramHeader*obj)
{ map<perm_string, Subprogram*>::iterator it; { map<perm_string, SubprogramHeader*>::iterator it;
if((it = use_subprograms_.find(name)) != use_subprograms_.end() ) if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
use_subprograms_.erase(it); use_subprograms_.erase(it);
cur_subprograms_[name] = obj; cur_subprograms_[name] = obj;
@ -116,8 +116,8 @@ class ScopeBase {
std::map<perm_string, struct const_t*> use_constants_; //imported constants std::map<perm_string, struct const_t*> use_constants_; //imported constants
std::map<perm_string, struct const_t*> cur_constants_; //current constants std::map<perm_string, struct const_t*> cur_constants_; //current constants
std::map<perm_string, Subprogram*> use_subprograms_; //imported std::map<perm_string, SubprogramHeader*> use_subprograms_; //imported
std::map<perm_string, Subprogram*> cur_subprograms_; //current std::map<perm_string, SubprogramHeader*> cur_subprograms_; //current
std::list<const VTypeEnum*> use_enums_; std::list<const VTypeEnum*> use_enums_;
@ -170,7 +170,7 @@ class ActiveScope : public ScopeBase {
// Locate the subprogram by name. The subprogram body uses // Locate the subprogram by name. The subprogram body uses
// this to locate the sobprogram declaration. Note that the // this to locate the sobprogram declaration. Note that the
// subprogram may be in a package header. // subprogram may be in a package header.
Subprogram* recall_subprogram(perm_string name) const; SubprogramHeader* recall_subprogram(perm_string name) const;
/* All bind_name function check if the given name was present /* All bind_name function check if the given name was present
* in previous scopes. If it is found, it is erased (but the pointer * in previous scopes. If it is found, it is erased (but the pointer
@ -219,8 +219,8 @@ class ActiveScope : public ScopeBase {
cur_constants_[name] = new const_t(obj, val); cur_constants_[name] = new const_t(obj, val);
} }
inline void bind_name(perm_string name, Subprogram*obj) inline void bind_name(perm_string name, SubprogramHeader*obj)
{ map<perm_string, Subprogram*>::iterator it; { map<perm_string, SubprogramHeader*>::iterator it;
if((it = use_subprograms_.find(name)) != use_subprograms_.end() ) if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
use_subprograms_.erase(it); use_subprograms_.erase(it);
cur_subprograms_[name] = obj; cur_subprograms_[name] = obj;

View File

@ -30,44 +30,61 @@
using namespace std; using namespace std;
Subprogram::Subprogram(perm_string nam, list<InterfacePort*>*ports, SubprogramBody::SubprogramBody()
const VType*return_type) : statements_(NULL), header_(NULL)
: name_(nam), parent_(0), ports_(ports), return_type_(return_type), statements_(0)
{ {
} }
Subprogram::~Subprogram() SubprogramBody::~SubprogramBody()
{ {
} }
void Subprogram::set_parent(const ScopeBase*par) const InterfacePort*SubprogramBody::find_param(perm_string nam) const
{ {
ivl_assert(*this, parent_ == 0); if(!header_)
parent_ = par; return NULL;
return header_->find_param(nam);
} }
void Subprogram::set_program_body(list<SequentialStmt*>*stmt) void SubprogramBody::set_statements(list<SequentialStmt*>*stmt)
{ {
ivl_assert(*this, statements_==0); ivl_assert(*this, statements_==0);
statements_ = stmt; statements_ = stmt;
} }
bool Subprogram::unbounded() const { void SubprogramBody::write_to_stream(ostream&fd) const
if(return_type_->is_unbounded()) {
return true; for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
; cur != new_variables_.end() ; ++cur) {
cur->second->write_to_stream(fd);
}
if(ports_) { fd << "begin" << endl;
for(std::list<InterfacePort*>::const_iterator it = ports_->begin();
it != ports_->end(); ++it) {
if((*it)->type->is_unbounded())
return true;
}
}
return false; if (statements_) {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
(*cur)->write_to_stream(fd);
}
} else {
fd << "--empty body" << endl;
}
fd << "end function;" << endl;
} }
bool Subprogram::compare_specification(Subprogram*that) const SubprogramHeader::SubprogramHeader(perm_string nam, list<InterfacePort*>*ports,
const VType*return_type)
: name_(nam), ports_(ports), return_type_(return_type), body_(NULL), parent_(NULL)
{
}
SubprogramHeader::~SubprogramHeader()
{
delete body_;
}
bool SubprogramHeader::compare_specification(SubprogramHeader*that) const
{ {
if (name_ != that->name_) if (name_ != that->name_)
return false; return false;
@ -98,7 +115,7 @@ bool Subprogram::compare_specification(Subprogram*that) const
return true; return true;
} }
const InterfacePort*Subprogram::find_param(perm_string nam) const const InterfacePort*SubprogramHeader::find_param(perm_string nam) const
{ {
if(!ports_) if(!ports_)
return NULL; return NULL;
@ -112,7 +129,7 @@ const InterfacePort*Subprogram::find_param(perm_string nam) const
return NULL; return NULL;
} }
const VType*Subprogram::peek_param_type(int idx) const const VType*SubprogramHeader::peek_param_type(int idx) const
{ {
if(!ports_ || idx < 0 || (size_t)idx >= ports_->size()) if(!ports_ || idx < 0 || (size_t)idx >= ports_->size())
return NULL; return NULL;
@ -123,7 +140,37 @@ const VType*Subprogram::peek_param_type(int idx) const
return (*p)->type; return (*p)->type;
} }
Subprogram*Subprogram::make_instance(std::vector<Expression*> arguments, ScopeBase*scope) { void SubprogramHeader::set_parent(const ScopeBase*par)
{
ivl_assert(*this, !parent_);
parent_ = par;
}
bool SubprogramHeader::unbounded() const {
if(return_type_->is_unbounded())
return true;
if(ports_) {
for(std::list<InterfacePort*>::const_iterator it = ports_->begin();
it != ports_->end(); ++it) {
if((*it)->type->is_unbounded())
return true;
}
}
return false;
}
void SubprogramHeader::set_body(SubprogramBody*bdy)
{
ivl_assert(*this, !body_);
body_ = bdy;
ivl_assert(*this, !bdy->header_);
bdy->header_ = this;
}
SubprogramHeader*SubprogramHeader::make_instance(std::vector<Expression*> arguments,
ScopeBase*scope) {
assert(arguments.size() == ports_->size()); assert(arguments.size() == ports_->size());
std::list<InterfacePort*>*ports = new std::list<InterfacePort*>; std::list<InterfacePort*>*ports = new std::list<InterfacePort*>;
@ -142,25 +189,31 @@ Subprogram*Subprogram::make_instance(std::vector<Expression*> arguments, ScopeBa
char buf[80]; char buf[80];
snprintf(buf, sizeof(buf), "__%s_%p", name_.str(), ports); snprintf(buf, sizeof(buf), "__%s_%p", name_.str(), ports);
perm_string new_name = lex_strings.make(buf); perm_string new_name = lex_strings.make(buf);
Subprogram*instance = new Subprogram(new_name, ports, return_type_); SubprogramHeader*instance = new SubprogramHeader(new_name, ports, return_type_);
// Copy variables if(body_) {
for(std::map<perm_string,Variable*>::iterator it = new_variables_.begin(); SubprogramBody*body_inst = new SubprogramBody();
it != new_variables_.end(); ++it) {
Variable*v = new Variable(it->first, it->second->peek_type()->clone()); // Copy variables
instance->new_variables_[it->first] = v; for(std::map<perm_string,Variable*>::iterator it = body_->new_variables_.begin();
it != body_->new_variables_.end(); ++it) {
Variable*v = new Variable(it->first, it->second->peek_type()->clone());
body_inst->new_variables_[it->first] = v;
}
body_inst->set_statements(body_->statements_);
instance->set_parent(scope);
instance->set_body(body_inst);
instance->fix_return_type();
} }
instance->set_parent(scope);
instance->set_program_body(statements_);
instance->fix_return_type();
scope->bind_subprogram(new_name, instance); scope->bind_subprogram(new_name, instance);
return instance; return instance;
} }
struct check_return_type : public SeqStmtVisitor { struct check_return_type : public SeqStmtVisitor {
check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {} check_return_type(const SubprogramBody*subp) : subp_(subp), ret_type_(NULL) {}
void operator() (SequentialStmt*s) void operator() (SequentialStmt*s)
{ {
@ -195,54 +248,35 @@ struct check_return_type : public SeqStmtVisitor {
const VType*get_type() const { return ret_type_; } const VType*get_type() const { return ret_type_; }
private: private:
const Subprogram*subp_; const SubprogramBody*subp_;
const VType*ret_type_; const VType*ret_type_;
}; };
void Subprogram::fix_return_type() void SubprogramHeader::fix_return_type()
{ {
if(!statements_) if(!body_ || !body_->statements_)
return; return;
check_return_type r(this); check_return_type r(body_);
for (std::list<SequentialStmt*>::iterator s = statements_->begin() for (std::list<SequentialStmt*>::iterator s = body_->statements_->begin()
; s != statements_->end(); ++s) { ; s != body_->statements_->end(); ++s) {
(*s)->visit(r); (*s)->visit(r);
} }
VType*return_type = const_cast<VType*>(r.get_type()); VType*return_type = const_cast<VType*>(r.get_type());
if(return_type && !return_type->is_unbounded()) { if(return_type && !return_type->is_unbounded()) {
// Let's check if the variable length can be evaluated without any scope. // Let's check if the variable length can be evaluated without any scope.
// If not, then it is depends on information about e.g. function params // If not, then it depends on information about e.g. function params
if(return_type->is_variable_length(NULL)) { if(return_type->is_variable_length(NULL)) {
if(VTypeArray*arr = dynamic_cast<VTypeArray*>(return_type)) if(VTypeArray*arr = dynamic_cast<VTypeArray*>(return_type))
arr->evaluate_ranges(this); arr->evaluate_ranges(body_);
} }
return_type_ = return_type; return_type_ = return_type;
} }
} }
void Subprogram::write_to_stream(ostream&fd) const void SubprogramHeader::write_to_stream(ostream&fd) const
{
fd << " function " << name_ << "(";
if (ports_ && ! ports_->empty()) {
list<InterfacePort*>::const_iterator cur = ports_->begin();
InterfacePort*curp = *cur;
fd << curp->name << " : ";
curp->type->write_to_stream(fd);
for (++cur ; cur != ports_->end() ; ++cur) {
curp = *cur;
fd << "; " << curp->name << " : ";
curp->type->write_to_stream(fd);
}
}
fd << ") return ";
return_type_->write_to_stream(fd);
fd << ";" << endl;
}
void Subprogram::write_to_stream_body(ostream&fd) const
{ {
fd << "function " << name_ << "("; fd << "function " << name_ << "(";
if (ports_ && ! ports_->empty()) { if (ports_ && ! ports_->empty()) {
@ -258,22 +292,4 @@ void Subprogram::write_to_stream_body(ostream&fd) const
} }
fd << ") return "; fd << ") return ";
return_type_->write_to_stream(fd); return_type_->write_to_stream(fd);
fd << " is" << endl;
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
; cur != new_variables_.end() ; ++cur) {
cur->second->write_to_stream(fd);
}
fd << "begin" << endl;
if (statements_) {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
(*cur)->write_to_stream(fd);
}
} else {
fd << "--empty body" << endl;
}
fd << "end function;" << endl;
} }

View File

@ -27,51 +27,75 @@
# include "scope.h" # include "scope.h"
# include <iostream> # include <iostream>
# include <list> # include <list>
# include <cassert>
class InterfacePort; class InterfacePort;
class SequentialStmt; class SequentialStmt;
class VType; class VType;
class SubprogramHeader;
class Subprogram : public LineInfo, public ScopeBase { class SubprogramBody : public LineInfo, public ScopeBase {
public: public:
Subprogram(perm_string name, std::list<InterfacePort*>*ports, SubprogramBody();
~SubprogramBody();
const InterfacePort*find_param(perm_string nam) const;
void set_statements(std::list<SequentialStmt*>*statements);
inline bool empty_statements() const { return !statements_ || statements_->empty(); }
int emit(ostream&out, Entity*ent, ScopeBase*scope);
// Emit body as it would show up in a package.
int emit_package(std::ostream&fd) const;
void write_to_stream(std::ostream&fd) const;
void dump(std::ostream&fd) const;
private:
std::list<SequentialStmt*>*statements_;
SubprogramHeader*header_;
friend class SubprogramHeader;
};
class SubprogramHeader : public LineInfo {
public:
SubprogramHeader(perm_string name, std::list<InterfacePort*>*ports,
const VType*return_type); const VType*return_type);
~Subprogram(); ~SubprogramHeader();
void set_parent(const ScopeBase*par);
inline const ScopeBase*get_parent() const { return parent_; }
inline const perm_string&name() const { return name_; }
void set_program_body(std::list<SequentialStmt*>*statements);
inline bool empty_program_body() const { return !statements_ || statements_->empty(); }
// Return true if the specification (name, types, ports) // Return true if the specification (name, types, ports)
// matches this subprogram and that subprogram. // matches this subprogram and that subprogram.
bool compare_specification(Subprogram*that) const; bool compare_specification(SubprogramHeader*that) const;
const InterfacePort*find_param(perm_string nam) const; const InterfacePort*find_param(perm_string nam) const;
const VType*peek_param_type(int idx) const; const VType*peek_param_type(int idx) const;
const VType*peek_return_type() const { return return_type_; } const VType*peek_return_type() const { return return_type_; }
int emit(ostream&out, Entity*ent, ScopeBase*scope); void set_parent(const ScopeBase*par);
inline const ScopeBase*get_parent() const { return parent_; }
// Emit a definition as it would show up in a package. // Checks if either return type or parameters are unbounded vectors.
int emit_package(std::ostream&fd) const; bool unbounded() const;
void write_to_stream(std::ostream&fd) const; inline SubprogramBody*body() { return body_; }
void write_to_stream_body(std::ostream&fd) const; void set_body(SubprogramBody*bdy);
void dump(std::ostream&fd) const;
inline perm_string name() { return name_; }
// Creates a new instance of the function that takes arguments of // Creates a new instance of the function that takes arguments of
// a different type. It is used to allow VHDL functions that work with // a different type. It is used to allow VHDL functions that work with
// unbounded std_logic_vectors, so there can be a separate instance // unbounded std_logic_vectors, so there can be a separate instance
// for limited length logic vector. // for limited length logic vector.
Subprogram*make_instance(std::vector<Expression*> arguments, ScopeBase*scope); SubprogramHeader*make_instance(std::vector<Expression*> arguments, ScopeBase*scope);
// Checks if either return type or parameters are unbounded vectors. // Emit header as it would show up in a package.
bool unbounded() const; int emit_package(std::ostream&fd) const;
void write_to_stream(std::ostream&fd) const;
void dump(std::ostream&fd) const;
private: private:
// Tries to set the return type to a fixed type. VHDL functions that // Tries to set the return type to a fixed type. VHDL functions that
@ -79,11 +103,13 @@ class Subprogram : public LineInfo, public ScopeBase {
// demands. // demands.
void fix_return_type(); void fix_return_type();
// Procedure/function name
perm_string name_; perm_string name_;
const ScopeBase*parent_;
std::list<InterfacePort*>*ports_; std::list<InterfacePort*>*ports_;
const VType*return_type_; const VType*return_type_;
std::list<SequentialStmt*>*statements_; SubprogramBody*body_;
const ScopeBase*parent_;
}; };
#endif /* IVL_subprogram_H */ #endif /* IVL_subprogram_H */

View File

@ -25,7 +25,30 @@
using namespace std; using namespace std;
int Subprogram::emit_package(ostream&fd) const int SubprogramBody::emit_package(ostream&fd) const
{
int errors = 0;
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
; cur != new_variables_.end() ; ++cur) {
// Workaround to enable reg_flag for variables
cur->second->count_ref_sequ();
errors += cur->second->emit(fd, NULL, NULL);
}
if (statements_) {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
errors += (*cur)->emit(fd, NULL, const_cast<SubprogramBody*>(this));
}
} else {
fd << " begin /* empty body */ end" << endl;
}
return errors;
}
int SubprogramHeader::emit_package(ostream&fd) const
{ {
int errors = 0; int errors = 0;
@ -63,21 +86,8 @@ int Subprogram::emit_package(ostream&fd) const
fd << ");" << endl; fd << ");" << endl;
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin() if (body_)
; cur != new_variables_.end() ; ++cur) { body_->emit_package(fd);
// Workaround to enable reg_flag for variables
cur->second->count_ref_sequ();
errors += cur->second->emit(fd, NULL, NULL);
}
if (statements_) {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
errors += (*cur)->emit(fd, NULL, const_cast<Subprogram*>(this));
}
} else {
fd << " begin /* empty body */ end" << endl;
}
if (return_type_) if (return_type_)
fd << "endfunction" << endl; fd << "endfunction" << endl;
@ -86,3 +96,23 @@ int Subprogram::emit_package(ostream&fd) const
return errors; return errors;
} }
int SubprogramHeader::emit_name(const std::vector<Expression*>&,
std::ostream&out, Entity*, ScopeBase*) const
{
out << "\\" << name_;
return 0;
}
int SubprogramHeader::emit_args(const std::vector<Expression*>&argv,
std::ostream&out, Entity*ent, ScopeBase*scope) const
{
int errors = 0;
for (size_t idx = 0; idx < argv.size() ; idx += 1) {
if (idx > 0) out << ", ";
errors += argv[idx]->emit(out, ent, scope);
}
return errors;
}